Merge pull request #117

c76be9e Remove unused num functions (Pieter Wuille)
4285a98 Move lambda-splitting code to scalar. (Pieter Wuille)
f24041d Switch all EC/ECDSA logic from num to scalar (Pieter Wuille)
6794be6 Add scalar splitting functions (Pieter Wuille)
d1502eb Add secp256k1_scalar_inverse_var which delegates to GMP (Pieter Wuille)
b5c9ee7 Make test_point_times_order test meaningful again (Pieter Wuille)
0b73059 Switch wnaf splitting from num-based to scalar-based (Pieter Wuille)
1e6c77c Generalize secp256k1_scalar_get_bits (Pieter Wuille)
5213207 Add secp256k1_scalar_add_bit (Pieter Wuille)
This commit is contained in:
Pieter Wuille 2014-12-01 12:29:58 +01:00
commit e2e8a362ad
No known key found for this signature in database
GPG Key ID: 57896D2FF8F0B657
21 changed files with 619 additions and 492 deletions

View File

@ -223,7 +223,8 @@ case $set_bignum in
gmp)
AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])
AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation])
AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the USE_FIELD_INV_NUM implementation])
AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation])
AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation])
;;
*)
AC_MSG_ERROR([invalid bignum implementation])

View File

@ -7,17 +7,21 @@
#ifndef _SECP256K1_ECDSA_
#define _SECP256K1_ECDSA_
#include "num.h"
#include "scalar.h"
#include "group.h"
static void secp256k1_ecsda_start(void);
static void secp256k1_ecdsa_stop(void);
typedef struct {
secp256k1_num_t r, s;
secp256k1_scalar_t r, s;
} secp256k1_ecdsa_sig_t;
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
#endif

View File

@ -8,13 +8,47 @@
#ifndef _SECP256K1_ECDSA_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_
#include "num.h"
#include "scalar.h"
#include "field.h"
#include "group.h"
#include "ecmult.h"
#include "ecmult_gen.h"
#include "ecdsa.h"
typedef struct {
secp256k1_fe_t order_as_fe;
secp256k1_fe_t p_minus_order;
} secp256k1_ecdsa_consts_t;
static const secp256k1_ecdsa_consts_t *secp256k1_ecdsa_consts = NULL;
static void secp256k1_ecdsa_start(void) {
if (secp256k1_ecdsa_consts != NULL)
return;
/* Allocate. */
secp256k1_ecdsa_consts_t *ret = (secp256k1_ecdsa_consts_t*)malloc(sizeof(secp256k1_ecdsa_consts_t));
unsigned char p[32];
secp256k1_num_get_bin(p, 32, &secp256k1_ge_consts->order);
secp256k1_fe_set_b32(&ret->order_as_fe, p);
secp256k1_fe_negate(&ret->p_minus_order, &ret->order_as_fe, 1);
secp256k1_fe_normalize(&ret->p_minus_order);
/* Set the global pointer. */
secp256k1_ecdsa_consts = ret;
}
static void secp256k1_ecdsa_stop(void) {
if (secp256k1_ecdsa_consts == NULL)
return;
secp256k1_ecdsa_consts_t *c = (secp256k1_ecdsa_consts_t*)secp256k1_ecmult_consts;
secp256k1_ecdsa_consts = NULL;
free(c);
}
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
if (sig[0] != 0x30) return 0;
int lenr = sig[3];
@ -26,18 +60,37 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch
if (lenr == 0) return 0;
if (sig[lenr+4] != 0x02) return 0;
if (lens == 0) return 0;
secp256k1_num_set_bin(&r->r, sig+4, lenr);
secp256k1_num_set_bin(&r->s, sig+6+lenr, lens);
const unsigned char *sp = sig + 6 + lenr;
while (lens > 0 && sp[0] == 0) {
lens--;
sp++;
}
if (lens > 32) return 0;
const unsigned char *rp = sig + 4;
while (lenr > 0 && rp[0] == 0) {
lenr--;
rp++;
}
if (lenr > 32) return 0;
unsigned char ra[32] = {0}, sa[32] = {0};
memcpy(ra + 32 - lenr, rp, lenr);
memcpy(sa + 32 - lens, sp, lens);
int overflow = 0;
secp256k1_scalar_set_b32(&r->r, ra, &overflow);
if (overflow) return 0;
secp256k1_scalar_set_b32(&r->s, sa, &overflow);
if (overflow) return 0;
return 1;
}
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
int lenR = (secp256k1_num_bits(&a->r) + 7)/8;
if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1))
lenR++;
int lenS = (secp256k1_num_bits(&a->s) + 7)/8;
if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1))
lenS++;
unsigned char r[33] = {0}, s[33] = {0};
secp256k1_scalar_get_b32(&r[1], &a->r);
secp256k1_scalar_get_b32(&s[1], &a->s);
unsigned char *rp = r, *sp = s;
int lenR = 33, lenS = 33;
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
if (*size < 6+lenS+lenR)
return 0;
*size = 6 + lenS + lenR;
@ -45,98 +98,67 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
sig[1] = 4 + lenS + lenR;
sig[2] = 0x02;
sig[3] = lenR;
secp256k1_num_get_bin(sig+4, lenR, &a->r);
memcpy(sig+4, rp, lenR);
sig[4+lenR] = 0x02;
sig[5+lenR] = lenS;
secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s);
memcpy(sig+lenR+6, sp, lenS);
return 1;
}
static int secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
return 0;
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
return 0;
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
static int secp256k1_ecdsa_sig_recompute(secp256k1_scalar_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
int ret = 0;
secp256k1_num_t sn, u1, u2;
secp256k1_num_init(&sn);
secp256k1_num_init(&u1);
secp256k1_num_init(&u2);
secp256k1_num_mod_inverse(&sn, &sig->s, &c->order);
secp256k1_num_mod_mul(&u1, &sn, message, &c->order);
secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order);
secp256k1_scalar_t sn, u1, u2;
secp256k1_scalar_inverse_var(&sn, &sig->s);
secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, &sig->r);
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (!secp256k1_gej_is_infinity(&pr)) {
secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
secp256k1_fe_normalize(&xr);
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
secp256k1_num_set_bin(r2, xrb, 32);
secp256k1_num_mod(r2, &c->order);
secp256k1_scalar_set_b32(r2, xrb, NULL);
ret = 1;
}
secp256k1_num_free(&sn);
secp256k1_num_free(&u1);
secp256k1_num_free(&u2);
return ret;
}
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
return 0;
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
return 0;
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
secp256k1_num_t rx;
secp256k1_num_init(&rx);
secp256k1_num_copy(&rx, &sig->r);
if (recid & 2) {
secp256k1_num_add(&rx, &rx, &c->order);
if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0)
return 0;
}
unsigned char brx[32];
secp256k1_num_get_bin(brx, 32, &rx);
secp256k1_num_free(&rx);
secp256k1_scalar_get_b32(brx, &sig->r);
secp256k1_fe_t fx;
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* Either rx < n (and n < p), or rx + n < p (checked above). */
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
if (recid & 2) {
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_consts->p_minus_order) >= 0)
return 0;
secp256k1_fe_add(&fx, &secp256k1_ecdsa_consts->order_as_fe);
}
secp256k1_ge_t x;
if (!secp256k1_ge_set_xo(&x, &fx, recid & 1))
return 0;
secp256k1_gej_t xj;
secp256k1_gej_set_ge(&xj, &x);
secp256k1_num_t rn, u1, u2;
secp256k1_num_init(&rn);
secp256k1_num_init(&u1);
secp256k1_num_init(&u2);
secp256k1_num_mod_inverse(&rn, &sig->r, &c->order);
secp256k1_num_mod_mul(&u1, &rn, message, &c->order);
secp256k1_num_sub(&u1, &c->order, &u1);
secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order);
secp256k1_scalar_t rn, u1, u2;
secp256k1_scalar_inverse_var(&rn, &sig->r);
secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_scalar_negate(&u1, &u1);
secp256k1_scalar_mul(&u2, &rn, &sig->s);
secp256k1_gej_t qj;
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
secp256k1_num_free(&rn);
secp256k1_num_free(&u1);
secp256k1_num_free(&u2);
return !secp256k1_gej_is_infinity(&qj);
}
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
secp256k1_num_t r2;
secp256k1_num_init(&r2);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
secp256k1_scalar_t r2;
int ret = 0;
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0;
secp256k1_num_free(&r2);
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2);
return ret;
}
@ -150,34 +172,30 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
int overflow = 0;
secp256k1_scalar_t sigr;
secp256k1_scalar_set_b32(&sigr, b, &overflow);
secp256k1_scalar_set_b32(&sig->r, b, &overflow);
if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_scalar_t n;
secp256k1_scalar_mul(&n, &sigr, seckey);
secp256k1_scalar_mul(&n, &sig->r, seckey);
secp256k1_scalar_add(&n, &n, message);
secp256k1_scalar_t sigs;
secp256k1_scalar_inverse(&sigs, nonce);
secp256k1_scalar_mul(&sigs, &sigs, &n);
secp256k1_scalar_inverse(&sig->s, nonce);
secp256k1_scalar_mul(&sig->s, &sig->s, &n);
secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
if (secp256k1_scalar_is_zero(&sigs))
if (secp256k1_scalar_is_zero(&sig->s))
return 0;
if (secp256k1_scalar_is_high(&sigs)) {
secp256k1_scalar_negate(&sigs, &sigs);
if (secp256k1_scalar_is_high(&sig->s)) {
secp256k1_scalar_negate(&sig->s, &sig->s);
if (recid)
*recid ^= 1;
}
secp256k1_scalar_get_num(&sig->s, &sigs);
secp256k1_scalar_get_num(&sig->r, &sigr);
return 1;
}
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) {
secp256k1_num_copy(&sig->r, r);
secp256k1_num_copy(&sig->s, s);
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s) {
sig->r = *r;
sig->s = *s;
}
#endif

