mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-15 20:30:17 +01:00
working ecmult
This commit is contained in:
parent
cb4d29c81e
commit
7ba40aa4cd
6 changed files with 85 additions and 42 deletions
59
ecmult.h
59
ecmult.h
|
@ -7,6 +7,9 @@
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
|
|
||||||
|
#define WINDOW_A 5
|
||||||
|
#define WINDOW_G 11
|
||||||
|
|
||||||
namespace secp256k1 {
|
namespace secp256k1 {
|
||||||
|
|
||||||
template<typename G, int W> class WNAFPrecomp {
|
template<typename G, int W> class WNAFPrecomp {
|
||||||
|
@ -16,11 +19,14 @@ private:
|
||||||
public:
|
public:
|
||||||
WNAFPrecomp(const G &base) {
|
WNAFPrecomp(const G &base) {
|
||||||
pre[0] = 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);
|
GroupElemJac d; d.SetDouble(x);
|
||||||
|
// printf("d=%s\n", d.ToString().c_str());
|
||||||
for (int i=1; i<(1 << (W-2)); i++) {
|
for (int i=1; i<(1 << (W-2)); i++) {
|
||||||
x.SetAdd(d,pre[i-1]);
|
x.SetAdd(d,pre[i-1]);
|
||||||
pre[i].SetJac(x);
|
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) {
|
if (exp > 0) {
|
||||||
out = pre[(exp-1)/2];
|
out = pre[(exp-1)/2];
|
||||||
} else {
|
} else {
|
||||||
out.SetNeg(pre[(1-exp)/2]);
|
out.SetNeg(pre[(-exp-1)/2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -49,16 +55,19 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WNAF(Context &ctx, Scalar &exp, int w) : used(0) {
|
WNAF(Context &ctx, const Scalar &exp, int w) : used(0) {
|
||||||
int zeroes = 0;
|
int zeroes = 0;
|
||||||
while (!exp.IsZero()) {
|
Context ct(ctx);
|
||||||
while (!exp.IsOdd()) {
|
Scalar x(ct);
|
||||||
|
x.SetNumber(exp);
|
||||||
|
while (!x.IsZero()) {
|
||||||
|
while (!x.IsOdd()) {
|
||||||
zeroes++;
|
zeroes++;
|
||||||
exp.Shift1();
|
x.Shift1();
|
||||||
}
|
}
|
||||||
int word = exp.ShiftLowBits(ctx,w);
|
int word = x.ShiftLowBits(ctx,w);
|
||||||
if (word & (1 << (w-1))) {
|
if (word & (1 << (w-1))) {
|
||||||
exp.Inc();
|
x.Inc();
|
||||||
PushNAF(word - (1 << w), zeroes);
|
PushNAF(word - (1 << w), zeroes);
|
||||||
} else {
|
} else {
|
||||||
PushNAF(word, zeroes);
|
PushNAF(word, zeroes);
|
||||||
|
@ -72,14 +81,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int Get(int pos) const {
|
int Get(int pos) const {
|
||||||
return naf[used-1-pos];
|
assert(pos >= 0 && pos < used);
|
||||||
|
return naf[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() {
|
std::string ToString() {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "(";
|
ss << "(";
|
||||||
for (int i=0; i<GetSize(); i++) {
|
for (int i=0; i<GetSize(); i++) {
|
||||||
ss << Get(i);
|
ss << Get(used-1-i);
|
||||||
if (i != used-1)
|
if (i != used-1)
|
||||||
ss << ',';
|
ss << ',';
|
||||||
}
|
}
|
||||||
|
@ -90,7 +100,7 @@ public:
|
||||||
|
|
||||||
class ECMultConsts {
|
class ECMultConsts {
|
||||||
public:
|
public:
|
||||||
const WNAFPrecomp<GroupElem,10> wpg;
|
const WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
||||||
|
|
||||||
ECMultConsts() : wpg(GetGroupConst().g) {}
|
ECMultConsts() : wpg(GetGroupConst().g) {}
|
||||||
};
|
};
|
||||||
|
@ -100,28 +110,29 @@ const ECMultConsts &GetECMultConsts() {
|
||||||
return ecmult_consts;
|
return ecmult_consts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECMult(Context &ctx, GroupElemJac &out, GroupElemJac &a, Scalar &an, Scalar &gn) {
|
void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Scalar &an, Scalar &gn) {
|
||||||
WNAF<256> wa(ctx, an, 5);
|
WNAF<256> wa(ctx, an, WINDOW_A);
|
||||||
WNAF<256> wg(ctx, gn, 10);
|
WNAF<256> wg(ctx, gn, WINDOW_G);
|
||||||
WNAFPrecomp<GroupElemJac,5> wpa(a);
|
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa(a);
|
||||||
const WNAFPrecomp<GroupElem,10> &wpg = GetECMultConsts().wpg;
|
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();
|
out = GroupElemJac();
|
||||||
GroupElemJac tmpj;
|
GroupElemJac tmpj;
|
||||||
GroupElem tmpa;
|
GroupElem tmpa;
|
||||||
|
|
||||||
for (int i=0; i<size; i++) {
|
for (int i=size-1; i>=0; i--) {
|
||||||
out.SetDouble(out);
|
out.SetDouble(out);
|
||||||
int anw = wa.Get(i);
|
int nw;
|
||||||
if (anw) {
|
if (i < size_a && (nw = wa.Get(i))) {
|
||||||
wpa.Get(tmpj, anw);
|
wpa.Get(tmpj, nw);
|
||||||
out.SetAdd(out, tmpj);
|
out.SetAdd(out, tmpj);
|
||||||
}
|
}
|
||||||
int gnw = wg.Get(i);
|
if (i < size_g && (nw = wg.Get(i))) {
|
||||||
if (gnw) {
|
wpg.Get(tmpa, nw);
|
||||||
wpg.Get(tmpa, gnw);
|
|
||||||
out.SetAdd(out, tmpa);
|
out.SetAdd(out, tmpa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
field.h
4
field.h
|
@ -87,13 +87,13 @@ public:
|
||||||
|
|
||||||
bool IsZero() {
|
bool IsZero() {
|
||||||
Normalize();
|
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) {
|
bool friend operator==(FieldElem &a, FieldElem &b) {
|
||||||
a.Normalize();
|
a.Normalize();
|
||||||
b.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 */
|
/** extract as 32-byte big endian array */
|
||||||
|
|
24
group.h
24
group.h
|
@ -39,10 +39,11 @@ public:
|
||||||
y.SetNeg(y, 1);
|
y.SetNeg(y, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() {
|
std::string ToString() const {
|
||||||
if (fInfinity)
|
if (fInfinity)
|
||||||
return "(inf)";
|
return "(inf)";
|
||||||
return "(" + x.ToString() + "," + y.ToString() + ")";
|
FieldElem xc = x, yc = y;
|
||||||
|
return "(" + xc.ToString() + "," + yc.ToString() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetJac(GroupElemJac &jac);
|
void SetJac(GroupElemJac &jac);
|
||||||
|
@ -51,7 +52,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Represents a point on the secp256k1 curve, with jacobian coordinates */
|
/** Represents a point on the secp256k1 curve, with jacobian coordinates */
|
||||||
class GroupElemJac : public GroupElem {
|
class GroupElemJac : private GroupElem {
|
||||||
protected:
|
protected:
|
||||||
FieldElem z;
|
FieldElem z;
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ public:
|
||||||
x.SetMult(x,z2);
|
x.SetMult(x,z2);
|
||||||
y.SetMult(y,z3);
|
y.SetMult(y,z3);
|
||||||
z = FieldElem(1);
|
z = FieldElem(1);
|
||||||
aff.fInfinity = false;
|
aff.fInfinity = fInfinity;
|
||||||
aff.x = x;
|
aff.x = x;
|
||||||
aff.y = y;
|
aff.y = y;
|
||||||
}
|
}
|
||||||
|
@ -122,18 +123,19 @@ public:
|
||||||
|
|
||||||
/** Sets this point to be the EC double of another */
|
/** Sets this point to be the EC double of another */
|
||||||
void SetDouble(const GroupElemJac &p) {
|
void SetDouble(const GroupElemJac &p) {
|
||||||
if (p.fInfinity || y.IsZero()) {
|
FieldElem t5 = p.y;
|
||||||
|
if (p.fInfinity || t5.IsZero()) {
|
||||||
fInfinity = true;
|
fInfinity = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldElem t1,t2,t3,t4,t5;
|
FieldElem t1,t2,t3,t4;
|
||||||
z.SetMult(p.y,p.z);
|
z.SetMult(t5,p.z);
|
||||||
z *= 2; // Z' = 2*Y*Z (2)
|
z *= 2; // Z' = 2*Y*Z (2)
|
||||||
t1.SetSquare(p.x);
|
t1.SetSquare(p.x);
|
||||||
t1 *= 3; // T1 = 3*X^2 (3)
|
t1 *= 3; // T1 = 3*X^2 (3)
|
||||||
t2.SetSquare(t1); // T2 = 9*X^4 (1)
|
t2.SetSquare(t1); // T2 = 9*X^4 (1)
|
||||||
t3.SetSquare(p.y);
|
t3.SetSquare(t5);
|
||||||
t3 *= 2; // T3 = 2*Y^2 (2)
|
t3 *= 2; // T3 = 2*Y^2 (2)
|
||||||
t4.SetSquare(t3);
|
t4.SetSquare(t3);
|
||||||
t4 *= 2; // T4 = 8*Y^4 (2)
|
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)
|
y.SetMult(t1,t3); // Y' = 36*X^3*Y^2 - 27*X^6 (1)
|
||||||
t2.SetNeg(t4,2); // T2 = -8*Y^4 (3)
|
t2.SetNeg(t4,2); // T2 = -8*Y^4 (3)
|
||||||
y += t2; // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4)
|
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 */
|
/** Sets this point to be the EC addition of two others */
|
||||||
|
@ -230,9 +233,10 @@ public:
|
||||||
y += h3;
|
y += h3;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() {
|
std::string ToString() const {
|
||||||
|
GroupElemJac cop = *this;
|
||||||
GroupElem aff;
|
GroupElem aff;
|
||||||
GetAffine(aff);
|
cop.GetAffine(aff);
|
||||||
return aff.ToString();
|
return aff.ToString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
6
num.h
6
num.h
|
@ -56,6 +56,9 @@ public:
|
||||||
Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) {
|
Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) {
|
||||||
SetBytes(bin,len);
|
SetBytes(bin,len);
|
||||||
}
|
}
|
||||||
|
void SetNumber(const Number &x) {
|
||||||
|
BN_copy(bn, x.bn);
|
||||||
|
}
|
||||||
void SetBytes(const unsigned char *bin, int len) {
|
void SetBytes(const unsigned char *bin, int len) {
|
||||||
BN_bin2bn(bin, len, bn);
|
BN_bin2bn(bin, len, bn);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +71,9 @@ public:
|
||||||
void SetModInverse(Context &ctx, const Number &x, const Number &m) {
|
void SetModInverse(Context &ctx, const Number &x, const Number &m) {
|
||||||
BN_mod_inverse(bn, x.bn, m.bn, ctx);
|
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 {
|
int GetBits() const {
|
||||||
return BN_num_bits(bn);
|
return BN_num_bits(bn);
|
||||||
}
|
}
|
||||||
|
|
6
scalar.h
6
scalar.h
|
@ -2,6 +2,7 @@
|
||||||
#define _SECP256K1_SCALAR_
|
#define _SECP256K1_SCALAR_
|
||||||
|
|
||||||
#include "num.h"
|
#include "num.h"
|
||||||
|
#include "group.h"
|
||||||
|
|
||||||
namespace secp256k1 {
|
namespace secp256k1 {
|
||||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141,
|
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141,
|
||||||
|
@ -10,6 +11,11 @@ namespace secp256k1 {
|
||||||
class Scalar : public Number {
|
class Scalar : public Number {
|
||||||
public:
|
public:
|
||||||
Scalar(Context &ctx) : Number(ctx) {}
|
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 <stdio.h>
|
||||||
|
|
||||||
#include "num.h"
|
#include "num.h"
|
||||||
#include "scalar.h"
|
|
||||||
#include "field.h"
|
#include "field.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
#include "scalar.h"
|
||||||
#include "ecmult.h"
|
#include "ecmult.h"
|
||||||
|
|
||||||
using namespace secp256k1;
|
using namespace secp256k1;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Context ctx;
|
Context ctx;
|
||||||
Scalar scal(ctx);
|
FieldElem x,y;
|
||||||
scal.SetHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
x.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004");
|
||||||
printf("scal=%s\n", scal.ToString().c_str());
|
y.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||||
WNAF<256> w(ctx, scal, 5);
|
GroupElemJac a(x,y);
|
||||||
printf("wnaf=%s\n", w.ToString().c_str());
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue