Switch all EC/ECDSA logic from num to scalar

This commit is contained in:
Pieter Wuille 2014-11-26 17:26:39 +01:00
parent 6794be6080
commit f24041d6aa
15 changed files with 285 additions and 192 deletions

View File

@ -7,17 +7,21 @@
#ifndef _SECP256K1_ECDSA_ #ifndef _SECP256K1_ECDSA_
#define _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 { typedef struct {
secp256k1_num_t r, s; secp256k1_scalar_t r, s;
} secp256k1_ecdsa_sig_t; } 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_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_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_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 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_num_t *r, const secp256k1_num_t *s); static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
#endif #endif

View File

@ -8,13 +8,47 @@
#ifndef _SECP256K1_ECDSA_IMPL_H_ #ifndef _SECP256K1_ECDSA_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_ #define _SECP256K1_ECDSA_IMPL_H_
#include "num.h" #include "scalar.h"
#include "field.h" #include "field.h"
#include "group.h" #include "group.h"
#include "ecmult.h" #include "ecmult.h"
#include "ecmult_gen.h" #include "ecmult_gen.h"
#include "ecdsa.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) { static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
if (sig[0] != 0x30) return 0; if (sig[0] != 0x30) return 0;
int lenr = sig[3]; 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 (lenr == 0) return 0;
if (sig[lenr+4] != 0x02) return 0; if (sig[lenr+4] != 0x02) return 0;
if (lens == 0) return 0; if (lens == 0) return 0;
secp256k1_num_set_bin(&r->r, sig+4, lenr); const unsigned char *sp = sig + 6 + lenr;
secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); 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; return 1;
} }
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { 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; unsigned char r[33] = {0}, s[33] = {0};
if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) secp256k1_scalar_get_b32(&r[1], &a->r);
lenR++; secp256k1_scalar_get_b32(&s[1], &a->s);
int lenS = (secp256k1_num_bits(&a->s) + 7)/8; unsigned char *rp = r, *sp = s;
if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) int lenR = 33, lenS = 33;
lenS++; 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) if (*size < 6+lenS+lenR)
return 0; return 0;
*size = 6 + lenS + lenR; *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[1] = 4 + lenS + lenR;
sig[2] = 0x02; sig[2] = 0x02;
sig[3] = lenR; sig[3] = lenR;
secp256k1_num_get_bin(sig+4, lenR, &a->r); memcpy(sig+4, rp, lenR);
sig[4+lenR] = 0x02; sig[4+lenR] = 0x02;
sig[5+lenR] = lenS; sig[5+lenR] = lenS;
secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); memcpy(sig+lenR+6, sp, lenS);
return 1; 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) { 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) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
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)
return 0; return 0;
int ret = 0; int ret = 0;
secp256k1_num_t sn, u1, u2; secp256k1_scalar_t sn, u1, u2;
secp256k1_num_init(&sn); secp256k1_scalar_inverse_var(&sn, &sig->s);
secp256k1_num_init(&u1); secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_num_init(&u2); secp256k1_scalar_mul(&u2, &sn, &sig->r);
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_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (!secp256k1_gej_is_infinity(&pr)) { if (!secp256k1_gej_is_infinity(&pr)) {
secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr); secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
secp256k1_fe_normalize(&xr); secp256k1_fe_normalize(&xr);
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
secp256k1_num_set_bin(r2, xrb, 32); secp256k1_scalar_set_b32(r2, xrb, NULL);
secp256k1_num_mod(r2, &c->order);
ret = 1; ret = 1;
} }
secp256k1_num_free(&sn);
secp256k1_num_free(&u1);
secp256k1_num_free(&u2);
return ret; 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) { static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
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)
return 0; 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]; unsigned char brx[32];
secp256k1_num_get_bin(brx, 32, &rx); secp256k1_scalar_get_b32(brx, &sig->r);
secp256k1_num_free(&rx);
secp256k1_fe_t fx; 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; secp256k1_ge_t x;
if (!secp256k1_ge_set_xo(&x, &fx, recid & 1)) if (!secp256k1_ge_set_xo(&x, &fx, recid & 1))
return 0; return 0;
secp256k1_gej_t xj; secp256k1_gej_t xj;
secp256k1_gej_set_ge(&xj, &x); secp256k1_gej_set_ge(&xj, &x);
secp256k1_num_t rn, u1, u2; secp256k1_scalar_t rn, u1, u2;
secp256k1_num_init(&rn); secp256k1_scalar_inverse_var(&rn, &sig->r);
secp256k1_num_init(&u1); secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_num_init(&u2); secp256k1_scalar_negate(&u1, &u1);
secp256k1_num_mod_inverse(&rn, &sig->r, &c->order); secp256k1_scalar_mul(&u2, &rn, &sig->s);
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_gej_t qj; secp256k1_gej_t qj;
secp256k1_ecmult(&qj, &xj, &u2, &u1); secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj); 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); 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) { static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
secp256k1_num_t r2; secp256k1_scalar_t r2;
secp256k1_num_init(&r2);
int ret = 0; int ret = 0;
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2);
secp256k1_num_free(&r2);
return ret; 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_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x); secp256k1_fe_get_b32(b, &r.x);
int overflow = 0; int overflow = 0;
secp256k1_scalar_t sigr; secp256k1_scalar_set_b32(&sig->r, b, &overflow);
secp256k1_scalar_set_b32(&sigr, b, &overflow);
if (recid) if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_scalar_t n; 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_add(&n, &n, message);
secp256k1_scalar_t sigs; secp256k1_scalar_inverse(&sig->s, nonce);
secp256k1_scalar_inverse(&sigs, nonce); secp256k1_scalar_mul(&sig->s, &sig->s, &n);
secp256k1_scalar_mul(&sigs, &sigs, &n);
secp256k1_scalar_clear(&n); secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp); secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r); secp256k1_ge_clear(&r);
if (secp256k1_scalar_is_zero(&sigs)) if (secp256k1_scalar_is_zero(&sig->s))
return 0; return 0;
if (secp256k1_scalar_is_high(&sigs)) { if (secp256k1_scalar_is_high(&sig->s)) {
secp256k1_scalar_negate(&sigs, &sigs); secp256k1_scalar_negate(&sig->s, &sig->s);
if (recid) if (recid)
*recid ^= 1; *recid ^= 1;
} }
secp256k1_scalar_get_num(&sig->s, &sigs);
secp256k1_scalar_get_num(&sig->r, &sigr);
return 1; return 1;
} }
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s) {
secp256k1_num_copy(&sig->r, r); sig->r = *r;
secp256k1_num_copy(&sig->s, s); sig->s = *s;
} }
#endif #endif