View File

@ -9,7 +9,6 @@
#include "group.h"
#include "scalar.h"
#include "num.h"
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
@ -18,8 +17,8 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
#endif

View File

@ -9,7 +9,7 @@
#include "eckey.h"
#include "num.h"
#include "scalar.h"
#include "field.h"
#include "group.h"
#include "ecmult_gen.h"
@ -154,17 +154,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp
return 1;
}
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
return 0;
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_num_t one;
secp256k1_num_init(&one);
secp256k1_num_set_int(&one, 1);
secp256k1_scalar_t one;
secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, tweak);
secp256k1_num_free(&one);
if (secp256k1_gej_is_infinity(&pt))
return 0;
@ -180,19 +175,15 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp
return 1;
}
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
if (secp256k1_num_is_zero(tweak))
return 0;
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
if (secp256k1_scalar_is_zero(tweak))
return 0;
secp256k1_num_t zero;
secp256k1_num_init(&zero);
secp256k1_num_set_int(&zero, 0);
secp256k1_scalar_t zero;
secp256k1_scalar_set_int(&zero, 0);
secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_num_free(&zero);
secp256k1_ge_set_gej(key, &pt);
return 1;
}

View File

@ -14,6 +14,6 @@ static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void);
/** 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);
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng);
#endif

View File

@ -7,8 +7,8 @@
#ifndef _SECP256K1_ECMULT_IMPL_H_
#define _SECP256K1_ECMULT_IMPL_H_
#include "num.h"
#include "group.h"
#include "scalar.h"
#include "ecmult.h"
/* optimal for 128-bit and 256-bit exponents. */
@ -121,47 +121,51 @@ static void secp256k1_ecmult_stop(void) {
* 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.
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more
* - than the number of bits in 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_copy(&x, a);
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
secp256k1_scalar_t s = *a;
int sign = 1;
if (secp256k1_num_is_neg(&x)) {
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s);
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 set_bits = 0;
int bit = 0;
while (bit < 256) {
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
bit++;
continue;
}
int word = secp256k1_num_shift(&x, w);
while (zeroes) {
wnaf[ret++] = 0;
zeroes--;
while (set_bits < bit) {
wnaf[set_bits++] = 0;
}
int now = w;
if (bit + now > 256) {
now = 256 - bit;
}
int word = secp256k1_scalar_get_bits_var(&s, bit, now);
if (word & (1 << (w-1))) {
secp256k1_num_inc(&x);
wnaf[ret++] = sign * (word - (1 << w));
secp256k1_scalar_add_bit(&s, bit + w);
wnaf[set_bits++] = sign * (word - (1 << w));
} else {
wnaf[ret++] = sign * word;
wnaf[set_bits++] = sign * word;
}
zeroes = w-1;
bit += now;
}
return ret;
return set_bits;
}
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) {
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
#ifdef USE_ENDOMORPHISM
secp256k1_num_t na_1, na_lam;
secp256k1_scalar_t na_1, na_lam;
/* 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_var(&na_1, &na_lam, na);
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
/* build wnaf representation for na_1 and na_lam. */
int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
@ -170,7 +174,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
if (bits_na_lam > bits) bits = bits_na_lam;
#else
/* build wnaf representation for na. */
int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
int wnaf_na[256]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
int bits = bits_na;
#endif
@ -184,10 +188,10 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]);
/* Splitted G factors. */
secp256k1_num_t ng_1, ng_128;
secp256k1_scalar_t ng_1, ng_128;
/* 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);
secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
/* Build wnaf representation for ng_1 and ng_128 */
int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);

