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