diff --git a/ecmult.h b/ecmult.h index 663ab1073f8..f97efa0e329 100644 --- a/ecmult.h +++ b/ecmult.h @@ -7,6 +7,9 @@ #include "group.h" #include "scalar.h" +#define WINDOW_A 5 +#define WINDOW_G 11 + namespace secp256k1 { template class WNAFPrecomp { @@ -16,11 +19,14 @@ private: public: WNAFPrecomp(const G &base) { pre[0] = base; - GroupElemJac x = base; + GroupElemJac x(base); +// printf("base=%s x=%s\n", base.ToString().c_str(), x.ToString().c_str()); GroupElemJac d; d.SetDouble(x); +// printf("d=%s\n", d.ToString().c_str()); for (int i=1; i<(1 << (W-2)); i++) { x.SetAdd(d,pre[i-1]); pre[i].SetJac(x); +// printf("precomp %s*%i = %s\n", base.ToString().c_str(), i*2 +1, pre[i].ToString().c_str()); } } @@ -31,7 +37,7 @@ public: if (exp > 0) { out = pre[(exp-1)/2]; } else { - out.SetNeg(pre[(1-exp)/2]); + out.SetNeg(pre[(-exp-1)/2]); } } }; @@ -49,16 +55,19 @@ private: } public: - WNAF(Context &ctx, Scalar &exp, int w) : used(0) { + WNAF(Context &ctx, const Scalar &exp, int w) : used(0) { int zeroes = 0; - while (!exp.IsZero()) { - while (!exp.IsOdd()) { + Context ct(ctx); + Scalar x(ct); + x.SetNumber(exp); + while (!x.IsZero()) { + while (!x.IsOdd()) { zeroes++; - exp.Shift1(); + x.Shift1(); } - int word = exp.ShiftLowBits(ctx,w); + int word = x.ShiftLowBits(ctx,w); if (word & (1 << (w-1))) { - exp.Inc(); + x.Inc(); PushNAF(word - (1 << w), zeroes); } else { PushNAF(word, zeroes); @@ -72,14 +81,15 @@ public: } int Get(int pos) const { - return naf[used-1-pos]; + assert(pos >= 0 && pos < used); + return naf[pos]; } std::string ToString() { std::stringstream ss; ss << "("; for (int i=0; i wpg; + const WNAFPrecomp wpg; ECMultConsts() : wpg(GetGroupConst().g) {} }; @@ -100,28 +110,29 @@ const ECMultConsts &GetECMultConsts() { return ecmult_consts; } -void ECMult(Context &ctx, GroupElemJac &out, GroupElemJac &a, Scalar &an, Scalar &gn) { - WNAF<256> wa(ctx, an, 5); - WNAF<256> wg(ctx, gn, 10); - WNAFPrecomp wpa(a); - const WNAFPrecomp &wpg = GetECMultConsts().wpg; +void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Scalar &an, Scalar &gn) { + WNAF<256> wa(ctx, an, WINDOW_A); + WNAF<256> wg(ctx, gn, WINDOW_G); + WNAFPrecomp wpa(a); + const WNAFPrecomp &wpg = GetECMultConsts().wpg; - int size = std::max(wa.GetSize(), wg.GetSize()); + int size_a = wa.GetSize(); + int size_g = wg.GetSize(); + int size = std::max(size_a, size_g); out = GroupElemJac(); GroupElemJac tmpj; GroupElem tmpa; - for (int i=0; i=0; i--) { out.SetDouble(out); - int anw = wa.Get(i); - if (anw) { - wpa.Get(tmpj, anw); + int nw; + if (i < size_a && (nw = wa.Get(i))) { + wpa.Get(tmpj, nw); out.SetAdd(out, tmpj); } - int gnw = wg.Get(i); - if (gnw) { - wpg.Get(tmpa, gnw); + if (i < size_g && (nw = wg.Get(i))) { + wpg.Get(tmpa, nw); out.SetAdd(out, tmpa); } } diff --git a/field.h b/field.h index 4c973736a9a..2d0dec532d5 100644 --- a/field.h +++ b/field.h @@ -87,13 +87,13 @@ public: bool IsZero() { Normalize(); - return n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0; + return (n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0); } bool friend operator==(FieldElem &a, FieldElem &b) { a.Normalize(); b.Normalize(); - return a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]; + return (a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]); } /** extract as 32-byte big endian array */ diff --git a/group.h b/group.h index de49f49cc01..fa76a72bebf 100644 --- a/group.h +++ b/group.h @@ -39,10 +39,11 @@ public: y.SetNeg(y, 1); } - std::string ToString() { + std::string ToString() const { if (fInfinity) return "(inf)"; - return "(" + x.ToString() + "," + y.ToString() + ")"; + FieldElem xc = x, yc = y; + return "(" + xc.ToString() + "," + yc.ToString() + ")"; } void SetJac(GroupElemJac &jac); @@ -51,7 +52,7 @@ public: }; /** Represents a point on the secp256k1 curve, with jacobian coordinates */ -class GroupElemJac : public GroupElem { +class GroupElemJac : private GroupElem { protected: FieldElem z; @@ -95,7 +96,7 @@ public: x.SetMult(x,z2); y.SetMult(y,z3); z = FieldElem(1); - aff.fInfinity = false; + aff.fInfinity = fInfinity; aff.x = x; aff.y = y; } @@ -122,18 +123,19 @@ public: /** Sets this point to be the EC double of another */ void SetDouble(const GroupElemJac &p) { - if (p.fInfinity || y.IsZero()) { + FieldElem t5 = p.y; + if (p.fInfinity || t5.IsZero()) { fInfinity = true; return; } - FieldElem t1,t2,t3,t4,t5; - z.SetMult(p.y,p.z); + FieldElem t1,t2,t3,t4; + z.SetMult(t5,p.z); z *= 2; // Z' = 2*Y*Z (2) t1.SetSquare(p.x); t1 *= 3; // T1 = 3*X^2 (3) t2.SetSquare(t1); // T2 = 9*X^4 (1) - t3.SetSquare(p.y); + t3.SetSquare(t5); t3 *= 2; // T3 = 2*Y^2 (2) t4.SetSquare(t3); t4 *= 2; // T4 = 8*Y^4 (2) @@ -148,6 +150,7 @@ public: y.SetMult(t1,t3); // Y' = 36*X^3*Y^2 - 27*X^6 (1) t2.SetNeg(t4,2); // T2 = -8*Y^4 (3) y += t2; // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) + fInfinity = false; } /** Sets this point to be the EC addition of two others */ @@ -230,9 +233,10 @@ public: y += h3; } - std::string ToString() { + std::string ToString() const { + GroupElemJac cop = *this; GroupElem aff; - GetAffine(aff); + cop.GetAffine(aff); return aff.ToString(); } }; diff --git a/num.h b/num.h index ce12cb8c1b3..87ef1d7034c 100644 --- a/num.h +++ b/num.h @@ -56,6 +56,9 @@ public: Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) { SetBytes(bin,len); } + void SetNumber(const Number &x) { + BN_copy(bn, x.bn); + } void SetBytes(const unsigned char *bin, int len) { BN_bin2bn(bin, len, bn); } @@ -68,6 +71,9 @@ 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); + } int GetBits() const { return BN_num_bits(bn); } diff --git a/scalar.h b/scalar.h index 494a98d1b44..47ef5879136 100644 --- a/scalar.h +++ b/scalar.h @@ -2,6 +2,7 @@ #define _SECP256K1_SCALAR_ #include "num.h" +#include "group.h" namespace secp256k1 { /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141, @@ -10,6 +11,11 @@ namespace secp256k1 { class Scalar : public Number { public: Scalar(Context &ctx) : Number(ctx) {} + + void Multiply(Context &ctx, const Scalar &f) { + const GroupConstants &c = GetGroupConst(); + SetModMul(ctx, f, c.order); + } }; } diff --git a/secp256k1.cpp b/secp256k1.cpp index f7e7ebc4421..5bee7470729 100644 --- a/secp256k1.cpp +++ b/secp256k1.cpp @@ -1,19 +1,35 @@ #include #include "num.h" -#include "scalar.h" #include "field.h" #include "group.h" +#include "scalar.h" #include "ecmult.h" using namespace secp256k1; int main() { Context ctx; - Scalar scal(ctx); - scal.SetHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - printf("scal=%s\n", scal.ToString().c_str()); - WNAF<256> w(ctx, scal, 5); - printf("wnaf=%s\n", w.ToString().c_str()); + FieldElem x,y; + x.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004"); + y.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f"); + GroupElemJac a(x,y); + printf("a=%s\n", a.ToString().c_str()); + Scalar an(ctx); + an.SetHex("8b30bce9ad2a890696b23f671709eff3727fd8cc04d3362c6c7bf458f2846fff"); + Scalar af(ctx); + af.SetHex("1337"); + printf("an=%s\n", an.ToString().c_str()); + Scalar gn(ctx); + gn.SetHex("f557be925d4b65381409fdf30514750f1eb4343a91216a4f71163cb35f2f6e0e"); + Scalar gf(ctx); + gf.SetHex("2113"); + printf("gn=%s\n", gn.ToString().c_str()); + for (int i=0; i<50000; i++) { + ECMult(ctx, a, a, an, gn); + an.Multiply(ctx, af); + gn.Multiply(ctx, gf); + } + printf("%s\n", a.ToString().c_str()); return 0; }