View File

@ -34,6 +34,7 @@
typedef struct {
secp256k1_num_t p;
secp256k1_fe_t order;
} secp256k1_fe_consts_t;
static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL;
@ -59,6 +60,9 @@ static int secp256k1_fe_is_odd(const secp256k1_fe_t *a);
/** Compare two field elements. Requires both inputs to be normalized */
static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
/** Compare two field elements. Requires both inputs to be normalized */
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
/** Set a field element equal to 32-byte big endian value. If succesful, the resulting field element is normalized. */
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a);

View File

@ -152,6 +152,20 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
| (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0;
}
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
for (int i = 9; i >= 0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
return 0;
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;

View File

@ -150,6 +150,20 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])) == 0;
}
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
for (int i = 4; i >= 0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
return 0;
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
for (int i=0; i<32; i++) {

View File

@ -75,6 +75,14 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
return ret;
}
SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
for (int i=FIELD_LIMBS; i>=0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
return 0;
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
for (int i=0; i<FIELD_LIMBS+1; i++)
r->n[i] = 0;

View File

@ -34,7 +34,6 @@ typedef struct {
#ifdef USE_ENDOMORPHISM
/* constants related to secp256k1's efficiently computable endomorphism */
secp256k1_fe_t beta;
secp256k1_num_t lambda, a1b2, b1, a2;
#endif
} secp256k1_ge_consts_t;
@ -112,10 +111,6 @@ static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a);
#ifdef USE_ENDOMORPHISM
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a);
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is
not more than 256 bits). */
static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a);
#endif
/** Clear a secp256k1_gej_t to prevent leaking sensitive information. */

View File

@ -414,30 +414,6 @@ static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
*r = *a;
secp256k1_fe_mul(&r->x, &r->x, beta);
}
static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;
secp256k1_num_copy(&bnn2, &c->order);
secp256k1_num_shift(&bnn2, 1);
secp256k1_num_mul(&bnc1, a, &c->a1b2);
secp256k1_num_add(&bnc1, &bnc1, &bnn2);
secp256k1_num_div(&bnc1, &bnc1, &c->order);
secp256k1_num_mul(&bnc2, a, &c->b1);
secp256k1_num_add(&bnc2, &bnc2, &bnn2);
secp256k1_num_div(&bnc2, &bnc2, &c->order);
secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2);
secp256k1_num_mul(&bnt2, &bnc2, &c->a2);
secp256k1_num_add(&bnt1, &bnt1, &bnt2);
secp256k1_num_sub(r1, a, &bnt1);
secp256k1_num_mul(&bnt1, &bnc1, &c->b1);
secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2);
secp256k1_num_sub(r2, &bnt1, &bnt2);
}
#endif
@ -462,31 +438,12 @@ static void secp256k1_ge_start(void) {
};
#ifdef USE_ENDOMORPHISM
/* properties of secp256k1's efficiently computable endomorphism */
static const unsigned char secp256k1_ge_consts_lambda[] = {
0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72
};
static const unsigned char secp256k1_ge_consts_beta[] = {
0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10,
0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9,
0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95,
0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee
};
static const unsigned char secp256k1_ge_consts_a1b2[] = {
0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
};
static const unsigned char secp256k1_ge_consts_b1[] = {
0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
};
static const unsigned char secp256k1_ge_consts_a2[] = {
0x01,
0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8
};
#endif
if (secp256k1_ge_consts == NULL) {
secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t));
@ -494,10 +451,6 @@ static void secp256k1_ge_start(void) {
secp256k1_num_copy(&ret->half_order, &ret->order);
secp256k1_num_shift(&ret->half_order, 1);
#ifdef USE_ENDOMORPHISM
secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda));
secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2));
secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2));
secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1));
VERIFY_CHECK(secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta));
#endif
secp256k1_fe_t g_x, g_y;

View File

