diff --git a/ecdsa.h b/ecdsa.h new file mode 100644 index 0000000..7a309a0 --- /dev/null +++ b/ecdsa.h @@ -0,0 +1,55 @@ +#ifndef _SECP256K1_ECDSA_ +#define _SECP256K1_ECDSA_ + +namespace secp256k1 { + +bool ParsePubkey(GroupElemJac &elem, const unsigned char *pub, int size) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + FieldElem x; + x.SetBytes(pub+1); + elem.SetCompressed(x, pub[0] == 0x03); + } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { + FieldElem x,y; + x.SetBytes(pub+1); + y.SetBytes(pub+33); + elem = GroupElem(x,y); + if ((pub[0] == 0x06 || pub[0] == 0x07) && y.IsOdd() != (pub[0] == 0x07)) + return false; + } else { + return false; + } + return elem.IsValid(); +} + +class Signature { +private: + Number r,s; + +public: + bool Verify(Context &ctx, const GroupElemJac &pubkey, const Number &message) { + const GroupConstants &c = GetGroupConst(); + + if (r.IsNeg() || s.IsNeg()) + return false; + if (r.IsZero() || s.IsZero()) + return false; + if (r.Compare(c.order) >= 0 || s.Compare(c.order) >= 0) + return false; + + Context ct(ctx); + Number sn(ct); sn.SetModInverse(ct, s, c.order); + Number u1(ct); u1.SetModMul(ct, sn, message, c.order); + Number u2(ct); u2.SetModMul(ct, sn, r, c.order); + GroupElemJac pr; ECMult(ct, pr, pubkey, u2, u1); + if (pr.IsInfinity()) + return false; + FieldElem xr; pr.GetX(xr); + unsigned char xrb[32]; xr.GetBytes(xrb); + Number xrn(ct); xrn.SetBytes(xrb,32); xrn.SetMod(ct,xrn,c.order); + return xrn.Compare(r) == 0; + } +}; + +} + +#endif diff --git a/group.h b/group.h index 880ac3e..b9b0837 100644 --- a/group.h +++ b/group.h @@ -39,6 +39,14 @@ public: y.SetNeg(y, 1); } + void GetX(FieldElem &xout) const { + xout = x; + } + + void GetY(FieldElem &yout) const { + yout = y; + } + std::string ToString() const { if (fInfinity) return "(inf)"; @@ -101,6 +109,24 @@ public: aff.y = y; } + void GetX(FieldElem &xout) { + FieldElem zi; + zi.SetInverse(z); + zi.SetSquare(zi); + xout.SetMult(x, zi); + } + + bool IsInfinity() const { + return fInfinity; + } + + void GetY(FieldElem &yout) { + FieldElem zi; + zi.SetInverse(z); + FieldElem zi3; zi3.SetSquare(zi); zi3.SetMult(zi, zi3); + yout.SetMult(y, zi3); + } + void SetNeg(const GroupElemJac &p) { *this = p; y.Normalize(); diff --git a/num.h b/num.h index bff7f16..78e5a62 100644 --- a/num.h +++ b/num.h @@ -71,8 +71,8 @@ public: void SetModInverse(Context &ctx, const Number &x, const Number &m) { BN_mod_inverse(bn, x.bn, m.bn, ctx); } - void SetModMul(Context &ctx, const Number &f, const Number &m) { - BN_mod_mul(bn, bn, f.bn, m.bn, ctx); + void SetModMul(Context &ctx, const Number &a, const Number &b, const Number &m) { + BN_mod_mul(bn, a.bn, b.bn, m.bn, ctx); } void SetAdd(Context &ctx, const Number &a1, const Number &a2) { BN_add(bn, a1.bn, a2.bn); @@ -86,6 +86,12 @@ public: void SetDiv(Context &ctx, const Number &a1, const Number &a2) { BN_div(bn, NULL, a1.bn, a2.bn, ctx); } + void SetMod(Context &ctx, const Number &a, const Number &m) { + BN_nnmod(bn, m.bn, a.bn, ctx); + } + int Compare(const Number &a) { + return BN_cmp(bn, a.bn); + } int GetBits() const { return BN_num_bits(bn); } @@ -99,7 +105,7 @@ public: BN_rshift(bn, bn, bits); return ret; } - // check whether number is 0 + // check whether number is 0, bool IsZero() { return BN_is_zero(bn); } diff --git a/secp256k1.cpp b/secp256k1.cpp index 5965c2b..f7ad1dd 100644 --- a/secp256k1.cpp +++ b/secp256k1.cpp @@ -4,6 +4,7 @@ #include "field.h" #include "group.h" #include "ecmult.h" +#include "ecdsa.h" using namespace secp256k1;