View File

@ -9,7 +9,6 @@
#include "group.h" #include "group.h"
#include "scalar.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_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); 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_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_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_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 #endif

View File

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

View File

@ -14,6 +14,6 @@ static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void); static void secp256k1_ecmult_stop(void);
/** Double multiply: R = na*A + ng*G */ /** 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 #endif

View File

@ -7,7 +7,6 @@
#ifndef _SECP256K1_ECMULT_IMPL_H_ #ifndef _SECP256K1_ECMULT_IMPL_H_
#define _SECP256K1_ECMULT_IMPL_H_ #define _SECP256K1_ECMULT_IMPL_H_
#include "num.h"
#include "group.h" #include "group.h"
#include "scalar.h" #include "scalar.h"
#include "ecmult.h" #include "ecmult.h"
@ -125,22 +124,13 @@ static void secp256k1_ecmult_stop(void) {
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more * - 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. * - 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) { static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
secp256k1_num_t x; secp256k1_scalar_t s = *a;
secp256k1_num_copy(&x, a);
int sign = 1;
if (secp256k1_num_is_neg(&x)) {
sign = -1;
secp256k1_num_negate(&x);
}
unsigned char cr[32];
secp256k1_num_get_bin(cr, 32, &x);
secp256k1_scalar_t s;
secp256k1_scalar_set_b32(&s, cr, NULL);
int sign = 1;
if (secp256k1_scalar_get_bits(&s, 255, 1)) { if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s); secp256k1_scalar_negate(&s, &s);
sign *= -1; sign = -1;
} }
int set_bits = 0; int set_bits = 0;
@ -169,13 +159,13 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
return set_bits; 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; const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
#ifdef USE_ENDOMORPHISM #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) */ /* 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. */ /* 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); int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
@ -198,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]); secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]);
/* Splitted G factors. */ /* 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) */ /* 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 */ /* 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); 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 { typedef struct {
secp256k1_num_t p; secp256k1_num_t p;
secp256k1_fe_t order;
} secp256k1_fe_consts_t; } secp256k1_fe_consts_t;
static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL; 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 */ /** 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); 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. */ /** 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); 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; | (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) { 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[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; 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; 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) { 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[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
for (int i=0; i<32; i++) { 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; 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) { static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
for (int i=0; i<FIELD_LIMBS+1; i++) for (int i=0; i<FIELD_LIMBS+1; i++)
r->n[i] = 0; r->n[i] = 0;

View File

@ -72,6 +72,9 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a);
/** Convert a scalar to a number. */ /** Convert a scalar to a number. */
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a); 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); static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM

View File

@ -401,4 +401,8 @@ static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_
r2->d[3] = 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 #endif

View File

@ -634,4 +634,8 @@ static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_
r2->d[7] = 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 #endif

View File

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

View File

@ -100,6 +100,18 @@ void random_scalar_order_test(secp256k1_scalar_t *num) {
} while(1); } 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) { void random_num_order(secp256k1_num_t *num) {
do { do {
unsigned char b32[32]; unsigned char b32[32];
@ -240,14 +252,6 @@ void run_num_smalltests(void) {
/***** SCALAR TESTS *****/ /***** 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) { void scalar_test(void) {
unsigned char c[32]; unsigned char c[32];
@ -746,35 +750,47 @@ void run_ecmult_chain(void) {
secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64)); secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64));
secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay); secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
/* two random initial factors xn and gn */ /* two random initial factors xn and gn */
secp256k1_num_t xn; static const unsigned char xni[32] = {
secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64); 0x84, 0xcc, 0x54, 0x52, 0xf7, 0xfd, 0xe1, 0xed,
secp256k1_num_t gn; 0xb4, 0xd3, 0x8a, 0x8c, 0xe9, 0xb1, 0xb8, 0x4c,
secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64); 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: */ /* two small multipliers to be applied to xn and gn in every iteration: */
secp256k1_num_t xf; 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_num_set_hex(&xf, "1337", 4); secp256k1_scalar_t xf;
secp256k1_num_t gf; secp256k1_scalar_set_b32(&xf, xfi, NULL);
secp256k1_num_set_hex(&gf, "7113", 4); 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 */ /* accumulators with the resulting coefficients to A and G */
secp256k1_num_t ae; secp256k1_scalar_t ae;
secp256k1_num_set_int(&ae, 1); secp256k1_scalar_set_int(&ae, 1);
secp256k1_num_t ge; secp256k1_scalar_t ge;
secp256k1_num_set_int(&ge, 0); secp256k1_scalar_set_int(&ge, 0);
/* the point being computed */ /* the point being computed */
secp256k1_gej_t x = a; secp256k1_gej_t x = a;
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
for (int i=0; i<200*count; i++) { for (int i=0; i<200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */ /* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&x, &x, &xn, &gn); secp256k1_ecmult(&x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */ /* 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) */ /* 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_scalar_mul(&ae, &ae, &xn);
secp256k1_num_mod_mul(&ge, &ge, &xn, order); secp256k1_scalar_mul(&ge, &ge, &xn);
secp256k1_num_add(&ge, &ge, &gn); secp256k1_scalar_add(&ge, &ge, &gn);
secp256k1_num_mod(&ge, order);
/* modify xn and gn */ /* modify xn and gn */
secp256k1_num_mod_mul(&xn, &xn, &xf, order); secp256k1_scalar_mul(&xn, &xn, &xf);
secp256k1_num_mod_mul(&gn, &gn, &gf, order); secp256k1_scalar_mul(&gn, &gn, &gf);
/* verify */ /* verify */
if (i == 19999) { if (i == 19999) {
@ -795,10 +811,10 @@ void run_ecmult_chain(void) {
void test_point_times_order(const secp256k1_gej_t *point) { void test_point_times_order(const secp256k1_gej_t *point) {
/* X * (point + G) + (order-X) * (pointer + G) = 0 */ /* X * (point + G) + (order-X) * (pointer + G) = 0 */
secp256k1_num_t x; secp256k1_scalar_t x;
random_num_order_test(&x); random_scalar_order_test(&x);
secp256k1_num_t nx; secp256k1_scalar_t nx;
secp256k1_num_sub(&nx, &secp256k1_ge_consts->order, &x); secp256k1_scalar_negate(&nx, &x);
secp256k1_gej_t res1, res2; secp256k1_gej_t res1, res2;
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ 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_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
@ -824,16 +840,16 @@ void run_point_times_order(void) {
CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0); CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
} }
void test_wnaf(const secp256k1_num_t *number, int w) { void test_wnaf(const secp256k1_scalar_t *number, int w) {
secp256k1_num_t x, two, t; secp256k1_scalar_t x, two, t;
secp256k1_num_set_int(&x, 0); secp256k1_scalar_set_int(&x, 0);
secp256k1_num_set_int(&two, 2); secp256k1_scalar_set_int(&two, 2);
int wnaf[256]; int wnaf[256];
int bits = secp256k1_ecmult_wnaf(wnaf, number, w); int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
CHECK(bits <= 256); CHECK(bits <= 256);
int zeroes = -1; int zeroes = -1;
for (int i=bits-1; i>=0; i--) { for (int i=bits-1; i>=0; i--) {
secp256k1_num_mul(&x, &x, &two); secp256k1_scalar_mul(&x, &x, &two);
int v = wnaf[i]; int v = wnaf[i];
if (v) { if (v) {
CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */
@ -845,21 +861,23 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */
zeroes++; zeroes++;
} }
secp256k1_num_set_int(&t, v); if (v >= 0) {
secp256k1_num_add(&x, &x, &t); secp256k1_scalar_set_int(&t, v);
} else {
secp256k1_scalar_set_int(&t, -v);
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_add(&x, &x, &t);
} }
secp256k1_num_t xcopy = x, ncopy = *number; CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */
secp256k1_num_mod(&xcopy, &secp256k1_ge_consts->order);
secp256k1_num_mod(&ncopy, &secp256k1_ge_consts->order);
CHECK(secp256k1_num_eq(&xcopy, &ncopy)); /* check that wnaf represents number */
} }
void run_wnaf(void) { void run_wnaf(void) {
secp256k1_num_t n; secp256k1_scalar_t n;
for (int i=0; i<count; i++) { for (int i=0; i<count; i++) {
random_num_order(&n); random_scalar_order(&n);
if (i % 1) if (i % 1)
secp256k1_num_negate(&n); secp256k1_scalar_negate(&n, &n);
test_wnaf(&n, 4+(i%10)); test_wnaf(&n, 4+(i%10));
} }
} }
@ -879,11 +897,11 @@ void test_ecdsa_sign_verify(void) {
secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
random_sign(&sig, &key, &msg, NULL); random_sign(&sig, &key, &msg, NULL);
secp256k1_num_t msg_num; CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
secp256k1_scalar_get_num(&msg_num, &msg); secp256k1_scalar_t one;
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); secp256k1_scalar_set_int(&one, 1);
secp256k1_num_inc(&msg_num); secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
} }
void run_ecdsa_sign_verify(void) { void run_ecdsa_sign_verify(void) {
@ -1071,11 +1089,12 @@ void test_ecdsa_openssl(void) {
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
secp256k1_num_t msg_num; CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
secp256k1_scalar_get_num(&msg_num, &msg); secp256k1_scalar_t one;
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); secp256k1_scalar_set_int(&one, 1);
secp256k1_num_inc(&sig.r); secp256k1_scalar_t msg2;
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); secp256k1_scalar_add(&msg2, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg2));
random_sign(&sig, &key, &msg, NULL); random_sign(&sig, &key, &msg, NULL);
int secp_sigsize = 80; int secp_sigsize = 80;