@ -17,9 +17,6 @@
#error "Please select num implementation"
#endif
/** Clear a number to prevent the leak of sensitive data. */
static void secp256k1_num_clear(secp256k1_num_t *r);
/** Copy a number. */
static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a);
@ -30,15 +27,9 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec
/** Set a number to the value of a binary big-endian string. */
static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen);
/** Set a number equal to a (signed) integer. */
static void secp256k1_num_set_int(secp256k1_num_t *r, int a);
/** Compute a modular inverse. The input must be less than the modulus. */
static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m);
/** Multiply two numbers modulo another. */
static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m);
/** Compare the absolute value of two numbers. */
static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b);
@ -61,40 +52,16 @@ static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, cons
even if r was negative. */
static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m);
/** Calculate the number of bits in (the absolute value of) a number. */
static int secp256k1_num_bits(const secp256k1_num_t *a);
/** Right-shift the passed number by bits bits, and return those bits. */
static int secp256k1_num_shift(secp256k1_num_t *r, int bits);
/** Check whether a number is zero. */
static int secp256k1_num_is_zero(const secp256k1_num_t *a);
/** Check whether a number is odd. */
static int secp256k1_num_is_odd(const secp256k1_num_t *a);
/** Check whether a number is strictly negative. */
static int secp256k1_num_is_neg(const secp256k1_num_t *a);
/** Check whether a particular bit is set in a number. */
static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos);
/** Increase a number by 1. */
static void secp256k1_num_inc(secp256k1_num_t *r);
/** Set a number equal to the value of a hex string (unsigned). */
static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen);
/** Convert (the absolute value of) a number to a hexadecimal string. */
static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a);
/** Split a number into a low and high part. */
static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits);
/** Change a number's sign. */
static void secp256k1_num_negate(secp256k1_num_t *r);
/** Get a bunch of bits from a number. */
static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count);
#endif

View File

@ -22,35 +22,10 @@ static void secp256k1_num_sanity(const secp256k1_num_t *a) {
#define secp256k1_num_sanity(a) do { } while(0)
#endif
static void secp256k1_num_init(secp256k1_num_t *r) {
r->neg = 0;
r->limbs = 1;
r->data[0] = 0;
}
static void secp256k1_num_clear(secp256k1_num_t *r) {
memset(r, 0, sizeof(*r));
}
static void secp256k1_num_free(secp256k1_num_t *r) {
(void)r;
}
static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
*r = *a;
}
static int secp256k1_num_bits(const secp256k1_num_t *a) {
int ret=(a->limbs-1)*GMP_NUMB_BITS;
mp_limb_t x=a->data[a->limbs-1];
while (x) {
x >>= 1;
ret++;
}
return ret;
}
static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
unsigned char tmp[65];
int len = 0;
@ -81,12 +56,6 @@ static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, un
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
}
static void secp256k1_num_set_int(secp256k1_num_t *r, int a) {
r->limbs = 1;
r->neg = (a < 0);
r->data[0] = (a < 0) ? -a : a;
}
static void secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
r->limbs = a->limbs;
@ -165,10 +134,6 @@ static int secp256k1_num_is_zero(const secp256k1_num_t *a) {
return (a->limbs == 1 && a->data[0] == 0);
}
static int secp256k1_num_is_odd(const secp256k1_num_t *a) {
return a->data[0] & 1;
}
static int secp256k1_num_is_neg(const secp256k1_num_t *a) {
return (a->limbs > 1 || a->data[0] != 0) && a->neg;
}
@ -260,12 +225,6 @@ static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, cons
r->neg = a->neg ^ b->neg;
}
static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) {
secp256k1_num_mul(r, a, b);
secp256k1_num_mod(r, m);
}
static int secp256k1_num_shift(secp256k1_num_t *r, int bits) {
VERIFY_CHECK(bits <= GMP_NUMB_BITS);
mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits);
@ -274,107 +233,8 @@ static int secp256k1_num_shift(secp256k1_num_t *r, int bits) {
return ret;
}
static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1);
}
static void secp256k1_num_inc(secp256k1_num_t *r) {
mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1);
if (ret) {
VERIFY_CHECK(r->limbs < 2*NUM_LIMBS);
r->data[r->limbs++] = ret;
}
}
static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) {
static const unsigned char cvt[256] = {
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0
};
unsigned char num[257] = {};
for (int i=0; i<alen; i++) {
num[i] = cvt[(unsigned char)a[i]];
}
r->limbs = mpn_set_str(r->data, num, alen, 16);
r->neg = 0;
while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--;
}
static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) {
static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
unsigned char *tmp = malloc(257);
mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs);
VERIFY_CHECK(len <= rlen);
for (int i=0; i<len; i++) {
VERIFY_CHECK(rlen-len+i >= 0);
VERIFY_CHECK(rlen-len+i < rlen);
VERIFY_CHECK(tmp[i] < 16);
r[rlen-len+i] = cvt[tmp[i]];
}
for (int i=0; i<rlen-len; i++) {
VERIFY_CHECK(i >= 0);
VERIFY_CHECK(i < rlen);
r[i] = cvt[0];
}
free(tmp);
}
static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
VERIFY_CHECK(bits > 0);
rh->neg = a->neg;
if (bits >= a->limbs * GMP_NUMB_BITS) {
*rl = *a;
rh->limbs = 1;
rh->data[0] = 0;
return;
}
rl->limbs = 0;
rl->neg = a->neg;
int left = bits;
while (left >= GMP_NUMB_BITS) {
rl->data[rl->limbs] = a->data[rl->limbs];
rl->limbs++;
left -= GMP_NUMB_BITS;
}
if (left == 0) {
mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs);
rh->limbs = a->limbs - rl->limbs;
} else {
mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left);
rh->limbs = a->limbs - rl->limbs;
while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--;
}
if (left > 0) {
rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1);
rl->limbs++;
}
while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--;
}
static void secp256k1_num_negate(secp256k1_num_t *r) {
r->neg ^= 1;
}
static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) {
int ret = 0;
for (int i = 0; i < count; i++) {
ret |= ((a->data[(offset + i) / GMP_NUMB_BITS] >> ((offset + i) % GMP_NUMB_BITS)) & 1) << i;
}
return ret;
}
#endif

View File

