@@ -25,8 +25,8 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont
25
25
26
26
static void secp256k1_ecmult_gen_context_clear (secp256k1_ecmult_gen_context * ctx ) {
27
27
ctx -> built = 0 ;
28
- secp256k1_scalar_clear (& ctx -> blind );
29
- secp256k1_gej_clear (& ctx -> initial );
28
+ secp256k1_scalar_clear (& ctx -> scalar_offset );
29
+ secp256k1_ge_clear (& ctx -> ge_offset );
30
30
}
31
31
32
32
/* For accelerating the computation of a*G:
@@ -51,12 +51,13 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
51
51
secp256k1_ge_storage adds ;
52
52
secp256k1_scalar gnb ;
53
53
int i , j , n_i ;
54
-
54
+
55
55
memset (& adds , 0 , sizeof (adds ));
56
- * r = ctx -> initial ;
57
- /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
58
- secp256k1_scalar_add (& gnb , gn , & ctx -> blind );
59
- add .infinity = 0 ;
56
+ secp256k1_gej_set_infinity (r );
57
+
58
+ /* Blind scalar/point multiplication by computing (gn-b)*G + b*G instead of gn*G. */
59
+ secp256k1_scalar_add (& gnb , gn , & ctx -> scalar_offset );
60
+
60
61
for (i = 0 ; i < n ; i ++ ) {
61
62
n_i = secp256k1_scalar_get_bits (& gnb , i * bits , bits );
62
63
for (j = 0 ; j < g ; j ++ ) {
@@ -76,6 +77,11 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
76
77
secp256k1_gej_add_ge (r , r , & add );
77
78
}
78
79
n_i = 0 ;
80
+
81
+ /* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was
82
+ * subtracted from the input scalar gn). */
83
+ secp256k1_gej_add_ge (r , r , & ctx -> ge_offset );
84
+
79
85
secp256k1_ge_clear (& add );
80
86
secp256k1_scalar_clear (& gnb );
81
87
}
@@ -84,19 +90,17 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
84
90
static void secp256k1_ecmult_gen_blind (secp256k1_ecmult_gen_context * ctx , const unsigned char * seed32 ) {
85
91
secp256k1_scalar b ;
86
92
secp256k1_gej gb ;
87
- secp256k1_fe s ;
88
93
unsigned char nonce32 [32 ];
89
94
secp256k1_rfc6979_hmac_sha256 rng ;
90
95
unsigned char keydata [64 ];
91
96
if (seed32 == NULL ) {
92
- /* When seed is NULL, reset the initial point and blinding value. */
93
- secp256k1_gej_set_ge (& ctx -> initial , & secp256k1_ge_const_g );
94
- secp256k1_gej_neg (& ctx -> initial , & ctx -> initial );
95
- secp256k1_scalar_set_int (& ctx -> blind , 1 );
97
+ /* When seed is NULL, reset the final point and blinding value. */
98
+ secp256k1_ge_neg (& ctx -> ge_offset , & secp256k1_ge_const_g );
99
+ ctx -> scalar_offset = secp256k1_scalar_one ;
96
100
return ;
97
101
}
98
102
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
99
- secp256k1_scalar_get_b32 (keydata , & ctx -> blind );
103
+ secp256k1_scalar_get_b32 (keydata , & ctx -> scalar_offset );
100
104
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
101
105
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
102
106
* asking the caller for blinding values directly and expecting them to retry on failure.
@@ -105,24 +109,23 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
105
109
memcpy (keydata + 32 , seed32 , 32 );
106
110
secp256k1_rfc6979_hmac_sha256_initialize (& rng , keydata , 64 );
107
111
memset (keydata , 0 , sizeof (keydata ));
108
- secp256k1_rfc6979_hmac_sha256_generate (& rng , nonce32 , 32 );
109
- secp256k1_fe_set_b32_mod (& s , nonce32 );
110
- secp256k1_fe_cmov (& s , & secp256k1_fe_one , secp256k1_fe_normalizes_to_zero (& s ));
111
- /* Randomize the projection to defend against multiplier sidechannels.
112
- Do this before our own call to secp256k1_ecmult_gen below. */
113
- secp256k1_gej_rescale (& ctx -> initial , & s );
114
- secp256k1_fe_clear (& s );
112
+
113
+ /* TODO: reintroduce projective blinding. */
114
+
115
+ /* For a random blinding value b, set ctx->scalar_offset=-b, ctx->ge_offset=bG. */
115
116
secp256k1_rfc6979_hmac_sha256_generate (& rng , nonce32 , 32 );
116
117
secp256k1_scalar_set_b32 (& b , nonce32 , NULL );
117
- /* A blinding value of 0 works, but would undermine the projection hardening. */
118
+ /* The blinding value cannot be zero, as that would mean ge_offset = infinity,
119
+ * which secp256k1_gej_add_ge cannot handle. */
118
120
secp256k1_scalar_cmov (& b , & secp256k1_scalar_one , secp256k1_scalar_is_zero (& b ));
119
121
secp256k1_rfc6979_hmac_sha256_finalize (& rng );
120
122
memset (nonce32 , 0 , 32 );
121
- /* The random projection in ctx->initial ensures that gb will have a random projection. */
122
123
secp256k1_ecmult_gen (ctx , & gb , & b );
123
124
secp256k1_scalar_negate (& b , & b );
124
- ctx -> blind = b ;
125
- ctx -> initial = gb ;
125
+ ctx -> scalar_offset = b ;
126
+ secp256k1_ge_set_gej (& ctx -> ge_offset , & gb );
127
+
128
+ /* Clean up. */
126
129
secp256k1_scalar_clear (& b );
127
130
secp256k1_gej_clear (& gb );
128
131
}
0 commit comments