Switch wnaf splitting from num-based to scalar-based

This commit is contained in:
Pieter Wuille 2014-11-26 14:47:23 +01:00
parent 1e6c77c321
commit 0b73059709
2 changed files with 43 additions and 25 deletions

View file

@ -9,6 +9,7 @@
#include "num.h" #include "num.h"
#include "group.h" #include "group.h"
#include "scalar.h"
#include "ecmult.h" #include "ecmult.h"
/* optimal for 128-bit and 256-bit exponents. */ /* optimal for 128-bit and 256-bit exponents. */
@ -121,12 +122,10 @@ static void secp256k1_ecmult_stop(void) {
* with the following guarantees: * with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) * - 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. * - 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 * - the number of set values in wnaf is returned. This number is at most 256, and at most one more
* bits is the number of bits necessary to represent 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_num_t *a, int w) {
int ret = 0;
int zeroes = 0;
secp256k1_num_t x; secp256k1_num_t x;
secp256k1_num_copy(&x, a); secp256k1_num_copy(&x, a);
int sign = 1; int sign = 1;
@ -134,25 +133,40 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
sign = -1; sign = -1;
secp256k1_num_negate(&x); secp256k1_num_negate(&x);
} }
while (!secp256k1_num_is_zero(&x)) { unsigned char cr[32];
while (!secp256k1_num_is_odd(&x)) { secp256k1_num_get_bin(cr, 32, &x);
zeroes++; secp256k1_scalar_t s;
secp256k1_num_shift(&x, 1); secp256k1_scalar_set_b32(&s, cr, NULL);
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s);
sign *= -1;
} }
int word = secp256k1_num_shift(&x, w);
while (zeroes) { int set_bits = 0;
wnaf[ret++] = 0; int bit = 0;
zeroes--; while (bit < 256) {
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
bit++;
continue;
} }
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))) { if (word & (1 << (w-1))) {
secp256k1_num_inc(&x); secp256k1_scalar_add_bit(&s, bit + w);
wnaf[ret++] = sign * (word - (1 << w)); wnaf[set_bits++] = sign * (word - (1 << w));
} else { } 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_num_t *na, const secp256k1_num_t *ng) {
@ -170,7 +184,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
if (bits_na_lam > bits) bits = bits_na_lam; if (bits_na_lam > bits) bits = bits_na_lam;
#else #else
/* build wnaf representation for na. */ /* 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; int bits = bits_na;
#endif #endif

View file

@ -825,8 +825,9 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
secp256k1_num_t x, two, t; secp256k1_num_t x, two, t;
secp256k1_num_set_int(&x, 0); secp256k1_num_set_int(&x, 0);
secp256k1_num_set_int(&two, 2); secp256k1_num_set_int(&two, 2);
int wnaf[257]; int wnaf[256];
int bits = secp256k1_ecmult_wnaf(wnaf, number, w); int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
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_num_mul(&x, &x, &two);
@ -844,7 +845,10 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
secp256k1_num_set_int(&t, v); secp256k1_num_set_int(&t, v);
secp256k1_num_add(&x, &x, &t); secp256k1_num_add(&x, &x, &t);
} }
CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */ secp256k1_num_t xcopy = x, ncopy = *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) {