@ -21,21 +21,33 @@
#error "Please select scalar implementation"
#endif
static void secp256k1_scalar_start(void);
static void secp256k1_scalar_stop(void);
/** Clear a scalar to prevent the leak of sensitive data. */
static void secp256k1_scalar_clear(secp256k1_scalar_t *r);
/** Access bits from a scalar. */
static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count);
/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */
static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count);
/** Access bits from a scalar. Not constant time. */
static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count);
/** Set a scalar from a big endian byte array. */
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow);
/** Set a scalar to an unsigned integer. */
static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v);
/** Convert a scalar to a byte array. */
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a);
/** Add two scalars together (modulo the group order). */
static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
/** Add a power of two to a scalar. The result is not allowed to overflow. */
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit);
/** Multiply two scalars (modulo the group order). */
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
@ -45,6 +57,9 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
/** Compute the inverse of a scalar (modulo the group order). */
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */
static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
/** Compute the complement of a scalar (modulo the group order). */
static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
@ -60,4 +75,14 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a);
/** Convert a scalar to a number. */
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a);
/** Compare two scalars. */
static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
#ifdef USE_ENDOMORPHISM
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
#endif
#endif

View File

@ -33,9 +33,27 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) {
r->d[3] = 0;
}
SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) {
VERIFY_CHECK((offset + count - 1) / 64 == offset / 64);
return (a->d[offset / 64] >> (offset % 64)) & ((((uint64_t)1) << count) - 1);
SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) {
r->d[0] = v;
r->d[1] = 0;
r->d[2] = 0;
r->d[3] = 0;
}
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6);
return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1);
}
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
VERIFY_CHECK(count < 32);
VERIFY_CHECK(offset + count <= 256);
if ((offset + count - 1) >> 6 == offset >> 6) {
return secp256k1_scalar_get_bits(a, offset, count);
} else {
VERIFY_CHECK((offset >> 6) + 1 < 4);
return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1);
}
}
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) {
@ -75,6 +93,22 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r));
}
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
VERIFY_CHECK(bit < 256);
uint128_t t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << bit);
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
#ifdef VERIFY
VERIFY_CHECK((t >> 64) == 0);
VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
#endif
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56;
r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56;
@ -356,4 +390,19 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
#undef extract
#undef extract_fast
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
r1->d[0] = a->d[0];
r1->d[1] = a->d[1];
r1->d[2] = 0;
r1->d[3] = 0;
r2->d[0] = a->d[2];
r2->d[1] = a->d[3];
r2->d[2] = 0;
r2->d[3] = 0;
}
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0;
}
#endif

View File

@ -45,9 +45,31 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) {
r->d[7] = 0;
}
SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) {
VERIFY_CHECK((offset + count - 1) / 32 == offset / 32);
return (a->d[offset / 32] >> (offset % 32)) & ((1 << count) - 1);
SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) {
r->d[0] = v;
r->d[1] = 0;
r->d[2] = 0;
r->d[3] = 0;
r->d[4] = 0;
r->d[5] = 0;
r->d[6] = 0;
r->d[7] = 0;
}
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5);
return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1);
}
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
VERIFY_CHECK(count < 32);
VERIFY_CHECK(offset + count <= 256);
if ((offset + count - 1) >> 5 == offset >> 5) {
return secp256k1_scalar_get_bits(a, offset, count);
} else {
VERIFY_CHECK((offset >> 5) + 1 < 8);
return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1);
}
}
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) {
@ -109,6 +131,30 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r));
}
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
VERIFY_CHECK(bit < 256);
uint64_t t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << bit);
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
r->d[1] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F));
r->d[2] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F));
r->d[3] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F));
r->d[4] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F));
r->d[5] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F));
r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F));
r->d[7] = t & 0xFFFFFFFFULL;
#ifdef VERIFY
VERIFY_CHECK((t >> 32) == 0);
VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
#endif
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24;
r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24;
@ -569,4 +615,27 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
#undef extract
#undef extract_fast
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
r1->d[0] = a->d[0];
r1->d[1] = a->d[1];
r1->d[2] = a->d[2];
r1->d[3] = a->d[3];
r1->d[4] = 0;
r1->d[5] = 0;
r1->d[6] = 0;
r1->d[7] = 0;
r2->d[0] = a->d[4];
r2->d[1] = a->d[5];
r2->d[2] = a->d[6];
r2->d[3] = a->d[7];
r2->d[4] = 0;
r2->d[5] = 0;
r2->d[6] = 0;
r2->d[7] = 0;
}
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0;
}
#endif

View File

@ -9,6 +9,7 @@
#include <string.h>
#include "group.h"
#include "scalar.h"
#if defined HAVE_CONFIG_H
@ -23,6 +24,54 @@
#error "Please select scalar implementation"
#endif
typedef struct {
#ifdef USE_ENDOMORPHISM
secp256k1_num_t a1b2, b1, a2;
#endif
} secp256k1_scalar_consts_t;
static const secp256k1_scalar_consts_t *secp256k1_scalar_consts = NULL;
static void secp256k1_scalar_start(void) {
if (secp256k1_scalar_consts != NULL)
return;
/* Allocate. */
secp256k1_scalar_consts_t *ret = (secp256k1_scalar_consts_t*)malloc(sizeof(secp256k1_scalar_consts_t));
#ifdef USE_ENDOMORPHISM
static const unsigned char secp256k1_scalar_consts_a1b2[] = {
0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
};
static const unsigned char secp256k1_scalar_consts_b1[] = {
0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
};
static const unsigned char secp256k1_scalar_consts_a2[] = {
0x01,
0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8
};
secp256k1_num_set_bin(&ret->a1b2, secp256k1_scalar_consts_a1b2, sizeof(secp256k1_scalar_consts_a1b2));
secp256k1_num_set_bin(&ret->a2, secp256k1_scalar_consts_a2, sizeof(secp256k1_scalar_consts_a2));
secp256k1_num_set_bin(&ret->b1, secp256k1_scalar_consts_b1, sizeof(secp256k1_scalar_consts_b1));
#endif
/* Set the global pointer. */
secp256k1_scalar_consts = ret;
}
static void secp256k1_scalar_stop(void) {
if (secp256k1_scalar_consts == NULL)
return;
secp256k1_scalar_consts_t *c = (secp256k1_scalar_consts_t*)secp256k1_scalar_consts;
secp256k1_scalar_consts = NULL;
free(c);
}
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) {
unsigned char c[32];
secp256k1_scalar_get_b32(c, a);
@ -181,4 +230,65 @@ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal
secp256k1_scalar_mul(r, t, &x6); /* 111111 */
}
static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) {
#if defined(USE_SCALAR_INV_BUILTIN)
secp256k1_scalar_inverse(r, x);
#elif defined(USE_SCALAR_INV_NUM)
unsigned char b[32];
secp256k1_scalar_get_b32(b, x);
secp256k1_num_t n;
secp256k1_num_set_bin(&n, b, 32);
secp256k1_num_mod_inverse(&n, &n, &secp256k1_ge_consts->order);
secp256k1_num_get_bin(b, 32, &n);
secp256k1_scalar_set_b32(r, b, NULL);
#else
#error "Please select scalar inverse implementation"
#endif
}
#ifdef USE_ENDOMORPHISM
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
unsigned char b[32];
secp256k1_scalar_get_b32(b, a);
secp256k1_num_t na;
secp256k1_num_set_bin(&na, b, 32);
secp256k1_num_t rn1, rn2;
const secp256k1_scalar_consts_t *c = secp256k1_scalar_consts;
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;
secp256k1_num_copy(&bnn2, order);
secp256k1_num_shift(&bnn2, 1);
secp256k1_num_mul(&bnc1, &na, &c->a1b2);
secp256k1_num_add(&bnc1, &bnc1, &bnn2);
secp256k1_num_div(&bnc1, &bnc1, order);
secp256k1_num_mul(&bnc2, &na, &c->b1);
secp256k1_num_add(&bnc2, &bnc2, &bnn2);
secp256k1_num_div(&bnc2, &bnc2, order);
secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2);
secp256k1_num_mul(&bnt2, &bnc2, &c->a2);
secp256k1_num_add(&bnt1, &bnt1, &bnt2);
secp256k1_num_sub(&rn1, &na, &bnt1);
secp256k1_num_mul(&bnt1, &bnc1, &c->b1);
secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2);
secp256k1_num_sub(&rn2, &bnt1, &bnt2);
secp256k1_num_get_bin(b, 32, &rn1);
secp256k1_scalar_set_b32(r1, b, NULL);
if (secp256k1_num_is_neg(&rn1)) {
secp256k1_scalar_negate(r1, r1);
}
secp256k1_num_get_bin(b, 32, &rn2);
secp256k1_scalar_set_b32(r2, b, NULL);
if (secp256k1_num_is_neg(&rn2)) {
secp256k1_scalar_negate(r2, r2);
}
}
#endif
#endif

View File

