Browse Source

Fourth step in converting to C: ecmult

master
Pieter Wuille 10 years ago
parent
commit
b1483f874c
  1. 2
      src/bench.cpp
  2. 4
      src/ecdsa.cpp
  3. 396
      src/ecmult.cpp
  4. 11
      src/ecmult.h
  5. 183
      src/num_openssl_.cpp
  6. 3
      src/secp256k1.cpp
  7. 17
      src/tests.cpp

2
src/bench.cpp

@ -12,6 +12,7 @@ int main() { @@ -12,6 +12,7 @@ int main() {
secp256k1_num_start();
secp256k1_fe_start();
secp256k1_ge_start();
secp256k1_ecmult_start();
secp256k1_fe_t x;
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
@ -39,6 +40,7 @@ int main() { @@ -39,6 +40,7 @@ int main() {
secp256k1_num_free(&s);
secp256k1_num_free(&m);
secp256k1_ecmult_stop();
secp256k1_ge_stop();
secp256k1_fe_stop();
secp256k1_num_stop();

4
src/ecdsa.cpp

@ -79,7 +79,7 @@ bool Signature::RecomputeR(secp256k1_num_t &r2, const secp256k1_gej_t &pubkey, c @@ -79,7 +79,7 @@ bool Signature::RecomputeR(secp256k1_num_t &r2, const secp256k1_gej_t &pubkey, c
secp256k1_num_mod_inverse(&sn, &s, &c.order);
secp256k1_num_mod_mul(&u1, &sn, &message, &c.order);
secp256k1_num_mod_mul(&u2, &sn, &r, &c.order);
secp256k1_gej_t pr; ECMult(pr, pubkey, u2, u1);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkey, &u2, &u1);
if (!secp256k1_gej_is_infinity(&pr)) {
secp256k1_fe_t xr; secp256k1_gej_get_x(&xr, &pr);
secp256k1_fe_normalize(&xr);
@ -107,7 +107,7 @@ bool Signature::Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &messa @@ -107,7 +107,7 @@ bool Signature::Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &messa
const secp256k1_ge_consts_t &c = *secp256k1_ge_consts;
secp256k1_gej_t rp;
ECMultBase(rp, nonce);
secp256k1_ecmult_gen(&rp, &nonce);
secp256k1_fe_t rx;
secp256k1_gej_get_x(&rx, &rp);
unsigned char b[32];

396
src/ecmult.cpp

@ -12,245 +12,221 @@ @@ -12,245 +12,221 @@
// exponentially larger precomputed tables. WINDOW_G == 13 results in 640 KiB.
#define WINDOW_G 14
namespace secp256k1 {
template<int W> class WNAFPrecompJac {
private:
secp256k1_gej_t pre[1 << (W-2)];
public:
WNAFPrecompJac() {}
void Build(const secp256k1_gej_t &base) {
pre[0] = base;
secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]);
for (int i=1; i<(1 << (W-2)); i++)
secp256k1_gej_add(&pre[i], &d, &pre[i-1]);
}
extern "C" {
/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
* pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for
* 2^(w-2) entries.
*
* There are two versions of this function:
* - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation,
* fast to precompute, but slower to use in later additions.
* - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations,
* (much) slower to precompute, but a bit faster to use in later additions.
* To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as
* G is constant, so it only needs to be done once in advance.
*/
void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) {
pre[0] = *a;
secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]);
for (int i=1; i<(1 << (w-2)); i++)
secp256k1_gej_add(&pre[i], &d, &pre[i-1]);
}
WNAFPrecompJac(const secp256k1_gej_t &base) {
Build(base);
void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_ge_t *a, int w) {
pre[0] = *a;
secp256k1_gej_t x; secp256k1_gej_set_ge(&x, a);
secp256k1_gej_t d; secp256k1_gej_double(&d, &x);
for (int i=1; i<(1 << (w-2)); i++) {
secp256k1_gej_add_ge(&x, &d, &pre[i-1]);
secp256k1_ge_set_gej(&pre[i], &x);
}
}
void Get(secp256k1_gej_t &out, int exp) const {
assert((exp & 1) == 1);
assert(exp >= -((1 << (W-1)) - 1));
assert(exp <= ((1 << (W-1)) - 1));
if (exp > 0) {
out = pre[(exp-1)/2];
} else {
secp256k1_gej_neg(&out, &pre[(-exp-1)/2]);
}
}
};
template<int W> class WNAFPrecompAff {
private:
secp256k1_ge_t pre[1 << (W-2)];
public:
WNAFPrecompAff() {}
void Build(const secp256k1_ge_t &base) {
pre[0] = base;
secp256k1_gej_t x; secp256k1_gej_set_ge(&x, &base);
secp256k1_gej_t d; secp256k1_gej_double(&d, &x);
for (int i=1; i<(1 << (W-2)); i++) {
secp256k1_gej_add_ge(&x, &d, &pre[i-1]);
secp256k1_ge_set_gej(&pre[i], &x);
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
/** The following two macro retrieves a particular odd multiple from a table
* of precomputed multiples. */
#define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \
assert(((n) & 1) == 1); \
assert((n) >= -((1 << ((w)-1)) - 1)); \
assert((n) <= ((1 << ((w)-1)) - 1)); \
if ((n) > 0) \
*(r) = (pre)[((n)-1)/2]; \
else \
(neg)((r), &(pre)[(-(n)-1)/2]); \
} while(0)
#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg)
#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
typedef struct {
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
} secp256k1_ecmult_consts_t;
static secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
static void secp256k1_ecmult_start(void) {
if (secp256k1_ecmult_consts != NULL)
return;
secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t));
secp256k1_ecmult_consts = ret;
// get the generator
const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
// calculate 2^128*generator
secp256k1_gej_t g_128j; secp256k1_gej_set_ge(&g_128j, g);
for (int i=0; i<128; i++)
secp256k1_gej_double(&g_128j, &g_128j);
secp256k1_ge_t g_128; secp256k1_ge_set_gej(&g_128, &g_128j);
// precompute the tables with odd multiples
secp256k1_ecmult_table_precomp_ge(ret->pre_g, g, WINDOW_G);
secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128, WINDOW_G);
// compute prec and fin
secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g);
secp256k1_ge_t ad = *g;
secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn);
for (int j=0; j<64; j++) {
secp256k1_ge_set_gej(&ret->prec[j][0], &gg);
secp256k1_gej_add(&fn, &fn, &gg);
for (int i=1; i<16; i++) {
secp256k1_gej_add_ge(&gg, &gg, &ad);
secp256k1_ge_set_gej(&ret->prec[j][i], &gg);
}
ad = ret->prec[j][15];
}
secp256k1_ge_set_gej(&ret->fin, &fn);
secp256k1_ge_neg(&ret->fin, &ret->fin);
}
WNAFPrecompAff(const secp256k1_ge_t &base) {
Build(base);
}
void Get(secp256k1_ge_t &out, int exp) const {
assert((exp & 1) == 1);
assert(exp >= -((1 << (W-1)) - 1));
assert(exp <= ((1 << (W-1)) - 1));
if (exp > 0) {
out = pre[(exp-1)/2];
} else {
secp256k1_ge_neg(&out, &pre[(-exp-1)/2]);
}
}
};
static void secp256k1_ecmult_stop(void) {
if (secp256k1_ecmult_consts == NULL)
return;
template<int B> class WNAF {
private:
int naf[B+1];
int used;
free(secp256k1_ecmult_consts);
secp256k1_ecmult_consts = NULL;
}
void PushNAF(int num, int zeroes) {
assert(used < B+1);
for (int i=0; i<zeroes; i++) {
naf[used++]=0;
}
naf[used++]=num;
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
* with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
* - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where
* bits is the number of bits necessary to represent the absolute value of the input.
*/
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
int ret = 0;
int zeroes = 0;
secp256k1_num_t x;
secp256k1_num_init(&x);
secp256k1_num_copy(&x, a);
int sign = 1;
if (secp256k1_num_is_neg(&x)) {
sign = -1;
secp256k1_num_negate(&x);
}
public:
WNAF(const secp256k1_num_t &exp, int w) : used(0) {
int zeroes = 0;
secp256k1_num_t x;
secp256k1_num_init(&x);
secp256k1_num_copy(&x, &exp);
int sign = 1;
if (secp256k1_num_is_neg(&x)) {
sign = -1;
secp256k1_num_negate(&x);
}
while (!secp256k1_num_is_zero(&x)) {
while (!secp256k1_num_is_odd(&x)) {
zeroes++;
secp256k1_num_shift(&x, 1);
}
int word = secp256k1_num_shift(&x, w);
if (word & (1 << (w-1))) {
secp256k1_num_inc(&x);
PushNAF(sign * (word - (1 << w)), zeroes);
} else {
PushNAF(sign * word, zeroes);
}
zeroes = w-1;
while (!secp256k1_num_is_zero(&x)) {
while (!secp256k1_num_is_odd(&x)) {
zeroes++;
secp256k1_num_shift(&x, 1);
}
secp256k1_num_free(&x);
}
int GetSize() const {
return used;
}
int Get(int pos) const {
assert(pos >= 0 && pos < used);
return naf[pos];
}
std::string ToString() {
std::stringstream ss;
ss << "(";
for (int i=0; i<GetSize(); i++) {
ss << Get(used-1-i);
if (i != used-1)
ss << ',';
int word = secp256k1_num_shift(&x, w);
while (zeroes) {
wnaf[ret++] = 0;
zeroes--;
}
ss << ")";
return ss.str();
}
};
class ECMultConsts {
public:
WNAFPrecompAff<WINDOW_G> wpg;
WNAFPrecompAff<WINDOW_G> wpg128;
secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
ECMultConsts() {
const secp256k1_ge_t &g = secp256k1_ge_consts->g;
secp256k1_gej_t g128j; secp256k1_gej_set_ge(&g128j, &g);
for (int i=0; i<128; i++)
secp256k1_gej_double(&g128j, &g128j);
secp256k1_ge_t g128; secp256k1_ge_set_gej(&g128, &g128j);
wpg.Build(g);
wpg128.Build(g128);
secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, &g);
secp256k1_ge_t ad = g;
secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn);
for (int j=0; j<64; j++) {
secp256k1_ge_set_gej(&prec[j][0], &gg);
secp256k1_gej_add(&fn, &fn, &gg);
for (int i=1; i<16; i++) {
secp256k1_gej_add_ge(&gg, &gg, &ad);
secp256k1_ge_set_gej(&prec[j][i], &gg);
}
ad = prec[j][15];
if (word & (1 << (w-1))) {
secp256k1_num_inc(&x);
wnaf[ret++] = sign * (word - (1 << w));
} else {
wnaf[ret++] = sign * word;
}
secp256k1_ge_set_gej(&fin, &fn);
secp256k1_ge_neg(&fin, &fin);
zeroes = w-1;
}
};
const ECMultConsts &GetECMultConsts() {
static const ECMultConsts ecmult_consts;
return ecmult_consts;
secp256k1_num_free(&x);
return ret;
}
void ECMultBase(secp256k1_gej_t &out, const secp256k1_num_t &gn) {
void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) {
secp256k1_num_t n;
secp256k1_num_init(&n);
secp256k1_num_copy(&n, &gn);
const ECMultConsts &c = GetECMultConsts();
secp256k1_gej_set_ge(&out, &c.prec[0][secp256k1_num_shift(&n, 4)]);
for (int j=1; j<64; j++) {
secp256k1_gej_add_ge(&out, &out, &c.prec[j][secp256k1_num_shift(&n, 4)]);
}
secp256k1_num_copy(&n, gn);
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]);
for (int j=1; j<64; j++)
secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]);
secp256k1_num_free(&n);
secp256k1_gej_add_ge(&out, &out, &c.fin);
secp256k1_gej_add_ge(r, r, &c->fin);
}
void ECMult(secp256k1_gej_t &out, const secp256k1_gej_t &a, const secp256k1_num_t &an, const secp256k1_num_t &gn) {
secp256k1_num_t an1, an2;
secp256k1_num_t gn1, gn2;
secp256k1_num_init(&an1);
secp256k1_num_init(&an2);
secp256k1_num_init(&gn1);
secp256k1_num_init(&gn2);
secp256k1_gej_split_exp(&an1, &an2, &an);
// 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());
secp256k1_num_split(&gn1, &gn2, &gn, 128);
WNAF<128> wa1(an1, WINDOW_A);
WNAF<128> wa2(an2, WINDOW_A);
WNAF<128> wg1(gn1, WINDOW_G);
WNAF<128> wg2(gn2, WINDOW_G);
secp256k1_gej_t a2; secp256k1_gej_mul_lambda(&a2, &a);
WNAFPrecompJac<WINDOW_A> wpa1(a);
WNAFPrecompJac<WINDOW_A> wpa2(a2);
const ECMultConsts &c = GetECMultConsts();
int size_a1 = wa1.GetSize();
int size_a2 = wa2.GetSize();
int size_g1 = wg1.GetSize();
int size_g2 = wg2.GetSize();
int size = std::max(std::max(size_a1, size_a2), std::max(size_g1, size_g2));
out; secp256k1_gej_set_infinity(&out);
void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) {
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
secp256k1_num_t na_1, na_lam;
secp256k1_num_t ng_1, ng_128;
secp256k1_num_init(&na_1);
secp256k1_num_init(&na_lam);
secp256k1_num_init(&ng_1);
secp256k1_num_init(&ng_128);
// split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit)
secp256k1_gej_split_exp(&na_1, &na_lam, na);
// split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit)
secp256k1_num_split(&ng_1, &ng_128, ng, 128);
// build wnaf representation for na_1, na_lam, ng_1, ng_128
int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
// calculate a_lam = a*lambda
secp256k1_gej_t a_lam; secp256k1_gej_mul_lambda(&a_lam, a);
// calculate odd multiples of a and a_lam
secp256k1_gej_t pre_a_1[ECMULT_TABLE_SIZE(WINDOW_A)], pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ecmult_table_precomp_gej(pre_a_1, a, WINDOW_A);
secp256k1_ecmult_table_precomp_gej(pre_a_lam, &a_lam, WINDOW_A);
int bits = std::max(std::max(bits_na_1, bits_na_lam), std::max(bits_ng_1, bits_ng_128));
secp256k1_gej_set_infinity(r);
secp256k1_gej_t tmpj;
secp256k1_ge_t tmpa;
for (int i=size-1; i>=0; i--) {
secp256k1_gej_double(&out, &out);
int nw;
if (i < size_a1 && (nw = wa1.Get(i))) {
wpa1.Get(tmpj, nw);
secp256k1_gej_add(&out, &out, &tmpj);
for (int i=bits-1; i>=0; i--) {
secp256k1_gej_double(r, r);
int n;
if (i < bits_na_1 && (n = wnaf_na_1[i])) {
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_1, n, WINDOW_A);
secp256k1_gej_add(r, r, &tmpj);
}
if (i < size_a2 && (nw = wa2.Get(i))) {
wpa2.Get(tmpj, nw);
secp256k1_gej_add(&out, &out, &tmpj);
if (i < bits_na_lam && (n = wnaf_na_lam[i])) {
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A);
secp256k1_gej_add(r, r, &tmpj);
}
if (i < size_g1 && (nw = wg1.Get(i))) {
c.wpg.Get(tmpa, nw);
secp256k1_gej_add_ge(&out, &out, &tmpa);
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge(r, r, &tmpa);
}
if (i < size_g2 && (nw = wg2.Get(i))) {
c.wpg128.Get(tmpa, nw);
secp256k1_gej_add_ge(&out, &out, &tmpa);
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G);
secp256k1_gej_add_ge(r, r, &tmpa);
}
}
secp256k1_num_free(&an1);
secp256k1_num_free(&an2);
secp256k1_num_free(&gn1);
secp256k1_num_free(&gn2);
secp256k1_num_free(&na_1);
secp256k1_num_free(&na_lam);
secp256k1_num_free(&ng_1);
secp256k1_num_free(&ng_128);
}
}

11
src/ecmult.h

@ -4,10 +4,15 @@ @@ -4,10 +4,15 @@
#include "num.h"
#include "group.h"
namespace secp256k1 {
extern "C" {
void ECMultBase(secp256k1_gej_t &out, const secp256k1_num_t &gn);
void ECMult(secp256k1_gej_t &out, const secp256k1_gej_t &a, const secp256k1_num_t &an, const secp256k1_num_t &gn);
static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void);
/** Multiply with the generator: R = a*G */
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a);
/** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng);
}

183
src/num_openssl_.cpp

@ -1,183 +0,0 @@ @@ -1,183 +0,0 @@
#include <assert.h>
#include <string>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include "num_openssl.h"
namespace secp256k1 {
class Context {
private:
BN_CTX *ctx;
operator BN_CTX*() {
return ctx;
}
friend class Number;
public:
Context() {
ctx = BN_CTX_new();
}
~Context() {
BN_CTX_free(ctx);
}
};
Number::operator const BIGNUM*() const {
return &b;
}
Number::operator BIGNUM*() {
return &b;
}
Number::Number() {
BN_init(*this);
}
Number::~Number() {
BN_free(*this);
}
Number::Number(const unsigned char *bin, int len) {
BN_init(*this);
SetBytes(bin,len);
}
void Number::SetNumber(const Number &x) {
BN_copy(*this, x);
}
Number::Number(const Number &x) {
BN_init(*this);
BN_copy(*this, x);
}
Number &Number::operator=(const Number &x) {
BN_copy(*this, x);
return *this;
}
void Number::SetBytes(const unsigned char *bin, int len) {
BN_bin2bn(bin, len, *this);
}
void Number::GetBytes(unsigned char *bin, int len) {
int size = BN_num_bytes(*this);
assert(size <= len);
memset(bin,0,len);
BN_bn2bin(*this, bin + len - size);
}
void Number::SetInt(int x) {
if (x >= 0) {
BN_set_word(*this, x);
} else {
BN_set_word(*this, -x);
BN_set_negative(*this, 1);
}
}
void Number::SetModInverse(const Number &x, const Number &m) {
Context ctx;
BN_mod_inverse(*this, x, m, ctx);
}
void Number::SetModMul(const Number &a, const Number &b, const Number &m) {
Context ctx;
BN_mod_mul(*this, a, b, m, ctx);
}
void Number::SetAdd(const Number &a1, const Number &a2) {
BN_add(*this, a1, a2);
}
void Number::SetSub(const Number &a1, const Number &a2) {
BN_sub(*this, a1, a2);
}
void Number::SetMult(const Number &a1, const Number &a2) {
Context ctx;
BN_mul(*this, a1, a2, ctx);
}
void Number::SetDiv(const Number &a1, const Number &a2) {
Context ctx;
BN_div(*this, NULL, a1, a2, ctx);
}
void Number::SetMod(const Number &a, const Number &m) {
Context ctx;
BN_nnmod(*this, a, m, ctx);
}
int Number::Compare(const Number &a) const {
return BN_cmp(*this, a);
}
int Number::GetBits() const {
return BN_num_bits(*this);
}
int Number::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;
}
bool Number::IsZero() const {
return BN_is_zero((const BIGNUM*)*this);
}
bool Number::IsOdd() const {
return BN_is_odd((const BIGNUM*)*this);
}
bool Number::CheckBit(int pos) const {
return BN_is_bit_set((const BIGNUM*)*this, pos);
}
bool Number::IsNeg() const {
return BN_is_negative((const BIGNUM*)*this);
}
void Number::Negate() {
BN_set_negative(*this, !IsNeg());
}
void Number::Shift1() {
BN_rshift1(*this,*this);
}
void Number::Inc() {
BN_add_word(*this,1);
}
void Number::SetHex(const std::string &str) {
BIGNUM *bn = *this;
BN_hex2bn(&bn, str.c_str());
}
void Number::SetPseudoRand(const Number &max) {
BN_pseudo_rand_range(*this, max);
}
void Number::SplitInto(int bits, Number &low, Number &high) const {
BN_copy(low, *this);
BN_mask_bits(low, bits);
BN_rshift(high, *this, bits);
}
std::string Number::ToString() const {
char *str = BN_bn2hex(*this);
std::string ret(str);
OPENSSL_free(str);
return ret;
}
}

3
src/secp256k1.cpp

@ -11,10 +11,11 @@ extern "C" void secp256k1_start(void) { @@ -11,10 +11,11 @@ extern "C" void secp256k1_start(void) {
secp256k1_num_start();
secp256k1_fe_start();
secp256k1_ge_start();
GetECMultConsts();
secp256k1_ecmult_start();
}
extern "C" void secp256k1_stop(void) {
secp256k1_ecmult_stop();
secp256k1_ge_stop();
secp256k1_fe_stop();
secp256k1_num_stop();

17
src/tests.cpp

@ -42,7 +42,7 @@ void test_run_ecmult_chain() { @@ -42,7 +42,7 @@ void test_run_ecmult_chain() {
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
for (int i=0; i<200*COUNT; i++) {
// in each iteration, compute X = xn*X + gn*G;
ECMult(x, x, xn, gn);
secp256k1_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)
secp256k1_num_mod_mul(&ae, &ae, &xn, order);
@ -59,7 +59,7 @@ void test_run_ecmult_chain() { @@ -59,7 +59,7 @@ void test_run_ecmult_chain() {
assert(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
}
// redo the computation, but directly with the resulting ae and ge coefficients:
secp256k1_gej_t x2; ECMult(x2, a, ae, ge);
secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge);
char res2[132]; int resl2 = 132;
secp256k1_gej_get_hex(res2, &resl2, &x2);
assert(strcmp(res, res2) == 0);
@ -82,7 +82,7 @@ void test_point_times_order(const secp256k1_gej_t &point) { @@ -82,7 +82,7 @@ void test_point_times_order(const secp256k1_gej_t &point) {
secp256k1_num_init(&zero);
secp256k1_num_set_int(&zero, 0);
secp256k1_gej_t res;
ECMult(res, point, *order, zero); // calc res = order * point + 0 * G;
secp256k1_ecmult(&res, &point, order, order); // calc res = order * point + order * G;
assert(secp256k1_gej_is_infinity(&res));
secp256k1_num_free(&zero);
}
@ -106,11 +106,12 @@ void test_wnaf(const secp256k1_num_t &number, int w) { @@ -106,11 +106,12 @@ void test_wnaf(const secp256k1_num_t &number, int w) {
secp256k1_num_init(&t);
secp256k1_num_set_int(&x, 0);
secp256k1_num_set_int(&two, 2);
WNAF<1023> wnaf(number, w);
int wnaf[1024];
int bits = secp256k1_ecmult_wnaf(wnaf, &number, w);
int zeroes = -1;
for (int i=wnaf.GetSize()-1; i>=0; i--) {
for (int i=bits-1; i>=0; i--) {
secp256k1_num_mul(&x, &x, &two);
int v = wnaf.Get(i);
int v = wnaf[i];
if (v) {
assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
zeroes=0;
@ -157,7 +158,7 @@ void test_ecdsa_sign_verify() { @@ -157,7 +158,7 @@ void test_ecdsa_sign_verify() {
secp256k1_num_init(&key);
secp256k1_num_set_rand(&key, &c.order);
secp256k1_num_init(&nonce);
secp256k1_gej_t pub; ECMultBase(pub, key);
secp256k1_gej_t pub; secp256k1_ecmult_gen(&pub, &key);
Signature sig;
do {
secp256k1_num_set_rand(&nonce, &c.order);
@ -180,12 +181,14 @@ int main(void) { @@ -180,12 +181,14 @@ int main(void) {
secp256k1_num_start();
secp256k1_fe_start();
secp256k1_ge_start();
secp256k1_ecmult_start();
test_run_wnaf();
test_run_point_times_order();
test_run_ecmult_chain();
test_run_ecdsa_sign_verify();
secp256k1_ecmult_stop();
secp256k1_ge_stop();
secp256k1_fe_stop();
secp256k1_num_stop();

Loading…
Cancel
Save