working ecmult

pull/11871/head
Pieter Wuille 12 years ago
parent cb4d29c81e
commit 7ba40aa4cd

@ -7,6 +7,9 @@
#include "group.h"
#include "scalar.h"
#define WINDOW_A 5
#define WINDOW_G 11
namespace secp256k1 {
template<typename G, int W> 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<GetSize(); i++) {
ss << Get(i);
ss << Get(used-1-i);
if (i != used-1)
ss << ',';
}
@ -90,7 +100,7 @@ public:
class ECMultConsts {
public:
const WNAFPrecomp<GroupElem,10> wpg;
const WNAFPrecomp<GroupElem,WINDOW_G> 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<GroupElemJac,5> wpa(a);
const WNAFPrecomp<GroupElem,10> &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<GroupElemJac,WINDOW_A> wpa(a);
const WNAFPrecomp<GroupElem,WINDOW_G> &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<size; i++) {
for (int i=size-1; 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);
}
}

@ -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 */

@ -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();
}
};

@ -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);
}

@ -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);
}
};
}

@ -1,19 +1,35 @@
#include <stdio.h>
#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;
}

Loading…
Cancel
Save