@ -21,6 +21,8 @@
void secp256k1_start(unsigned int flags) {
secp256k1_fe_start();
secp256k1_ge_start();
secp256k1_scalar_start();
secp256k1_ecdsa_start();
if (flags & SECP256K1_START_SIGN) {
secp256k1_ecmult_gen_start();
}
@ -32,6 +34,8 @@ void secp256k1_start(unsigned int flags) {
void secp256k1_stop(void) {
secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
secp256k1_ecdsa_stop();
secp256k1_scalar_stop();
secp256k1_ge_stop();
secp256k1_fe_stop();
}
@ -43,11 +47,13 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned
DEBUG_CHECK(sig != NULL);
DEBUG_CHECK(pubkey != NULL);
unsigned char msg32[32] = {0};
memcpy(msg32 + 32 - msglen, msg, msglen);
int ret = -3;
secp256k1_num_t m;
secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t s;
secp256k1_ge_t q;
secp256k1_num_set_bin(&m, msg, msglen);
secp256k1_scalar_set_b32(&m, msg32, NULL);
if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
ret = -1;
@ -123,8 +129,8 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid);
}
if (ret) {
secp256k1_num_get_bin(sig64, 32, &sig.r);
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
secp256k1_scalar_get_b32(sig64, &sig.r);
secp256k1_scalar_get_b32(sig64 + 32, &sig.s);
}
secp256k1_scalar_clear(&msg);
secp256k1_scalar_clear(&non);
@ -142,11 +148,20 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const
DEBUG_CHECK(recid >= 0 && recid <= 3);
int ret = 0;
secp256k1_num_t m;
unsigned char msg32[32] = {0};
memcpy(msg32 + 32 - msglen, msg, msglen);
secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t sig;
secp256k1_num_set_bin(&sig.r, sig64, 32);
secp256k1_num_set_bin(&sig.s, sig64 + 32, 32);
secp256k1_num_set_bin(&m, msg, msglen);
int overflow = 0;
secp256k1_scalar_set_b32(&sig.r, sig64, &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_set_b32(&m, msg32, NULL);
secp256k1_ge_t q;
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
@ -224,8 +239,12 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
secp256k1_num_t term;
secp256k1_num_set_bin(&term, tweak, 32);
secp256k1_scalar_t term;
int overflow = 0;
secp256k1_scalar_set_b32(&term, tweak, &overflow);
if (overflow) {
return 0;
}
secp256k1_ge_t p;
int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {
@ -264,8 +283,12 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
secp256k1_num_t factor;
secp256k1_num_set_bin(&factor, tweak, 32);
secp256k1_scalar_t factor;
int overflow = 0;
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
if (overflow) {
return 0;
}
secp256k1_ge_t p;
int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {

View File

@ -100,6 +100,18 @@ void random_scalar_order_test(secp256k1_scalar_t *num) {
} while(1);
}
void random_scalar_order(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
secp256k1_rand256(b32);
int overflow = 0;
secp256k1_scalar_set_b32(num, b32, &overflow);
if (overflow || secp256k1_scalar_is_zero(num))
continue;
break;
} while(1);
}
void random_num_order(secp256k1_num_t *num) {
do {
unsigned char b32[32];
@ -113,39 +125,6 @@ void random_num_order(secp256k1_num_t *num) {
} while(1);
}
void test_num_copy_inc_cmp(void) {
secp256k1_num_t n1,n2;
random_num_order(&n1);
secp256k1_num_copy(&n2, &n1);
CHECK(secp256k1_num_eq(&n1, &n2));
CHECK(secp256k1_num_eq(&n2, &n1));
secp256k1_num_inc(&n2);
CHECK(!secp256k1_num_eq(&n1, &n2));
CHECK(!secp256k1_num_eq(&n2, &n1));
}
void test_num_get_set_hex(void) {
secp256k1_num_t n1,n2;
random_num_order_test(&n1);
char c[64];
secp256k1_num_get_hex(c, 64, &n1);
secp256k1_num_set_hex(&n2, c, 64);
CHECK(secp256k1_num_eq(&n1, &n2));
for (int i=0; i<64; i++) {
/* check whether the lower 4 bits correspond to the last hex character */
int low1 = secp256k1_num_shift(&n1, 4);
int lowh = c[63];
int low2 = ((lowh>>6)*9+(lowh-'0'))&15;
CHECK(low1 == low2);
/* shift bits off the hex representation, and compare */
memmove(c+1, c, 63);
c[0] = '0';
secp256k1_num_set_hex(&n2, c, 64);
CHECK(secp256k1_num_eq(&n1, &n2));
}
}
void test_num_get_set_bin(void) {
secp256k1_num_t n1,n2;
random_num_order_test(&n1);
@ -166,18 +145,6 @@ void test_num_get_set_bin(void) {
}
}
void run_num_int(void) {
secp256k1_num_t n1;
for (int i=-255; i<256; i++) {
unsigned char c1[3] = {};
c1[2] = abs(i);
unsigned char c2[3] = {0x11,0x22,0x33};
secp256k1_num_set_int(&n1, i);
secp256k1_num_get_bin(c2, 3, &n1);
CHECK(memcmp(c1, c2, 3) == 0);
}
}
void test_num_negate(void) {
secp256k1_num_t n1;
secp256k1_num_t n2;
@ -229,25 +196,14 @@ void test_num_add_sub(void) {
void run_num_smalltests(void) {
for (int i=0; i<100*count; i++) {
test_num_copy_inc_cmp();
test_num_get_set_hex();
test_num_get_set_bin();
test_num_negate();
test_num_add_sub();
}
run_num_int();
}
/***** SCALAR TESTS *****/
int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) {
secp256k1_scalar_t t;
secp256k1_scalar_negate(&t, s2);
secp256k1_scalar_add(&t, &t, s1);
int ret = secp256k1_scalar_is_zero(&t);
return ret;
}
void scalar_test(void) {
unsigned char c[32];
@ -278,15 +234,38 @@ void scalar_test(void) {
{
/* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */
secp256k1_num_t n, t, m;
secp256k1_num_set_int(&n, 0);
secp256k1_num_set_int(&m, 16);
secp256k1_scalar_t n;
secp256k1_scalar_set_int(&n, 0);
for (int i = 0; i < 256; i += 4) {
secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4));
secp256k1_num_mul(&n, &n, &m);
secp256k1_num_add(&n, &n, &t);
secp256k1_scalar_t t;
secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4));
for (int j = 0; j < 4; j++) {
secp256k1_scalar_add(&n, &n, &n);
}
secp256k1_scalar_add(&n, &n, &t);
}
CHECK(secp256k1_num_eq(&n, &snum));
CHECK(secp256k1_scalar_eq(&n, &s));
}
{
/* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */
secp256k1_scalar_t n;
secp256k1_scalar_set_int(&n, 0);
int i = 0;
while (i < 256) {
int now = (secp256k1_rand32() % 15) + 1;
if (now + i > 256) {
now = 256 - i;
}
secp256k1_scalar_t t;
secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now));
for (int j = 0; j < now; j++) {
secp256k1_scalar_add(&n, &n, &n);
}
secp256k1_scalar_add(&n, &n, &t);
i += now;
}
CHECK(secp256k1_scalar_eq(&n, &s));
}
{
@ -382,6 +361,24 @@ void scalar_test(void) {
CHECK(secp256k1_scalar_eq(&r1, &r2));
}
{
/* Test add_bit. */
int bit = secp256k1_rand32() % 256;
secp256k1_scalar_t b;
secp256k1_scalar_set_int(&b, 1);
CHECK(secp256k1_scalar_is_one(&b));
for (int i = 0; i < bit; i++) {
secp256k1_scalar_add(&b, &b, &b);
}
secp256k1_scalar_t r1 = s1, r2 = s1;
secp256k1_scalar_add(&r1, &r1, &b);
if (!(secp256k1_scalar_get_bits(&s1, 255, 1) == 1 && secp256k1_scalar_get_bits(&r1, 255, 1) == 0)) {
/* No overflow happened. */
secp256k1_scalar_add_bit(&r2, bit);
CHECK(secp256k1_scalar_eq(&r1, &r2));
}
}
{
/* Test commutativity of mul. */
secp256k1_scalar_t r1, r2;
@ -705,35 +702,47 @@ void run_ecmult_chain(void) {
secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64));
secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
/* two random initial factors xn and gn */
secp256k1_num_t xn;
secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
secp256k1_num_t gn;
secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
static const unsigned char xni[32] = {
0x84, 0xcc, 0x54, 0x52, 0xf7, 0xfd, 0xe1, 0xed,
0xb4, 0xd3, 0x8a, 0x8c, 0xe9, 0xb1, 0xb8, 0x4c,
0xce, 0xf3, 0x1f, 0x14, 0x6e, 0x56, 0x9b, 0xe9,
0x70, 0x5d, 0x35, 0x7a, 0x42, 0x98, 0x54, 0x07
};
secp256k1_scalar_t xn;
secp256k1_scalar_set_b32(&xn, xni, NULL);
static const unsigned char gni[32] = {
0xa1, 0xe5, 0x8d, 0x22, 0x55, 0x3d, 0xcd, 0x42,
0xb2, 0x39, 0x80, 0x62, 0x5d, 0x4c, 0x57, 0xa9,
0x6e, 0x93, 0x23, 0xd4, 0x2b, 0x31, 0x52, 0xe5,
0xca, 0x2c, 0x39, 0x90, 0xed, 0xc7, 0xc9, 0xde
};
secp256k1_scalar_t gn;
secp256k1_scalar_set_b32(&gn, gni, NULL);
/* two small multipliers to be applied to xn and gn in every iteration: */
secp256k1_num_t xf;
secp256k1_num_set_hex(&xf, "1337", 4);
secp256k1_num_t gf;
secp256k1_num_set_hex(&gf, "7113", 4);
static const unsigned char xfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x13,0x37};
secp256k1_scalar_t xf;
secp256k1_scalar_set_b32(&xf, xfi, NULL);
static const unsigned char gfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x71,0x13};
secp256k1_scalar_t gf;
secp256k1_scalar_set_b32(&gf, gfi, NULL);
/* accumulators with the resulting coefficients to A and G */
secp256k1_num_t ae;
secp256k1_num_set_int(&ae, 1);
secp256k1_num_t ge;
secp256k1_num_set_int(&ge, 0);
secp256k1_scalar_t ae;
secp256k1_scalar_set_int(&ae, 1);
secp256k1_scalar_t ge;
secp256k1_scalar_set_int(&ge, 0);
/* the point being computed */
secp256k1_gej_t x = a;
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; */
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);
secp256k1_num_mod_mul(&ge, &ge, &xn, order);
secp256k1_num_add(&ge, &ge, &gn);
secp256k1_num_mod(&ge, order);
secp256k1_scalar_mul(&ae, &ae, &xn);
secp256k1_scalar_mul(&ge, &ge, &xn);
secp256k1_scalar_add(&ge, &ge, &gn);
/* modify xn and gn */
secp256k1_num_mod_mul(&xn, &xn, &xf, order);
secp256k1_num_mod_mul(&gn, &gn, &gf, order);
secp256k1_scalar_mul(&xn, &xn, &xf);
secp256k1_scalar_mul(&gn, &gn, &gf);
/* verify */
if (i == 19999) {
@ -753,13 +762,16 @@ void run_ecmult_chain(void) {
}
void test_point_times_order(const secp256k1_gej_t *point) {
/* multiplying a point by the order results in O */
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
secp256k1_num_t zero;
secp256k1_num_set_int(&zero, 0);
secp256k1_gej_t res;
secp256k1_ecmult(&res, point, order, order); /* calc res = order * point + order * G; */
CHECK(secp256k1_gej_is_infinity(&res));
/* X * (point + G) + (order-X) * (pointer + G) = 0 */
secp256k1_scalar_t x;
random_scalar_order_test(&x);
secp256k1_scalar_t nx;
secp256k1_scalar_negate(&nx, &x);
secp256k1_gej_t res1, res2;
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_gej_add_var(&res1, &res1, &res2);
CHECK(secp256k1_gej_is_infinity(&res1));
}
void run_point_times_order(void) {
@ -780,15 +792,16 @@ void run_point_times_order(void) {
CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
}
void test_wnaf(const secp256k1_num_t *number, int w) {
secp256k1_num_t x, two, t;
secp256k1_num_set_int(&x, 0);
secp256k1_num_set_int(&two, 2);
int wnaf[257];
void test_wnaf(const secp256k1_scalar_t *number, int w) {
secp256k1_scalar_t x, two, t;
secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&two, 2);
int wnaf[256];
int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
CHECK(bits <= 256);
int zeroes = -1;
for (int i=bits-1; i>=0; i--) {
secp256k1_num_mul(&x, &x, &two);
secp256k1_scalar_mul(&x, &x, &two);
int v = wnaf[i];
if (v) {
CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */
@ -800,18 +813,23 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */
zeroes++;
}
secp256k1_num_set_int(&t, v);
secp256k1_num_add(&x, &x, &t);
if (v >= 0) {
secp256k1_scalar_set_int(&t, v);
} else {
secp256k1_scalar_set_int(&t, -v);
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_add(&x, &x, &t);
}
CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */
CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */
}
void run_wnaf(void) {
secp256k1_num_t n;
secp256k1_scalar_t n;
for (int i=0; i<count; i++) {
random_num_order(&n);
random_scalar_order(&n);
if (i % 1)
secp256k1_num_negate(&n);
secp256k1_scalar_negate(&n, &n);
test_wnaf(&n, 4+(i%10));
}
}
@ -831,11 +849,11 @@ void test_ecdsa_sign_verify(void) {
secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecdsa_sig_t sig;
random_sign(&sig, &key, &msg, NULL);
secp256k1_num_t msg_num;
secp256k1_scalar_get_num(&msg_num, &msg);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
secp256k1_num_inc(&msg_num);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
secp256k1_scalar_t one;
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
}
void run_ecdsa_sign_verify(void) {
@ -1023,11 +1041,12 @@ void test_ecdsa_openssl(void) {
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
secp256k1_ecdsa_sig_t sig;
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
secp256k1_num_t msg_num;
secp256k1_scalar_get_num(&msg_num, &msg);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
secp256k1_num_inc(&sig.r);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
secp256k1_scalar_t one;
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_t msg2;
secp256k1_scalar_add(&msg2, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg2));
random_sign(&sig, &key, &msg, NULL);
int secp_sigsize = 80;