add signing
This commit is contained in:
parent
607884fc11
commit
0a07e62f6f
48
ecdsa.cpp
48
ecdsa.cpp
|
@ -40,7 +40,28 @@ bool Signature::Parse(const unsigned char *sig, int size) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Signature::RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) {
|
bool Signature::Serialize(unsigned char *sig, int *size) {
|
||||||
|
int lenR = (r.GetBits() + 7)/8;
|
||||||
|
if (lenR == 0 || r.CheckBit(lenR*8-1))
|
||||||
|
lenR++;
|
||||||
|
int lenS = (s.GetBits() + 7)/8;
|
||||||
|
if (lenS == 0 || s.CheckBit(lenS*8-1))
|
||||||
|
lenS++;
|
||||||
|
if (*size < 6+lenS+lenR)
|
||||||
|
return false;
|
||||||
|
*size = 6 + lenS + lenR;
|
||||||
|
sig[0] = 0x30;
|
||||||
|
sig[1] = 4 + lenS + lenR;
|
||||||
|
sig[2] = 0x02;
|
||||||
|
sig[3] = lenR;
|
||||||
|
r.GetBytes(sig+4, lenR);
|
||||||
|
sig[4+lenR] = 0x02;
|
||||||
|
sig[5+lenR] = lenS;
|
||||||
|
s.GetBytes(sig+6, lenS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Signature::RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) const {
|
||||||
const GroupConstants &c = GetGroupConst();
|
const GroupConstants &c = GetGroupConst();
|
||||||
|
|
||||||
if (r.IsNeg() || s.IsNeg())
|
if (r.IsNeg() || s.IsNeg())
|
||||||
|
@ -63,13 +84,36 @@ bool Signature::RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Signature::Verify(const GroupElemJac &pubkey, const Number &message) {
|
bool Signature::Verify(const GroupElemJac &pubkey, const Number &message) const {
|
||||||
Number r2;
|
Number r2;
|
||||||
if (!RecomputeR(r2, pubkey, message))
|
if (!RecomputeR(r2, pubkey, message))
|
||||||
return false;
|
return false;
|
||||||
return r2.Compare(r) == 0;
|
return r2.Compare(r) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Signature::Sign(const Number &seckey, const Number &message, const Number &nonce) {
|
||||||
|
const GroupConstants &c = GetGroupConst();
|
||||||
|
|
||||||
|
GroupElemJac rp;
|
||||||
|
ECMultBase(rp, nonce);
|
||||||
|
FieldElem rx;
|
||||||
|
rp.GetX(rx);
|
||||||
|
unsigned char b[32];
|
||||||
|
rx.GetBytes(b);
|
||||||
|
r.SetBytes(b, 32);
|
||||||
|
r.SetMod(r, c.order);
|
||||||
|
Number n;
|
||||||
|
n.SetModMul(r, seckey, c.order);
|
||||||
|
n.SetAdd(message, n);
|
||||||
|
s.SetModInverse(nonce, c.order);
|
||||||
|
s.SetModMul(s, n, c.order);
|
||||||
|
if (s.IsZero())
|
||||||
|
return false;
|
||||||
|
if (s.IsOdd())
|
||||||
|
s.SetSub(c.order, s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Signature::SetRS(const Number &rin, const Number &sin) {
|
void Signature::SetRS(const Number &rin, const Number &sin) {
|
||||||
r = rin;
|
r = rin;
|
||||||
s = sin;
|
s = sin;
|
||||||
|
|
6
ecdsa.h
6
ecdsa.h
|
@ -9,8 +9,10 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Parse(const unsigned char *sig, int size);
|
bool Parse(const unsigned char *sig, int size);
|
||||||
bool RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message);
|
bool Serialize(unsigned char *sig, int *size);
|
||||||
bool Verify(const GroupElemJac &pubkey, const Number &message);
|
bool RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) const;
|
||||||
|
bool Verify(const GroupElemJac &pubkey, const Number &message) const;
|
||||||
|
bool Sign(const Number &seckey, const Number &message, const Number &nonce);
|
||||||
void SetRS(const Number &rin, const Number &sin);
|
void SetRS(const Number &rin, const Number &sin);
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
};
|
};
|
||||||
|
|
26
ecmult.cpp
26
ecmult.cpp
|
@ -112,6 +112,8 @@ class ECMultConsts {
|
||||||
public:
|
public:
|
||||||
WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
||||||
WNAFPrecomp<GroupElem,WINDOW_G> wpg128;
|
WNAFPrecomp<GroupElem,WINDOW_G> wpg128;
|
||||||
|
GroupElem prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
|
||||||
|
GroupElem fin; // -(sum(prec[j][0], j=0..63))
|
||||||
|
|
||||||
ECMultConsts() {
|
ECMultConsts() {
|
||||||
const GroupElem &g = GetGroupConst().g;
|
const GroupElem &g = GetGroupConst().g;
|
||||||
|
@ -121,6 +123,20 @@ public:
|
||||||
GroupElem g128; g128.SetJac(g128j);
|
GroupElem g128; g128.SetJac(g128j);
|
||||||
wpg.Build(g);
|
wpg.Build(g);
|
||||||
wpg128.Build(g128);
|
wpg128.Build(g128);
|
||||||
|
GroupElemJac gg(g);
|
||||||
|
GroupElem ad(g);
|
||||||
|
GroupElemJac fn;
|
||||||
|
for (int j=0; j<64; j++) {
|
||||||
|
prec[j][0].SetJac(gg);
|
||||||
|
fn.SetAdd(fn, gg);
|
||||||
|
for (int i=1; i<16; i++) {
|
||||||
|
gg.SetAdd(gg, ad);
|
||||||
|
prec[j][i].SetJac(gg);
|
||||||
|
}
|
||||||
|
ad = prec[j][15];
|
||||||
|
}
|
||||||
|
fn.SetNeg(fn);
|
||||||
|
fin.SetJac(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,6 +145,16 @@ const ECMultConsts &GetECMultConsts() {
|
||||||
return ecmult_consts;
|
return ecmult_consts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ECMultBase(GroupElemJac &out, const Number &gn) {
|
||||||
|
Number n; n.SetNumber(gn);
|
||||||
|
const ECMultConsts &c = GetECMultConsts();
|
||||||
|
out.SetAffine(c.prec[0][n.ShiftLowBits(4)]);
|
||||||
|
for (int j=1; j<64; j++) {
|
||||||
|
out.SetAdd(out, c.prec[j][n.ShiftLowBits(4)]);
|
||||||
|
}
|
||||||
|
out.SetAdd(out, c.fin);
|
||||||
|
}
|
||||||
|
|
||||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
|
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
|
||||||
Number an1, an2;
|
Number an1, an2;
|
||||||
Number gn1, gn2;
|
Number gn1, gn2;
|
||||||
|
|
1
ecmult.h
1
ecmult.h
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
namespace secp256k1 {
|
namespace secp256k1 {
|
||||||
|
|
||||||
|
void ECMultBase(GroupElemJac &out, const Number &gn);
|
||||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn);
|
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,10 +47,17 @@ GroupElemJac::GroupElemJac(const FieldElem &xin, const FieldElem &yin) : GroupEl
|
||||||
|
|
||||||
GroupElemJac::GroupElemJac(const GroupElem &in) : GroupElem(in), z(1) {}
|
GroupElemJac::GroupElemJac(const GroupElem &in) : GroupElem(in), z(1) {}
|
||||||
|
|
||||||
void GroupElemJac::SetJac(GroupElemJac &jac) {
|
void GroupElemJac::SetJac(const GroupElemJac &jac) {
|
||||||
*this = jac;
|
*this = jac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupElemJac::SetAffine(const GroupElem &aff) {
|
||||||
|
fInfinity = aff.fInfinity;
|
||||||
|
x = aff.x;
|
||||||
|
y = aff.y;
|
||||||
|
z = FieldElem(1);
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupElemJac::IsValid() const {
|
bool GroupElemJac::IsValid() const {
|
||||||
if (IsInfinity())
|
if (IsInfinity())
|
||||||
return false;
|
return false;
|
||||||
|
|
4
group.h
4
group.h
|
@ -55,7 +55,9 @@ public:
|
||||||
|
|
||||||
GroupElemJac(const GroupElem &in);
|
GroupElemJac(const GroupElem &in);
|
||||||
|
|
||||||
void SetJac(GroupElemJac &jac);
|
void SetJac(const GroupElemJac &jac);
|
||||||
|
|
||||||
|
void SetAffine(const GroupElem &aff);
|
||||||
|
|
||||||
/** Checks whether this is a non-infinite point on the curve */
|
/** Checks whether this is a non-infinite point on the curve */
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
|
@ -58,6 +58,10 @@ void Number::SetBytes(const unsigned char *bin, unsigned int len) {
|
||||||
mpz_import(bn, len, 1, 1, 1, 0, bin);
|
mpz_import(bn, len, 1, 1, 1, 0, bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Number::CheckBit(int pos) const {
|
||||||
|
return mpz_tstbit(bn, pos);
|
||||||
|
}
|
||||||
|
|
||||||
void Number::GetBytes(unsigned char *bin, unsigned int len) {
|
void Number::GetBytes(unsigned char *bin, unsigned int len) {
|
||||||
unsigned int size = (mpz_sizeinbase(bn,2)+7)/8;
|
unsigned int size = (mpz_sizeinbase(bn,2)+7)/8;
|
||||||
assert(size <= len);
|
assert(size <= len);
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
bool IsZero() const;
|
bool IsZero() const;
|
||||||
bool IsOdd() const;
|
bool IsOdd() const;
|
||||||
bool IsNeg() const;
|
bool IsNeg() const;
|
||||||
|
bool CheckBit(int pos) const;
|
||||||
void Negate();
|
void Negate();
|
||||||
void Shift1();
|
void Shift1();
|
||||||
void Inc();
|
void Inc();
|
||||||
|
|
|
@ -138,6 +138,10 @@ bool Number::IsOdd() const {
|
||||||
return BN_is_odd((const BIGNUM*)*this);
|
return BN_is_odd((const BIGNUM*)*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Number::CheckBit(int pos) const {
|
||||||
|
return BN_is_bit_set((const BIGNUM*)*this, pos);
|
||||||
|
}
|
||||||
|
|
||||||
bool Number::IsNeg() const {
|
bool Number::IsNeg() const {
|
||||||
return BN_is_negative((const BIGNUM*)*this);
|
return BN_is_negative((const BIGNUM*)*this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
bool IsZero() const;
|
bool IsZero() const;
|
||||||
bool IsOdd() const;
|
bool IsOdd() const;
|
||||||
bool IsNeg() const;
|
bool IsNeg() const;
|
||||||
|
bool CheckBit(int pos) const;
|
||||||
void Negate();
|
void Negate();
|
||||||
void Shift1();
|
void Shift1();
|
||||||
void Inc();
|
void Inc();
|
||||||
|
|
|
@ -25,4 +25,5 @@ int VerifyECDSA(const unsigned char *msg, int msglen, const unsigned char *sig,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
22
tests.cpp
22
tests.cpp
|
@ -103,9 +103,31 @@ void test_run_wnaf() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_ecdsa_sign_verify() {
|
||||||
|
const GroupConstants &c = GetGroupConst();
|
||||||
|
Number msg; msg.SetPseudoRand(c.order);
|
||||||
|
Number key; key.SetPseudoRand(c.order);
|
||||||
|
Number nonce;
|
||||||
|
GroupElemJac pub; ECMultBase(pub, key);
|
||||||
|
Signature sig;
|
||||||
|
do {
|
||||||
|
nonce.SetPseudoRand(c.order);
|
||||||
|
} while(!sig.Sign(key, msg, nonce));
|
||||||
|
assert(sig.Verify(pub, msg));
|
||||||
|
msg.Inc();
|
||||||
|
assert(!sig.Verify(pub, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_run_ecdsa_sign_verify() {
|
||||||
|
for (int i=0; i<1000; i++) {
|
||||||
|
test_ecdsa_sign_verify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
test_run_wnaf();
|
test_run_wnaf();
|
||||||
test_run_point_times_order();
|
test_run_point_times_order();
|
||||||
test_run_ecmult_chain();
|
test_run_ecmult_chain();
|
||||||
|
test_run_ecdsa_sign_verify();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue