@@ -117,6 +117,23 @@ static int secp256k1_frost_session_load(const secp256k1_context* ctx, secp256k1_
117
117
return 1 ;
118
118
}
119
119
120
+ static const unsigned char secp256k1_frost_partial_sig_magic [4 ] = { 0x8d , 0xd8 , 0x31 , 0x6e };
121
+
122
+ static void secp256k1_frost_partial_sig_save (secp256k1_frost_partial_sig * sig , secp256k1_scalar * s ) {
123
+ memcpy (& sig -> data [0 ], secp256k1_frost_partial_sig_magic , 4 );
124
+ secp256k1_scalar_get_b32 (& sig -> data [4 ], s );
125
+ }
126
+
127
+ static int secp256k1_frost_partial_sig_load (const secp256k1_context * ctx , secp256k1_scalar * s , const secp256k1_frost_partial_sig * sig ) {
128
+ int overflow ;
129
+
130
+ ARG_CHECK (secp256k1_memcmp_var (& sig -> data [0 ], secp256k1_frost_partial_sig_magic , 4 ) == 0 );
131
+ secp256k1_scalar_set_b32 (s , & sig -> data [4 ], & overflow );
132
+ /* Parsed signatures can not overflow */
133
+ VERIFY_CHECK (!overflow );
134
+ return 1 ;
135
+ }
136
+
120
137
int secp256k1_frost_pubnonce_serialize (const secp256k1_context * ctx , unsigned char * out66 , const secp256k1_frost_pubnonce * nonce ) {
121
138
secp256k1_ge ge [2 ];
122
139
int i ;
@@ -163,6 +180,29 @@ int secp256k1_frost_pubnonce_parse(const secp256k1_context* ctx, secp256k1_frost
163
180
return 1 ;
164
181
}
165
182
183
+ int secp256k1_frost_partial_sig_serialize (const secp256k1_context * ctx , unsigned char * out32 , const secp256k1_frost_partial_sig * sig ) {
184
+ VERIFY_CHECK (ctx != NULL );
185
+ ARG_CHECK (out32 != NULL );
186
+ ARG_CHECK (sig != NULL );
187
+ memcpy (out32 , & sig -> data [4 ], 32 );
188
+ return 1 ;
189
+ }
190
+
191
+ int secp256k1_frost_partial_sig_parse (const secp256k1_context * ctx , secp256k1_frost_partial_sig * sig , const unsigned char * in32 ) {
192
+ secp256k1_scalar tmp ;
193
+ int overflow ;
194
+ VERIFY_CHECK (ctx != NULL );
195
+ ARG_CHECK (sig != NULL );
196
+ ARG_CHECK (in32 != NULL );
197
+
198
+ secp256k1_scalar_set_b32 (& tmp , in32 , & overflow );
199
+ if (overflow ) {
200
+ return 0 ;
201
+ }
202
+ secp256k1_frost_partial_sig_save (sig , & tmp );
203
+ return 1 ;
204
+ }
205
+
166
206
/* Write optional inputs into the hash */
167
207
static void secp256k1_nonce_function_frost_helper (secp256k1_sha256 * sha , unsigned int prefix_size , const unsigned char * data32 ) {
168
208
/* The spec requires length prefix to be 4 bytes for `extra_in`, 1 byte
@@ -424,4 +464,161 @@ int secp256k1_frost_nonce_process(const secp256k1_context* ctx, secp256k1_frost_
424
464
return 1 ;
425
465
}
426
466
467
+ void secp256k1_frost_partial_sign_clear (secp256k1_scalar * sk , secp256k1_scalar * k ) {
468
+ secp256k1_scalar_clear (sk );
469
+ secp256k1_scalar_clear (& k [0 ]);
470
+ secp256k1_scalar_clear (& k [1 ]);
471
+ }
472
+
473
+ int secp256k1_frost_partial_sign (const secp256k1_context * ctx , secp256k1_frost_partial_sig * partial_sig , secp256k1_frost_secnonce * secnonce , const secp256k1_frost_share * share , const secp256k1_frost_session * session , const secp256k1_frost_keygen_cache * keygen_cache ) {
474
+ secp256k1_scalar sk ;
475
+ secp256k1_scalar k [2 ];
476
+ secp256k1_scalar s ;
477
+ secp256k1_keygen_cache_internal cache_i ;
478
+ secp256k1_frost_session_internal session_i ;
479
+ int ret ;
480
+
481
+ VERIFY_CHECK (ctx != NULL );
482
+
483
+ ARG_CHECK (secnonce != NULL );
484
+ /* Fails if the magic doesn't match */
485
+ ret = secp256k1_frost_secnonce_load (ctx , k , secnonce );
486
+ /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls
487
+ * of this function to fail */
488
+ memset (secnonce , 0 , sizeof (* secnonce ));
489
+ if (!ret ) {
490
+ secp256k1_frost_partial_sign_clear (& sk , k );
491
+ return 0 ;
492
+ }
493
+
494
+ ARG_CHECK (partial_sig != NULL );
495
+ ARG_CHECK (share != NULL );
496
+ ARG_CHECK (keygen_cache != NULL );
497
+ ARG_CHECK (session != NULL );
498
+
499
+ if (!secp256k1_frost_share_load (ctx , & sk , share )) {
500
+ secp256k1_frost_partial_sign_clear (& sk , k );
501
+ return 0 ;
502
+ }
503
+ if (!secp256k1_keygen_cache_load (ctx , & cache_i , keygen_cache )) {
504
+ secp256k1_frost_partial_sign_clear (& sk , k );
505
+ return 0 ;
506
+ }
507
+
508
+ /* Negate sk if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc.
509
+ * This corresponds to the line "Let d = g⋅gacc⋅d' mod n" in the
510
+ * specification. */
511
+ if ((secp256k1_fe_is_odd (& cache_i .pk .y )
512
+ != cache_i .parity_acc )) {
513
+ secp256k1_scalar_negate (& sk , & sk );
514
+ }
515
+
516
+ if (!secp256k1_frost_session_load (ctx , & session_i , session )) {
517
+ secp256k1_frost_partial_sign_clear (& sk , k );
518
+ return 0 ;
519
+ }
520
+
521
+ if (session_i .fin_nonce_parity ) {
522
+ secp256k1_scalar_negate (& k [0 ], & k [0 ]);
523
+ secp256k1_scalar_negate (& k [1 ], & k [1 ]);
524
+ }
525
+
526
+ /* Sign */
527
+ secp256k1_scalar_mul (& s , & session_i .challenge , & sk );
528
+ secp256k1_scalar_mul (& k [1 ], & session_i .noncecoef , & k [1 ]);
529
+ secp256k1_scalar_add (& k [0 ], & k [0 ], & k [1 ]);
530
+ secp256k1_scalar_add (& s , & s , & k [0 ]);
531
+ secp256k1_frost_partial_sig_save (partial_sig , & s );
532
+ secp256k1_frost_partial_sign_clear (& sk , k );
533
+ return 1 ;
534
+ }
535
+
536
+ int secp256k1_frost_partial_sig_verify (const secp256k1_context * ctx , const secp256k1_frost_partial_sig * partial_sig , const secp256k1_frost_pubnonce * pubnonce , const secp256k1_pubkey * pubshare , const secp256k1_frost_session * session , const secp256k1_frost_keygen_cache * keygen_cache ) {
537
+ secp256k1_keygen_cache_internal cache_i ;
538
+ secp256k1_frost_session_internal session_i ;
539
+ secp256k1_scalar e , s ;
540
+ secp256k1_gej pkj ;
541
+ secp256k1_ge nonce_pt [2 ];
542
+ secp256k1_gej rj ;
543
+ secp256k1_gej tmp ;
544
+ secp256k1_ge pkp ;
545
+
546
+ VERIFY_CHECK (ctx != NULL );
547
+ ARG_CHECK (partial_sig != NULL );
548
+ ARG_CHECK (pubnonce != NULL );
549
+ ARG_CHECK (pubshare != NULL );
550
+ ARG_CHECK (keygen_cache != NULL );
551
+ ARG_CHECK (session != NULL );
552
+
553
+ if (!secp256k1_frost_session_load (ctx , & session_i , session )) {
554
+ return 0 ;
555
+ }
556
+
557
+ /* Compute "effective" nonce rj = aggnonce[0] + b*aggnonce[1] */
558
+ /* TODO: use multiexp to compute -s*G + e*pubshare + aggnonce[0] + b*aggnonce[1] */
559
+ if (!secp256k1_frost_pubnonce_load (ctx , nonce_pt , pubnonce )) {
560
+ return 0 ;
561
+ }
562
+ secp256k1_gej_set_ge (& rj , & nonce_pt [1 ]);
563
+ secp256k1_ecmult (& rj , & rj , & session_i .noncecoef , NULL );
564
+ secp256k1_gej_add_ge_var (& rj , & rj , & nonce_pt [0 ], NULL );
565
+
566
+ if (!secp256k1_pubkey_load (ctx , & pkp , pubshare )) {
567
+ return 0 ;
568
+ }
569
+ if (!secp256k1_keygen_cache_load (ctx , & cache_i , keygen_cache )) {
570
+ return 0 ;
571
+ }
572
+
573
+ secp256k1_scalar_set_int (& e , 1 );
574
+ /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc.
575
+ * This corresponds to the line "Let g' = g⋅gacc mod n" and the multiplication "g'⋅e"
576
+ * in the specification. */
577
+ if (secp256k1_fe_is_odd (& cache_i .pk .y )
578
+ != cache_i .parity_acc ) {
579
+ secp256k1_scalar_negate (& e , & e );
580
+ }
581
+ secp256k1_scalar_mul (& e , & e , & session_i .challenge );
582
+
583
+ if (!secp256k1_frost_partial_sig_load (ctx , & s , partial_sig )) {
584
+ return 0 ;
585
+ }
586
+
587
+ /* Compute -s*G + e*pkj + rj (e already includes the lagrange coefficient l) */
588
+ secp256k1_scalar_negate (& s , & s );
589
+ secp256k1_gej_set_ge (& pkj , & pkp );
590
+ secp256k1_ecmult (& tmp , & pkj , & e , & s );
591
+ if (session_i .fin_nonce_parity ) {
592
+ secp256k1_gej_neg (& rj , & rj );
593
+ }
594
+ secp256k1_gej_add_var (& tmp , & tmp , & rj , NULL );
595
+
596
+ return secp256k1_gej_is_infinity (& tmp );
597
+ }
598
+
599
+ int secp256k1_frost_partial_sig_agg (const secp256k1_context * ctx , unsigned char * sig64 , const secp256k1_frost_session * session , const secp256k1_frost_partial_sig * const * partial_sigs , size_t n_sigs ) {
600
+ size_t i ;
601
+ secp256k1_frost_session_internal session_i ;
602
+
603
+ VERIFY_CHECK (ctx != NULL );
604
+ ARG_CHECK (sig64 != NULL );
605
+ ARG_CHECK (session != NULL );
606
+ ARG_CHECK (partial_sigs != NULL );
607
+ ARG_CHECK (n_sigs > 0 );
608
+
609
+ if (!secp256k1_frost_session_load (ctx , & session_i , session )) {
610
+ return 0 ;
611
+ }
612
+ for (i = 0 ; i < n_sigs ; i ++ ) {
613
+ secp256k1_scalar term ;
614
+ if (!secp256k1_frost_partial_sig_load (ctx , & term , partial_sigs [i ])) {
615
+ return 0 ;
616
+ }
617
+ secp256k1_scalar_add (& session_i .s_part , & session_i .s_part , & term );
618
+ }
619
+ secp256k1_scalar_get_b32 (& sig64 [32 ], & session_i .s_part );
620
+ memcpy (& sig64 [0 ], session_i .fin_nonce , 32 );
621
+ return 1 ;
622
+ }
623
+
427
624
#endif
0 commit comments