Browse Source

remove Context interface... it doesn't help much

master
Pieter Wuille 10 years ago
parent
commit
d5f62719de
  1. 33
      ecdsa.h
  2. 45
      ecmult.h
  3. 14
      field.h
  4. 73
      group.h
  5. 31
      num_gmp.h
  6. 145
      num_openssl.h
  7. 49
      tests.cpp

33
ecdsa.h

@ -26,8 +26,6 @@ private: @@ -26,8 +26,6 @@ private:
Number r,s;
public:
Signature(Context &ctx) : r(ctx), s(ctx) {}
bool Parse(const unsigned char *sig, int size) {
if (sig[0] != 0x30) return false;
int lenr = sig[3];
@ -44,7 +42,7 @@ public: @@ -44,7 +42,7 @@ public:
return true;
}
bool RecomputeR(Context &ctx, Number &r2, const GroupElemJac &pubkey, const Number &message) {
bool RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) {
const GroupConstants &c = GetGroupConst();
if (r.IsNeg() || s.IsNeg())
@ -54,24 +52,22 @@ public: @@ -54,24 +52,22 @@ public:
if (r.Compare(c.order) >= 0 || s.Compare(c.order) >= 0)
return false;
Context ct(ctx);
Number sn(ct), u1(ct), u2(ct);
sn.SetModInverse(ct, s, c.order);
u1.SetModMul(ct, sn, message, c.order);
u2.SetModMul(ct, sn, r, c.order);
GroupElemJac pr; ECMult(ct, pr, pubkey, u2, u1);
Number sn, u1, u2;
sn.SetModInverse(s, c.order);
u1.SetModMul(sn, message, c.order);
u2.SetModMul(sn, r, c.order);
GroupElemJac pr; ECMult(pr, pubkey, u2, u1);
if (pr.IsInfinity())
return false;
FieldElem xr; pr.GetX(ct, xr);
FieldElem xr; pr.GetX(xr);
unsigned char xrb[32]; xr.GetBytes(xrb);
r2.SetBytes(xrb,32); r2.SetMod(ct,r2,c.order);
r2.SetBytes(xrb,32); r2.SetMod(r2,c.order);
return true;
}
bool Verify(Context &ctx, const GroupElemJac &pubkey, const Number &message) {
Context ct(ctx);
Number r2(ct);
if (!RecomputeR(ct, r2, pubkey, message))
bool Verify(const GroupElemJac &pubkey, const Number &message) {
Number r2;
if (!RecomputeR(r2, pubkey, message))
return false;
return r2.Compare(r) == 0;
}
@ -87,9 +83,8 @@ public: @@ -87,9 +83,8 @@ public:
};
int VerifyECDSA(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
Context ctx;
Number m(ctx);
Signature s(ctx);
Number m;
Signature s;
GroupElemJac q;
m.SetBytes(msg, msglen);
if (!ParsePubKey(q, pubkey, pubkeylen))
@ -101,7 +96,7 @@ int VerifyECDSA(const unsigned char *msg, int msglen, const unsigned char *sig, @@ -101,7 +96,7 @@ int VerifyECDSA(const unsigned char *msg, int msglen, const unsigned char *sig,
return -2;
}
// fprintf(stderr, "Verifying ECDSA: msg=%s pubkey=%s sig=%s\n", m.ToString().c_str(), q.ToString().c_str(), s.ToString().c_str());
if (!s.Verify(ctx, q, m))
if (!s.Verify(q, m))
return 0;
return 1;
}

45
ecmult.h

@ -23,18 +23,18 @@ private: @@ -23,18 +23,18 @@ private:
public:
WNAFPrecomp() {}
void Build(Context &ctx, const G &base) {
void Build(const G &base) {
pre[0] = base;
GroupElemJac x(base);
GroupElemJac d; d.SetDouble(x);
for (int i=1; i<(1 << (W-2)); i++) {
x.SetAdd(d,pre[i-1]);
pre[i].SetJac(ctx, x);
pre[i].SetJac(x);
}
}
WNAFPrecomp(Context &ctx, const G &base) {
Build(ctx, base);
WNAFPrecomp(const G &base) {
Build(base);
}
void Get(G &out, int exp) const {
@ -63,10 +63,9 @@ private: @@ -63,10 +63,9 @@ private:
}
public:
WNAF(Context &ctx, const Number &exp, int w) : used(0) {
WNAF(const Number &exp, int w) : used(0) {
int zeroes = 0;
Context ct(ctx);
Number x(ct);
Number x;
x.SetNumber(exp);
int sign = 1;
if (x.IsNeg()) {
@ -78,7 +77,7 @@ public: @@ -78,7 +77,7 @@ public:
zeroes++;
x.Shift1();
}
int word = x.ShiftLowBits(ct,w);
int word = x.ShiftLowBits(w);
if (word & (1 << (w-1))) {
x.Inc();
PushNAF(sign * (word - (1 << w)), zeroes);
@ -117,14 +116,13 @@ public: @@ -117,14 +116,13 @@ public:
WNAFPrecomp<GroupElem,WINDOW_G> wpg128;
ECMultConsts() {
Context ctx;
const GroupElem &g = GetGroupConst().g;
GroupElemJac g128j(g);
for (int i=0; i<128; i++)
g128j.SetDouble(g128j);
GroupElem g128; g128.SetJac(ctx, g128j);
wpg.Build(ctx, g);
wpg128.Build(ctx, g128);
GroupElem g128; g128.SetJac(g128j);
wpg.Build(g);
wpg128.Build(g128);
}
};
@ -133,26 +131,25 @@ const ECMultConsts &GetECMultConsts() { @@ -133,26 +131,25 @@ const ECMultConsts &GetECMultConsts() {
return ecmult_consts;
}
void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
Context ct(ctx);
Number an1(ct), an2(ct);
Number gn1(ct), gn2(ct);
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
Number an1, an2;
Number gn1, gn2;
SplitExp(ct, an, an1, an2);
SplitExp(an, an1, an2);
// printf("an=%s\n", an.ToString().c_str());
// printf("an1=%s\n", an1.ToString().c_str());
// printf("an2=%s\n", an2.ToString().c_str());
// printf("an1.len=%i\n", an1.GetBits());
// printf("an2.len=%i\n", an2.GetBits());
gn.SplitInto(ct, 128, gn1, gn2);
gn.SplitInto(128, gn1, gn2);
WNAF<128> wa1(ct, an1, WINDOW_A);
WNAF<128> wa2(ct, an2, WINDOW_A);
WNAF<128> wg1(ct, gn1, WINDOW_G);
WNAF<128> wg2(ct, gn2, WINDOW_G);
WNAF<128> wa1(an1, WINDOW_A);
WNAF<128> wa2(an2, WINDOW_A);
WNAF<128> wg1(gn1, WINDOW_G);
WNAF<128> wg2(gn2, WINDOW_G);
GroupElemJac a2; a2.SetMulLambda(a);
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa1(ct, a);
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa2(ct, a2);
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa1(a);
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa2(a2);
const ECMultConsts &c = GetECMultConsts();
int size_a1 = wa1.GetSize();

14
field.h

@ -308,7 +308,7 @@ public: @@ -308,7 +308,7 @@ public:
}
/** Set this to be the (modular) inverse of another FieldElem. Magnitude=1 */
void SetInverse(Context &ctx, FieldElem &a);
void SetInverse(FieldElem &a);
std::string ToString() {
unsigned char tmp[32];
@ -354,13 +354,10 @@ static const unsigned char field_p_[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF @@ -354,13 +354,10 @@ static const unsigned char field_p_[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F};
class FieldConstants {
private:
Context ctx;
public:
const Number field_p;
FieldConstants() : field_p(ctx, field_p_, sizeof(field_p_)) {}
FieldConstants() : field_p(field_p_, sizeof(field_p_)) {}
};
const FieldConstants &GetFieldConst() {
@ -368,7 +365,7 @@ const FieldConstants &GetFieldConst() { @@ -368,7 +365,7 @@ const FieldConstants &GetFieldConst() {
return field_const;
}
void FieldElem::SetInverse(Context &ctx, FieldElem &a) {
void FieldElem::SetInverse(FieldElem &a) {
#if defined(USE_FIELDINVERSE_BUILTIN)
// calculate a^p, with p={45,63,1019,1023}
FieldElem a2; a2.SetSquare(a);
@ -405,9 +402,8 @@ void FieldElem::SetInverse(Context &ctx, FieldElem &a) { @@ -405,9 +402,8 @@ void FieldElem::SetInverse(Context &ctx, FieldElem &a) {
a.GetBytes(b);
{
const Number &p = GetFieldConst().field_p;
Context ct(ctx);
Number n(ct); n.SetBytes(b, 32);
n.SetModInverse(ct, n, p);
Number n; n.SetBytes(b, 32);
n.SetModInverse(n, p);
n.GetBytes(b, 32);
}
SetBytes(b);

73
group.h

@ -39,11 +39,11 @@ public: @@ -39,11 +39,11 @@ public:
y.SetNeg(y, 1);
}
void GetX(Context &ctx, FieldElem &xout) {
void GetX(FieldElem &xout) {
xout = x;
}
void GetY(Context &ctx, FieldElem &yout) {
void GetY(FieldElem &yout) {
yout = y;
}
@ -54,7 +54,7 @@ public: @@ -54,7 +54,7 @@ public:
return "(" + xc.ToString() + "," + yc.ToString() + ")";
}
void SetJac(Context &ctx, GroupElemJac &jac);
void SetJac(GroupElemJac &jac);
friend class GroupElemJac;
};
@ -73,7 +73,7 @@ public: @@ -73,7 +73,7 @@ public:
GroupElemJac(const GroupElem &in) : GroupElem(in), z(1) {}
void SetJac(Context &ctx, GroupElemJac &jac) {
void SetJac(GroupElemJac &jac) {
*this = jac;
}
@ -95,8 +95,8 @@ public: @@ -95,8 +95,8 @@ public:
}
/** Returns the affine coordinates of this point */
void GetAffine(Context &ctx, GroupElem &aff) {
z.SetInverse(ctx, z);
void GetAffine(GroupElem &aff) {
z.SetInverse(z);
FieldElem z2;
z2.SetSquare(z);
FieldElem z3;
@ -109,9 +109,9 @@ public: @@ -109,9 +109,9 @@ public:
aff.y = y;
}
void GetX(Context &ctx, FieldElem &xout) {
void GetX(FieldElem &xout) {
FieldElem zi;
zi.SetInverse(ctx, z);
zi.SetInverse(z);
zi.SetSquare(zi);
xout.SetMult(x, zi);
}
@ -120,9 +120,9 @@ public: @@ -120,9 +120,9 @@ public:
return fInfinity;
}
void GetY(Context &ctx, FieldElem &yout) {
void GetY(FieldElem &yout) {
FieldElem zi;
zi.SetInverse(ctx, z);
zi.SetInverse(z);
FieldElem zi3; zi3.SetSquare(zi); zi3.SetMult(zi, zi3);
yout.SetMult(y, zi3);
}
@ -260,18 +260,17 @@ public: @@ -260,18 +260,17 @@ public:
}
std::string ToString() const {
Context ctx;
GroupElemJac cop = *this;
GroupElem aff;
cop.GetAffine(ctx, aff);
cop.GetAffine(aff);
return aff.ToString();
}
void SetMulLambda(const GroupElemJac &p);
};
void GroupElem::SetJac(Context &ctx, GroupElemJac &jac) {
jac.GetAffine(ctx, *this);
void GroupElem::SetJac(GroupElemJac &jac) {
jac.GetAffine(*this);
}
static const unsigned char order_[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
@ -307,7 +306,6 @@ static const unsigned char a2_[] = {0x01, @@ -307,7 +306,6 @@ static const unsigned char a2_[] = {0x01,
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8};
class GroupConstants {
private:
Context ctx;
const FieldElem g_x;
const FieldElem g_y;
@ -318,13 +316,13 @@ public: @@ -318,13 +316,13 @@ public:
const Number lambda, a1b2, b1, a2;
GroupConstants() : g_x(g_x_), g_y(g_y_),
order(ctx, order_, sizeof(order_)),
order(order_, sizeof(order_)),
g(g_x,g_y),
beta(beta_),
lambda(ctx, lambda_, sizeof(lambda_)),
a1b2(ctx, a1b2_, sizeof(a1b2_)),
b1(ctx, b1_, sizeof(b1_)),
a2(ctx, a2_, sizeof(a2_)) {}
lambda(lambda_, sizeof(lambda_)),
a1b2(a1b2_, sizeof(a1b2_)),
b1(b1_, sizeof(b1_)),
a2(a2_, sizeof(a2_)) {}
};
const GroupConstants &GetGroupConst() {
@ -338,28 +336,27 @@ void GroupElemJac::SetMulLambda(const GroupElemJac &p) { @@ -338,28 +336,27 @@ void GroupElemJac::SetMulLambda(const GroupElemJac &p) {
x.SetMult(x, beta);
}
void SplitExp(Context &ctx, const Number &exp, Number &exp1, Number &exp2) {
void SplitExp(const Number &exp, Number &exp1, Number &exp2) {
const GroupConstants &c = GetGroupConst();
Context ct(ctx);
Number bnc1(ct), bnc2(ct), bnt1(ct), bnt2(ct), bnn2(ct);
Number bnc1, bnc2, bnt1, bnt2, bnn2;
bnn2.SetNumber(c.order);
bnn2.Shift1();
bnc1.SetMult(ct, exp, c.a1b2);
bnc1.SetAdd(ct, bnc1, bnn2);
bnc1.SetDiv(ct, bnc1, c.order);
bnc2.SetMult(ct, exp, c.b1);
bnc2.SetAdd(ct, bnc2, bnn2);
bnc2.SetDiv(ct, bnc2, c.order);
bnt1.SetMult(ct, bnc1, c.a1b2);
bnt2.SetMult(ct, bnc2, c.a2);
bnt1.SetAdd(ct, bnt1, bnt2);
exp1.SetSub(ct, exp, bnt1);
bnt1.SetMult(ct, bnc1, c.b1);
bnt2.SetMult(ct, bnc2, c.a1b2);
exp2.SetSub(ct, bnt1, bnt2);
bnc1.SetMult(exp, c.a1b2);
bnc1.SetAdd(bnc1, bnn2);
bnc1.SetDiv(bnc1, c.order);
bnc2.SetMult(exp, c.b1);
bnc2.SetAdd(bnc2, bnn2);
bnc2.SetDiv(bnc2, c.order);
bnt1.SetMult(bnc1, c.a1b2);
bnt2.SetMult(bnc2, c.a2);
bnt1.SetAdd(bnt1, bnt2);
exp1.SetSub(exp, bnt1);
bnt1.SetMult(bnc1, c.b1);
bnt2.SetMult(bnc2, c.a1b2);
exp2.SetSub(bnt1, bnt2);
}
}

31
num_gmp.h

@ -9,15 +9,6 @@ @@ -9,15 +9,6 @@
namespace secp256k1 {
class Context {
public:
Context() {
}
Context(Context &par) {
}
};
class NumberState {
private:
gmp_randstate_t rng;
@ -44,13 +35,13 @@ private: @@ -44,13 +35,13 @@ private:
Number(const Number &x) {
}
public:
Number(Context &ctx) {
Number() {
mpz_init(bn);
}
~Number() {
mpz_clear(bn);
}
Number(Context &ctx, const unsigned char *bin, int len) {
Number(const unsigned char *bin, int len) {
mpz_init(bn);
SetBytes(bin,len);
}
@ -75,26 +66,26 @@ public: @@ -75,26 +66,26 @@ public:
void SetInt(int x) {
mpz_set_si(bn, x);
}
void SetModInverse(Context &ctx, const Number &x, const Number &m) {
void SetModInverse(const Number &x, const Number &m) {
mpz_invert(bn, x.bn, m.bn);
}
void SetModMul(Context &ctx, const Number &a, const Number &b, const Number &m) {
void SetModMul(const Number &a, const Number &b, const Number &m) {
mpz_mul(bn, a.bn, b.bn);
mpz_mod(bn, bn, m.bn);
}
void SetAdd(Context &ctx, const Number &a1, const Number &a2) {
void SetAdd(const Number &a1, const Number &a2) {
mpz_add(bn, a1.bn, a2.bn);
}
void SetSub(Context &ctx, const Number &a1, const Number &a2) {
void SetSub(const Number &a1, const Number &a2) {
mpz_sub(bn, a1.bn, a2.bn);
}
void SetMult(Context &ctx, const Number &a1, const Number &a2) {
void SetMult(const Number &a1, const Number &a2) {
mpz_mul(bn, a1.bn, a2.bn);
}
void SetDiv(Context &ctx, const Number &a1, const Number &a2) {
void SetDiv(const Number &a1, const Number &a2) {
mpz_tdiv_q(bn, a1.bn, a2.bn);
}
void SetMod(Context &ctx, const Number &a, const Number &m) {
void SetMod(const Number &a, const Number &m) {
mpz_mod(bn, a.bn, m.bn);
}
int Compare(const Number &a) const {
@ -104,7 +95,7 @@ public: @@ -104,7 +95,7 @@ public:
return mpz_sizeinbase(bn,2);
}
// return the lowest (rightmost) bits bits, and rshift them away
int ShiftLowBits(Context &ctx, int bits) {
int ShiftLowBits(int bits) {
int ret = mpz_get_ui(bn) & ((1 << bits) - 1);
mpz_fdiv_q_2exp(bn, bn, bits);
return ret;
@ -134,7 +125,7 @@ public: @@ -134,7 +125,7 @@ public:
void SetPseudoRand(const Number &max) {
number_state.gen(bn, max.bn);
}
void SplitInto(Context &ctx, int bits, Number &low, Number &high) const {
void SplitInto(int bits, Number &low, Number &high) const {
mpz_t tmp;
mpz_init_set_ui(tmp,1);
mpz_mul_2exp(tmp,tmp,bits);

145
num_openssl.h

@ -7,150 +7,151 @@ @@ -7,150 +7,151 @@
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <stdint.h>
namespace secp256k1 {
class Context {
private:
BN_CTX *bn_ctx;
bool root;
bool offspring;
BN_CTX *ctx;
public:
operator BN_CTX*() {
return bn_ctx;
return ctx;
}
friend class Number;
public:
Context() {
bn_ctx = BN_CTX_new();
BN_CTX_start(bn_ctx);
root = true;
offspring = false;
}
Context(Context &par) {
bn_ctx = par.bn_ctx;
root = false;
offspring = false;
par.offspring = true;
BN_CTX_start(bn_ctx);
ctx = BN_CTX_new();
}
~Context() {
BN_CTX_end(bn_ctx);
if (root)
BN_CTX_free(bn_ctx);
}
BIGNUM *Get() {
assert(offspring == false);
return BN_CTX_get(bn_ctx);
BN_CTX_free(ctx);
}
};
class Number {
private:
BIGNUM *bn;
BIGNUM b;
Number(const Number &x) {}
operator const BIGNUM*() const {
return &b;
}
operator BIGNUM*() {
return &b;
}
public:
Number(Context &ctx) : bn(ctx.Get()) {}
Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) {
Number() {
BN_init(*this);
}
~Number() {
BN_free(*this);
}
Number(const unsigned char *bin, int len) {
BN_init(*this);
SetBytes(bin,len);
}
void SetNumber(const Number &x) {
BN_copy(bn, x.bn);
BN_copy(*this, x);
}
Number &operator=(const Number &x) {
BN_copy(bn, x.bn);
BN_copy(*this, x);
return *this;
}
void SetBytes(const unsigned char *bin, int len) {
BN_bin2bn(bin, len, bn);
BN_bin2bn(bin, len, *this);
}
void GetBytes(unsigned char *bin, int len) {
int size = BN_num_bytes(bn);
int size = BN_num_bytes(*this);
assert(size <= len);
memset(bin,0,len);
BN_bn2bin(bn, bin + len - size);
BN_bn2bin(*this, bin + len - size);
}
void SetInt(int x) {
if (x >= 0) {
BN_set_word(bn, x);
BN_set_word(*this, x);
} else {
BN_set_word(bn, -x);
BN_set_negative(bn, 1);
BN_set_word(*this, -x);
BN_set_negative(*this, 1);
}
}
void SetModInverse(Context &ctx, const Number &x, const Number &m) {
BN_mod_inverse(bn, x.bn, m.bn, ctx);
void SetModInverse(const Number &x, const Number &m) {
Context ctx;
BN_mod_inverse(*this, x, m, 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 SetModMul(const Number &a, const Number &b, const Number &m) {
Context ctx;
BN_mod_mul(*this, a, b, m, ctx);
}
void SetAdd(Context &ctx, const Number &a1, const Number &a2) {
BN_add(bn, a1.bn, a2.bn);
void SetAdd(const Number &a1, const Number &a2) {
BN_add(*this, a1, a2);
}
void SetSub(Context &ctx, const Number &a1, const Number &a2) {
BN_sub(bn, a1.bn, a2.bn);
void SetSub(const Number &a1, const Number &a2) {
BN_sub(*this, a1, a2);
}
void SetMult(Context &ctx, const Number &a1, const Number &a2) {
BN_mul(bn, a1.bn, a2.bn, ctx);
void SetMult(const Number &a1, const Number &a2) {
Context ctx;
BN_mul(*this, a1, a2, ctx);
}
void SetDiv(Context &ctx, const Number &a1, const Number &a2) {
BN_div(bn, NULL, a1.bn, a2.bn, ctx);
void SetDiv(const Number &a1, const Number &a2) {
Context ctx;
BN_div(*this, NULL, a1, a2, ctx);
}
void SetMod(Context &ctx, const Number &a, const Number &m) {
BN_nnmod(bn, a.bn, m.bn, ctx);
void SetMod(const Number &a, const Number &m) {
Context ctx;
BN_nnmod(*this, a, m, ctx);
}
int Compare(const Number &a) const {
return BN_cmp(bn, a.bn);
return BN_cmp(*this, a);
}
int GetBits() const {
return BN_num_bits(bn);
return BN_num_bits(*this);
}
// return the lowest (rightmost) bits bits, and rshift them away
int ShiftLowBits(Context &ctx, int bits) {
Context ct(ctx);
BIGNUM *tmp = ct.Get();
BN_copy(tmp, bn);
BN_mask_bits(tmp, bits);
int ret = BN_get_word(tmp);
BN_rshift(bn, bn, bits);
int ShiftLowBits(int bits) {
BIGNUM *bn = *this;
int ret = BN_is_zero(bn) ? 0 : bn->d[0] & ((1 << bits) - 1);
BN_rshift(*this, *this, bits);
return ret;
}
// check whether number is 0,
bool IsZero() const {
return BN_is_zero(bn);
return BN_is_zero((const BIGNUM*)*this);
}
bool IsOdd() const {
return BN_is_odd(bn);
return BN_is_odd((const BIGNUM*)*this);
}
bool IsNeg() const {
return BN_is_negative(bn);
return BN_is_negative((const BIGNUM*)*this);
}
void Negate() {
BN_set_negative(bn, !IsNeg());
BN_set_negative(*this, !IsNeg());
}
void Shift1() {
BN_rshift1(bn,bn);
BN_rshift1(*this,*this);
}
void Inc() {
BN_add_word(bn,1);
BN_add_word(*this,1);
}
void SetHex(const std::string &str) {
BIGNUM *bn = *this;
BN_hex2bn(&bn, str.c_str());
}
void SetPseudoRand(const Number &max) {
BN_pseudo_rand_range(bn, max.bn);
BN_pseudo_rand_range(*this, max);
}
void SplitInto(Context &ctx, int bits, Number &low, Number &high) const {
BN_copy(low.bn, bn);
BN_mask_bits(low.bn, bits);
BN_rshift(high.bn, bn, bits);
void SplitInto(int bits, Number &low, Number &high) const {
BN_copy(low, *this);
BN_mask_bits(low, bits);
BN_rshift(high, *this, bits);
}
std::string ToString() const {
char *str = BN_bn2hex(bn);
char *str = BN_bn2hex(*this);
std::string ret(str);
OPENSSL_free(str);
return ret;

49
tests.cpp

@ -9,40 +9,39 @@ @@ -9,40 +9,39 @@
using namespace secp256k1;
void test_run_ecmult_chain() {
Context ctx;
// random starting point A (on the curve)
FieldElem ax; ax.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004");
FieldElem ay; ay.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
GroupElemJac a(ax,ay);
// two random initial factors xn and gn
Number xn(ctx); xn.SetHex("84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407");
Number gn(ctx); gn.SetHex("a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de");
Number xn; xn.SetHex("84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407");
Number gn; gn.SetHex("a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de");
// two small multipliers to be applied to xn and gn in every iteration:
Number xf(ctx); xf.SetHex("1337");
Number gf(ctx); gf.SetHex("7113");
Number xf; xf.SetHex("1337");
Number gf; gf.SetHex("7113");
// accumulators with the resulting coefficients to A and G
Number ae(ctx); ae.SetHex("01");
Number ge(ctx); ge.SetHex("00");
Number ae; ae.SetHex("01");
Number ge; ge.SetHex("00");
// the point being computed
GroupElemJac x = a;
const Number &order = GetGroupConst().order;
for (int i=0; i<20000; i++) {
// in each iteration, compute X = xn*X + gn*G;
ECMult(ctx, x, x, xn, gn);
ECMult(x, x, xn, gn);
// also compute ae and ge: the actual accumulated factors for A and G
// if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
ae.SetModMul(ctx, ae, xn, order);
ge.SetModMul(ctx, ge, xn, order);
ge.SetAdd(ctx, ge, gn);
ge.SetMod(ctx, ge, order);
ae.SetModMul(ae, xn, order);
ge.SetModMul(ge, xn, order);
ge.SetAdd(ge, gn);
ge.SetMod(ge, order);
// modify xn and gn
xn.SetModMul(ctx, xn, xf, order);
gn.SetModMul(ctx, gn, gf, order);
xn.SetModMul(xn, xf, order);
gn.SetModMul(gn, gf, order);
}
std::string res = x.ToString();
assert(res == "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)");
// redo the computation, but directly with the resulting ae and ge coefficients:
GroupElemJac x2; ECMult(ctx, x2, a, ae, ge);
GroupElemJac x2; ECMult(x2, a, ae, ge);
std::string res2 = x2.ToString();
assert(res == res2);
}
@ -53,15 +52,13 @@ void test_point_times_order(const GroupElemJac &point) { @@ -53,15 +52,13 @@ void test_point_times_order(const GroupElemJac &point) {
return;
const GroupConstants &c = GetGroupConst();
Context ctx;
Number zero(ctx); zero.SetInt(0);
Number zero; zero.SetInt(0);
GroupElemJac res;
ECMult(ctx, res, point, c.order, zero); // calc res = order * point + 0 * G;
ECMult(res, point, c.order, zero); // calc res = order * point + 0 * G;
assert(res.IsInfinity());
}
void test_run_point_times_order() {
Context ctx;
FieldElem x; x.SetHex("02");
for (int i=0; i<500; i++) {
GroupElemJac j; j.SetCompressed(x, true);
@ -72,14 +69,13 @@ void test_run_point_times_order() { @@ -72,14 +69,13 @@ void test_run_point_times_order() {
}
void test_wnaf(const Number &number, int w) {
Context ctx;
Number x(ctx), two(ctx), t(ctx);
Number x, two, t;
x.SetInt(0);
two.SetInt(2);
WNAF<1023> wnaf(ctx, number, w);
WNAF<1023> wnaf(number, w);
int zeroes = -1;
for (int i=wnaf.GetSize()-1; i>=0; i--) {
x.SetMult(ctx, x, two);
x.SetMult(x, two);
int v = wnaf.Get(i);
if (v) {
assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
@ -92,18 +88,17 @@ void test_wnaf(const Number &number, int w) { @@ -92,18 +88,17 @@ void test_wnaf(const Number &number, int w) {
zeroes++;
}
t.SetInt(v);
x.SetAdd(ctx, x, t);
x.SetAdd(x, t);
}
assert(x.Compare(number) == 0); // check that wnaf represents number
}
void test_run_wnaf() {
Context ctx;
Number range(ctx), min(ctx), n(ctx);
Number range, min, n;
range.SetHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); // 2^1024-1
min = range; min.Shift1(); min.Negate();
for (int i=0; i<100; i++) {
n.SetPseudoRand(range); n.SetAdd(ctx,n,min);
n.SetPseudoRand(range); n.SetAdd(n,min);
test_wnaf(n, 4+(i%10));
}
}

Loading…
Cancel
Save