@@ -236,4 +236,163 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
236
236
secp256k1_fe_equal_var (& rx , & r .x );
237
237
}
238
238
239
+ static int compute_midhash (const secp256k1_context * ctx , unsigned char * midhash , unsigned char * * sig64 , unsigned char * aggsig , unsigned char * * msg32 , secp256k1_xonly_pubkey * pubkey , size_t n_sigs ) {
240
+ secp256k1_sha256 hash ;
241
+ uint32_t i ;
242
+
243
+ VERIFY_CHECK ((aggsig != NULL ) != (sig64 != NULL ));
244
+
245
+ /* TODO: use actual tagged hash */
246
+ secp256k1_sha256_initialize (& hash );
247
+ /* z_i = int(hash_{HalfAggregation}(r_1 || pk_1 || m_1 || ... || r_n || pk_n || m_n || i)) mod n */
248
+ for (i = 0 ; i < n_sigs ; i ++ ) {
249
+ unsigned char pk_ser [32 ];
250
+
251
+ /* r_i = sig_i[0:32] */
252
+ if (sig64 != NULL ) {
253
+ secp256k1_sha256_write (& hash , sig64 [i ], 32 );
254
+ } else {
255
+ /* aggsig != NULL */
256
+ secp256k1_sha256_write (& hash , & aggsig [i * 32 ], 32 );
257
+ }
258
+ if (!secp256k1_xonly_pubkey_serialize (ctx , pk_ser , & pubkey [i ])) {
259
+ return 0 ;
260
+ }
261
+ secp256k1_sha256_write (& hash , pk_ser , sizeof (pk_ser ));
262
+ secp256k1_sha256_write (& hash , msg32 [i ], 32 );
263
+ }
264
+ /* TODO: copy midstate instead of computing intermediate "midhash" */
265
+ secp256k1_sha256_finalize (& hash , midhash );
266
+ return 1 ;
267
+ }
268
+
269
+ int secp256k1_schnorrsig_aggregate (const secp256k1_context * ctx , unsigned char * aggsig , size_t * aggsig_size , unsigned char * * sig64 , unsigned char * * msg32 , secp256k1_xonly_pubkey * pubkey , uint32_t n_sigs ) {
270
+ uint32_t i ;
271
+ secp256k1_sha256 hash ;
272
+ unsigned char midhash [32 ];
273
+ secp256k1_scalar s ;
274
+
275
+ VERIFY_CHECK (ctx != NULL );
276
+ ARG_CHECK (aggsig != NULL );
277
+ ARG_CHECK (aggsig_size != NULL );
278
+ ARG_CHECK (sig64 != NULL );
279
+ ARG_CHECK (msg32 != NULL );
280
+ ARG_CHECK (pubkey != NULL );
281
+
282
+ if (* aggsig_size < 32 * (1 + n_sigs )) {
283
+ return 0 ;
284
+ }
285
+
286
+ if (!compute_midhash (ctx , midhash , sig64 , NULL , msg32 , pubkey , n_sigs )) {
287
+ return 0 ;
288
+ }
289
+
290
+ /* s = z_1⋅s_1 + ... + z_n⋅s_n */
291
+ secp256k1_scalar_set_int (& s , 0 );
292
+ for (i = 0 ; i < n_sigs ; i ++ ) {
293
+ unsigned char randomizer [32 ];
294
+ secp256k1_scalar zi ;
295
+ secp256k1_scalar si ;
296
+
297
+ secp256k1_sha256_initialize (& hash );
298
+ secp256k1_sha256_write (& hash , midhash , sizeof (midhash ));
299
+ /* TODO: fix endianness issue */
300
+ secp256k1_sha256_write (& hash , (unsigned char * )& i , sizeof (i ));
301
+ secp256k1_sha256_finalize (& hash , randomizer );
302
+ secp256k1_scalar_set_b32 (& zi , randomizer , NULL );
303
+
304
+ secp256k1_scalar_set_b32 (& si , & sig64 [i ][32 ], NULL );
305
+ secp256k1_scalar_mul (& si , & si , & zi );
306
+ secp256k1_scalar_add (& s , & s , & si );
307
+
308
+ memcpy (& aggsig [i * 32 ], sig64 [i ], 32 );
309
+ }
310
+
311
+ /* Return sig = r_1 || ... || r_n || bytes(s) */
312
+ secp256k1_scalar_get_b32 (& aggsig [n_sigs * 32 ], & s );
313
+ * aggsig_size = 32 * (1 + n_sigs );
314
+
315
+ return 1 ;
316
+ }
317
+
318
+ int secp256k1_schnorrsig_aggverify (const secp256k1_context * ctx , unsigned char * * msg32 , uint32_t n_msgs , secp256k1_xonly_pubkey * pubkey , unsigned char * aggsig , size_t aggsig_size ) {
319
+ unsigned char midhash [32 ];
320
+ uint32_t i ;
321
+ secp256k1_gej lhs , rhs ;
322
+ secp256k1_scalar s ;
323
+ int overflow ;
324
+
325
+ VERIFY_CHECK (ctx != NULL );
326
+ ARG_CHECK (msg32 != NULL );
327
+ ARG_CHECK (pubkey != NULL );
328
+ ARG_CHECK (aggsig != NULL );
329
+
330
+ secp256k1_gej_set_infinity (& rhs );
331
+ if (aggsig_size != 32 * (1 + n_msgs )) {
332
+ return 0 ;
333
+ }
334
+
335
+ if (!compute_midhash (ctx , midhash , NULL , aggsig , msg32 , pubkey , n_msgs )) {
336
+ return 0 ;
337
+ }
338
+
339
+ for (i = 0 ; i < n_msgs ; i ++ ) {
340
+ secp256k1_sha256 hash ;
341
+ unsigned char randomizer [32 ];
342
+ secp256k1_scalar zi ;
343
+ secp256k1_fe rx ;
344
+ secp256k1_ge rp , pp ;
345
+ secp256k1_scalar ei ;
346
+ unsigned char pk_ser [32 ];
347
+ secp256k1_gej ppj , acc ;
348
+
349
+ secp256k1_sha256_initialize (& hash );
350
+ secp256k1_sha256_write (& hash , midhash , sizeof (midhash ));
351
+ /* TODO: fix endianness issue */
352
+ secp256k1_sha256_write (& hash , (unsigned char * )& i , sizeof (i ));
353
+ secp256k1_sha256_finalize (& hash , randomizer );
354
+ secp256k1_scalar_set_b32 (& zi , randomizer , NULL );
355
+
356
+ /* R_i = lift_x(int(r_i)); fail if that fails */
357
+ if (!secp256k1_fe_set_b32 (& rx , & aggsig [i * 32 ])) {
358
+ return 0 ;
359
+ }
360
+ if (!secp256k1_ge_set_xo_var (& rp , & rx , 0 )) {
361
+ return 0 ;
362
+ }
363
+
364
+ /* P_i = lift_x(int(pk_i)); fail if that fails */
365
+ if (!secp256k1_xonly_pubkey_load (ctx , & pp , & pubkey [i ])) {
366
+ return 0 ;
367
+ }
368
+
369
+ /* e_i = int(hash_{BIP0340/challenge}(bytes(r_i) || pk_i || m_i)) mod n */
370
+ /* TODO: compute pubkey serialization again after compute_midhash? */
371
+ if (!secp256k1_xonly_pubkey_serialize (ctx , pk_ser , & pubkey [i ])) {
372
+ return 0 ;
373
+ }
374
+ secp256k1_schnorrsig_challenge (& ei , & aggsig [i * 32 ], msg32 [i ], pk_ser );
375
+ secp256k1_gej_set_ge (& ppj , & pp );
376
+ /* e_i⋅P_i */
377
+ secp256k1_ecmult (& ctx -> ecmult_ctx , & acc , & ppj , & ei , NULL );
378
+ /* R_i + e_i⋅P_i */
379
+ secp256k1_gej_add_ge_var (& acc , & acc , & rp , NULL );
380
+ /* z_i⋅(R_i + e_i⋅P_i) */
381
+ secp256k1_ecmult (& ctx -> ecmult_ctx , & acc , & acc , & zi , NULL );
382
+ secp256k1_gej_add_var (& rhs , & rhs , & acc , NULL );
383
+ }
384
+ /* s = int(sig[n⋅32:(n+1)⋅32]) */
385
+ secp256k1_scalar_set_b32 (& s , & aggsig [n_msgs * 32 ], & overflow );
386
+ if (overflow ) {
387
+ return 0 ;
388
+ }
389
+ /* s⋅G */
390
+ secp256k1_ecmult (& ctx -> ecmult_ctx , & lhs , NULL , & secp256k1_scalar_zero , & s );
391
+
392
+ /* lhs ?= rhs */
393
+ secp256k1_gej_neg (& lhs , & lhs );
394
+ secp256k1_gej_add_var (& lhs , & lhs , & rhs , NULL );
395
+ return secp256k1_gej_is_infinity (& lhs );
396
+ }
397
+
239
398
#endif
0 commit comments