13
13
14
14
static uint64_t s2c_opening_magic = 0x5d0520b8b7f2b168ULL ;
15
15
16
+ static const unsigned char s2c_data_tag [16 ] = {
17
+ 's' , '2' , 'c' , '/' , 's' , 'c' , 'h' , 'n' , 'o' , 'r' , 'r' , '/' , 'd' , 'a' , 't' , 'a'
18
+ };
19
+ static const unsigned char s2c_point_tag [17 ] = {
20
+ 's' , '2' , 'c' , '/' , 's' , 'c' , 'h' , 'n' , 'o' , 'r' , 'r' , '/' , 'p' , 'o' , 'i' , 'n' , 't'
21
+ };
22
+
16
23
static void secp256k1_schnorrsig_s2c_opening_init (secp256k1_schnorrsig_s2c_opening * opening ) {
17
24
opening -> magic = s2c_opening_magic ;
18
25
opening -> nonce_is_negated = 0 ;
@@ -183,23 +190,31 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c
183
190
secp256k1_scalar_set_b32 (e , buf , NULL );
184
191
}
185
192
186
- static int secp256k1_schnorrsig_sign_internal (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg , size_t msglen , const secp256k1_keypair * keypair , secp256k1_nonce_function_hardened noncefp , void * ndata ) {
193
+ static int secp256k1_schnorrsig_sign_internal (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg , size_t msglen , const secp256k1_keypair * keypair , secp256k1_nonce_function_hardened noncefp , void * ndata , secp256k1_schnorrsig_s2c_opening * s2c_opening , const unsigned char * s2c_data32 ) {
187
194
secp256k1_scalar sk ;
188
195
secp256k1_scalar e ;
189
196
secp256k1_scalar k ;
190
197
secp256k1_gej rj ;
191
198
secp256k1_ge pk ;
192
199
secp256k1_ge r ;
200
+ secp256k1_sha256 sha ;
193
201
unsigned char buf [32 ] = { 0 };
194
202
unsigned char pk_buf [32 ];
195
203
unsigned char seckey [32 ];
204
+ unsigned char noncedata [32 ];
196
205
int ret = 1 ;
197
206
198
207
VERIFY_CHECK (ctx != NULL );
199
208
ARG_CHECK (secp256k1_ecmult_gen_context_is_built (& ctx -> ecmult_gen_ctx ));
200
209
ARG_CHECK (sig64 != NULL );
201
210
ARG_CHECK (msg != NULL || msglen == 0 );
202
211
ARG_CHECK (keypair != NULL );
212
+ /* sign-to-contract commitments only work with the default nonce function,
213
+ * because we need to ensure that s2c_data is actually hashed into the nonce and
214
+ * not just ignored because otherwise this could result in nonce reuse. */
215
+ ARG_CHECK (s2c_data32 == NULL || (noncefp == NULL || noncefp == secp256k1_nonce_function_bip340 ));
216
+ /* s2c_opening and s2c_data32 should be either both non-NULL or both NULL. */
217
+ ARG_CHECK ((s2c_opening != NULL ) == (s2c_data32 != NULL ));
203
218
204
219
if (noncefp == NULL ) {
205
220
noncefp = secp256k1_nonce_function_bip340 ;
@@ -215,6 +230,25 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
215
230
216
231
secp256k1_scalar_get_b32 (seckey , & sk );
217
232
secp256k1_fe_get_b32 (pk_buf , & pk .x );
233
+
234
+ if (s2c_data32 != NULL ) {
235
+ /* Provide s2c_data32 and ndata (if not NULL) to the the nonce function
236
+ * as additional data to derive the nonce from. If both pointers are
237
+ * not NULL, they need to be hashed to get the nonce data 32 bytes.
238
+ * Even if only s2c_data32 is not NULL, it's hashed because it should
239
+ * be possible to derive nonces even if only a SHA256 commitment to the
240
+ * data is known. This is for example important in the anti nonce
241
+ * sidechannel protocol.
242
+ */
243
+ secp256k1_sha256_initialize_tagged (& sha , s2c_data_tag , sizeof (s2c_data_tag ));
244
+ secp256k1_sha256_write (& sha , s2c_data32 , 32 );
245
+ if (ndata != NULL ) {
246
+ secp256k1_sha256_write (& sha , ndata , 32 );
247
+ }
248
+ secp256k1_sha256_finalize (& sha , noncedata );
249
+ ndata = & noncedata ;
250
+ }
251
+
218
252
ret &= !!noncefp (buf , msg , msglen , seckey , pk_buf , bip340_algo , sizeof (bip340_algo ), ndata );
219
253
secp256k1_scalar_set_b32 (& k , buf , NULL );
220
254
ret &= !secp256k1_scalar_is_zero (& k );
@@ -223,12 +257,27 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
223
257
secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & rj , & k );
224
258
secp256k1_ge_set_gej (& r , & rj );
225
259
260
+ if (s2c_opening != NULL ) {
261
+ secp256k1_schnorrsig_s2c_opening_init (s2c_opening );
262
+ if (s2c_data32 != NULL ) {
263
+ secp256k1_sha256_initialize_tagged (& sha , s2c_point_tag , sizeof (s2c_point_tag ));
264
+ /* Create sign-to-contract commitment */
265
+ secp256k1_pubkey_save (& s2c_opening -> original_pubnonce , & r );
266
+ secp256k1_ec_commit_seckey (& k , & r , & sha , s2c_data32 , 32 );
267
+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & rj , & k );
268
+ secp256k1_ge_set_gej (& r , & rj );
269
+ }
270
+ }
271
+
226
272
/* We declassify r to allow using it as a branch point. This is fine
227
273
* because r is not a secret. */
228
274
secp256k1_declassify (ctx , & r , sizeof (r ));
229
275
secp256k1_fe_normalize_var (& r .y );
230
276
if (secp256k1_fe_is_odd (& r .y )) {
231
277
secp256k1_scalar_negate (& k , & k );
278
+ if (s2c_opening != NULL ) {
279
+ s2c_opening -> nonce_is_negated = 1 ;
280
+ }
232
281
}
233
282
secp256k1_fe_normalize_var (& r .x );
234
283
secp256k1_fe_get_b32 (& sig64 [0 ], & r .x );
@@ -248,7 +297,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
248
297
249
298
int secp256k1_schnorrsig_sign32 (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg32 , const secp256k1_keypair * keypair , const unsigned char * aux_rand32 ) {
250
299
/* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */
251
- return secp256k1_schnorrsig_sign_internal (ctx , sig64 , msg32 , 32 , keypair , secp256k1_nonce_function_bip340 , (unsigned char * )aux_rand32 );
300
+ return secp256k1_schnorrsig_sign_internal (ctx , sig64 , msg32 , 32 , keypair , secp256k1_nonce_function_bip340 , (unsigned char * )aux_rand32 , NULL , NULL );
252
301
}
253
302
254
303
int secp256k1_schnorrsig_sign (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg32 , const secp256k1_keypair * keypair , const unsigned char * aux_rand32 ) {
@@ -258,6 +307,8 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64
258
307
int secp256k1_schnorrsig_sign_custom (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg , size_t msglen , const secp256k1_keypair * keypair , secp256k1_schnorrsig_extraparams * extraparams ) {
259
308
secp256k1_nonce_function_hardened noncefp = NULL ;
260
309
void * ndata = NULL ;
310
+ secp256k1_schnorrsig_s2c_opening * s2c_opening = NULL ;
311
+ const unsigned char * s2c_data32 = NULL ;
261
312
VERIFY_CHECK (ctx != NULL );
262
313
263
314
if (extraparams != NULL ) {
@@ -266,8 +317,10 @@ int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char
266
317
sizeof (extraparams -> magic )) == 0 );
267
318
noncefp = extraparams -> noncefp ;
268
319
ndata = extraparams -> ndata ;
320
+ s2c_opening = extraparams -> s2c_opening ;
321
+ s2c_data32 = extraparams -> s2c_data32 ;
269
322
}
270
- return secp256k1_schnorrsig_sign_internal (ctx , sig64 , msg , msglen , keypair , noncefp , ndata );
323
+ return secp256k1_schnorrsig_sign_internal (ctx , sig64 , msg , msglen , keypair , noncefp , ndata , s2c_opening , s2c_data32 );
271
324
}
272
325
273
326
int secp256k1_schnorrsig_verify (const secp256k1_context * ctx , const unsigned char * sig64 , const unsigned char * msg , size_t msglen , const secp256k1_xonly_pubkey * pubkey ) {
@@ -318,4 +371,34 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
318
371
secp256k1_fe_equal (& rx , & r .x );
319
372
}
320
373
374
+ int secp256k1_schnorrsig_verify_s2c_commit (const secp256k1_context * ctx , const unsigned char * sig64 , const unsigned char * data32 , const secp256k1_schnorrsig_s2c_opening * opening ) {
375
+ secp256k1_fe rx ;
376
+ secp256k1_ge original_r ;
377
+ secp256k1_ge r ;
378
+ secp256k1_sha256 sha ;
379
+
380
+ VERIFY_CHECK (ctx != NULL );
381
+ ARG_CHECK (sig64 != NULL );
382
+ ARG_CHECK (data32 != NULL );
383
+ ARG_CHECK (opening != NULL );
384
+ ARG_CHECK (secp256k1_schnorrsig_s2c_commit_is_init (opening ));
385
+
386
+ if (!secp256k1_fe_set_b32_limit (& rx , & sig64 [0 ])) {
387
+ return 0 ;
388
+ }
389
+ if (!secp256k1_ge_set_xo_var (& r , & rx , 0 )) {
390
+ return 0 ;
391
+ }
392
+ if (opening -> nonce_is_negated ) {
393
+ secp256k1_ge_neg (& r , & r );
394
+ }
395
+
396
+ if (!secp256k1_pubkey_load (ctx , & original_r , & opening -> original_pubnonce )) {
397
+ return 0 ;
398
+ }
399
+
400
+ secp256k1_sha256_initialize_tagged (& sha , s2c_point_tag , sizeof (s2c_point_tag ));
401
+ return secp256k1_ec_commit_verify (& r , & original_r , & sha , data32 , 32 );
402
+ }
403
+
321
404
#endif
0 commit comments