@@ -412,26 +412,27 @@ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
412412
413413void static secp256k1_gej_split_exp_var (secp256k1_num_t * r1 , secp256k1_num_t * r2 , const secp256k1_num_t * a ) {
414414 const secp256k1_ge_consts_t * c = secp256k1_ge_consts ;
415- secp256k1_num_t bnc1 , bnc2 , bnt1 , bnt2 , bnn2 ;
416-
417- secp256k1_num_copy (& bnn2 , & c -> order );
418- secp256k1_num_shift (& bnn2 , 1 );
419-
420- secp256k1_num_mul (& bnc1 , a , & c -> a1b2 );
421- secp256k1_num_add (& bnc1 , & bnc1 , & bnn2 );
422- secp256k1_num_div (& bnc1 , & bnc1 , & c -> order );
423-
424- secp256k1_num_mul (& bnc2 , a , & c -> b1 );
425- secp256k1_num_add (& bnc2 , & bnc2 , & bnn2 );
426- secp256k1_num_div (& bnc2 , & bnc2 , & c -> order );
427-
428- secp256k1_num_mul (& bnt1 , & bnc1 , & c -> a1b2 );
429- secp256k1_num_mul (& bnt2 , & bnc2 , & c -> a2 );
430- secp256k1_num_add (& bnt1 , & bnt1 , & bnt2 );
431- secp256k1_num_sub (r1 , a , & bnt1 );
432- secp256k1_num_mul (& bnt1 , & bnc1 , & c -> b1 );
433- secp256k1_num_mul (& bnt2 , & bnc2 , & c -> a1b2 );
434- secp256k1_num_sub (r2 , & bnt1 , & bnt2 );
415+
416+ secp256k1_num_t d1 , d2 , t ;
417+
418+ secp256k1_num_mul (& t , a , & c -> g1 );
419+ secp256k1_num_trunc (& d1 , & t , 272 );
420+ if (secp256k1_num_get_bit (& t , 271 ))
421+ secp256k1_num_inc (& d1 );
422+
423+ secp256k1_num_mul (& t , a , & c -> g2 );
424+ secp256k1_num_trunc (& d2 , & t , 272 );
425+ if (secp256k1_num_get_bit (& t , 271 ))
426+ secp256k1_num_inc (& d2 );
427+
428+ secp256k1_num_mul (& t , & d1 , & c -> a1b2 );
429+ secp256k1_num_sub (r1 , a , & t );
430+ secp256k1_num_mul (& t , & d2 , & c -> a2 );
431+ secp256k1_num_sub (r1 , r1 , & t );
432+
433+ secp256k1_num_mul (r2 , & d1 , & c -> b1 );
434+ secp256k1_num_mul (& t , & d2 , & c -> a1b2 );
435+ secp256k1_num_sub (r2 , r2 , & t );
435436}
436437#endif
437438
@@ -482,6 +483,33 @@ void static secp256k1_ge_start(void) {
482483 0x14 ,0xca ,0x50 ,0xf7 ,0xa8 ,0xe2 ,0xf3 ,0xf6 ,
483484 0x57 ,0xc1 ,0x10 ,0x8d ,0x9d ,0x44 ,0xcf ,0xd8
484485 };
486+ /**
487+ * g1, g2 are precomputed constants used to replace division with a rounded multiplication
488+ * when decomposing the scalar for an endomorphism-based point multiplication.
489+ *
490+ * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
491+ * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
492+ *
493+ * The derivation is described in the paper "Efficient Software Implementation of Public-Key
494+ * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
495+ * Section 4.3 (here we use a somewhat higher-precision estimate):
496+ * d = a1*b2 - b1*a2
497+ * g1 = round((2^272)*b2/d)
498+ * g2 = round((2^272)*b1/d)
499+ *
500+ * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
501+ * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
502+ */
503+ static const unsigned char secp256k1_ge_consts_g1 [] = {
504+ 0x30 ,0x86 ,
505+ 0xd2 ,0x21 ,0xa7 ,0xd4 ,0x6b ,0xcd ,0xe8 ,0x6c ,
506+ 0x90 ,0xe4 ,0x92 ,0x84 ,0xeb ,0x15 ,0x3d ,0xab
507+ };
508+ static const unsigned char secp256k1_ge_consts_g2 [] = {
509+ 0xe4 ,0x43 ,
510+ 0x7e ,0xd6 ,0x01 ,0x0e ,0x88 ,0x28 ,0x6f ,0x54 ,
511+ 0x7f ,0xa9 ,0x0a ,0xbf ,0xe4 ,0xc4 ,0x22 ,0x12
512+ };
485513#endif
486514 if (secp256k1_ge_consts == NULL ) {
487515 secp256k1_ge_consts_t * ret = (secp256k1_ge_consts_t * )malloc (sizeof (secp256k1_ge_consts_t ));
@@ -493,6 +521,8 @@ void static secp256k1_ge_start(void) {
493521 secp256k1_num_set_bin (& ret -> a1b2 , secp256k1_ge_consts_a1b2 , sizeof (secp256k1_ge_consts_a1b2 ));
494522 secp256k1_num_set_bin (& ret -> a2 , secp256k1_ge_consts_a2 , sizeof (secp256k1_ge_consts_a2 ));
495523 secp256k1_num_set_bin (& ret -> b1 , secp256k1_ge_consts_b1 , sizeof (secp256k1_ge_consts_b1 ));
524+ secp256k1_num_set_bin (& ret -> g1 , secp256k1_ge_consts_g1 , sizeof (secp256k1_ge_consts_g1 ));
525+ secp256k1_num_set_bin (& ret -> g2 , secp256k1_ge_consts_g2 , sizeof (secp256k1_ge_consts_g2 ));
496526 secp256k1_fe_set_b32 (& ret -> beta , secp256k1_ge_consts_beta );
497527#endif
498528 secp256k1_fe_t g_x , g_y ;
0 commit comments