Skip to content

Commit 0b73059

Browse files
committed
Switch wnaf splitting from num-based to scalar-based
1 parent 1e6c77c commit 0b73059

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

src/ecmult_impl.h

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "num.h"
1111
#include "group.h"
12+
#include "scalar.h"
1213
#include "ecmult.h"
1314

1415
/* optimal for 128-bit and 256-bit exponents. */
@@ -121,38 +122,51 @@ static void secp256k1_ecmult_stop(void) {
121122
* with the following guarantees:
122123
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
123124
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
124-
* - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where
125-
* bits is the number of bits necessary to represent the absolute value of the input.
125+
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more
126+
* - than the number of bits in the (absolute value) of the input.
126127
*/
127128
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
128-
int ret = 0;
129-
int zeroes = 0;
130129
secp256k1_num_t x;
131130
secp256k1_num_copy(&x, a);
132131
int sign = 1;
133132
if (secp256k1_num_is_neg(&x)) {
134133
sign = -1;
135134
secp256k1_num_negate(&x);
136135
}
137-
while (!secp256k1_num_is_zero(&x)) {
138-
while (!secp256k1_num_is_odd(&x)) {
139-
zeroes++;
140-
secp256k1_num_shift(&x, 1);
136+
unsigned char cr[32];
137+
secp256k1_num_get_bin(cr, 32, &x);
138+
secp256k1_scalar_t s;
139+
secp256k1_scalar_set_b32(&s, cr, NULL);
140+
141+
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
142+
secp256k1_scalar_negate(&s, &s);
143+
sign *= -1;
144+
}
145+
146+
int set_bits = 0;
147+
int bit = 0;
148+
while (bit < 256) {
149+
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
150+
bit++;
151+
continue;
152+
}
153+
while (set_bits < bit) {
154+
wnaf[set_bits++] = 0;
141155
}
142-
int word = secp256k1_num_shift(&x, w);
143-
while (zeroes) {
144-
wnaf[ret++] = 0;
145-
zeroes--;
156+
int now = w;
157+
if (bit + now > 256) {
158+
now = 256 - bit;
146159
}
160+
int word = secp256k1_scalar_get_bits_var(&s, bit, now);
147161
if (word & (1 << (w-1))) {
148-
secp256k1_num_inc(&x);
149-
wnaf[ret++] = sign * (word - (1 << w));
162+
secp256k1_scalar_add_bit(&s, bit + w);
163+
wnaf[set_bits++] = sign * (word - (1 << w));
150164
} else {
151-
wnaf[ret++] = sign * word;
165+
wnaf[set_bits++] = sign * word;
152166
}
153-
zeroes = w-1;
167+
bit += now;
154168
}
155-
return ret;
169+
return set_bits;
156170
}
157171

158172
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
170184
if (bits_na_lam > bits) bits = bits_na_lam;
171185
#else
172186
/* build wnaf representation for na. */
173-
int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
187+
int wnaf_na[256]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
174188
int bits = bits_na;
175189
#endif
176190

src/tests.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,8 +825,9 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
825825
secp256k1_num_t x, two, t;
826826
secp256k1_num_set_int(&x, 0);
827827
secp256k1_num_set_int(&two, 2);
828-
int wnaf[257];
828+
int wnaf[256];
829829
int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
830+
CHECK(bits <= 256);
830831
int zeroes = -1;
831832
for (int i=bits-1; i>=0; i--) {
832833
secp256k1_num_mul(&x, &x, &two);
@@ -844,7 +845,10 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
844845
secp256k1_num_set_int(&t, v);
845846
secp256k1_num_add(&x, &x, &t);
846847
}
847-
CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */
848+
secp256k1_num_t xcopy = x, ncopy = *number;
849+
secp256k1_num_mod(&xcopy, &secp256k1_ge_consts->order);
850+
secp256k1_num_mod(&ncopy, &secp256k1_ge_consts->order);
851+
CHECK(secp256k1_num_eq(&xcopy, &ncopy)); /* check that wnaf represents number */
848852
}
849853

850854
void run_wnaf(void) {

0 commit comments

Comments
 (0)