@@ -337,26 +337,27 @@ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
337337
338338void static secp256k1_gej_split_exp_var (secp256k1_num_t * r1 , secp256k1_num_t * r2 , const secp256k1_num_t * a ) {
339339 const secp256k1_ge_consts_t * c = secp256k1_ge_consts ;
340- secp256k1_num_t bnc1 , bnc2 , bnt1 , bnt2 , bnn2 ;
341-
342- secp256k1_num_copy (& bnn2 , & c -> order );
343- secp256k1_num_shift (& bnn2 , 1 );
344-
345- secp256k1_num_mul (& bnc1 , a , & c -> a1b2 );
346- secp256k1_num_add (& bnc1 , & bnc1 , & bnn2 );
347- secp256k1_num_div (& bnc1 , & bnc1 , & c -> order );
348-
349- secp256k1_num_mul (& bnc2 , a , & c -> b1 );
350- secp256k1_num_add (& bnc2 , & bnc2 , & bnn2 );
351- secp256k1_num_div (& bnc2 , & bnc2 , & c -> order );
352-
353- secp256k1_num_mul (& bnt1 , & bnc1 , & c -> a1b2 );
354- secp256k1_num_mul (& bnt2 , & bnc2 , & c -> a2 );
355- secp256k1_num_add (& bnt1 , & bnt1 , & bnt2 );
356- secp256k1_num_sub (r1 , a , & bnt1 );
357- secp256k1_num_mul (& bnt1 , & bnc1 , & c -> b1 );
358- secp256k1_num_mul (& bnt2 , & bnc2 , & c -> a1b2 );
359- secp256k1_num_sub (r2 , & bnt1 , & bnt2 );
340+
341+ secp256k1_num_t d1 , d2 , t ;
342+
343+ secp256k1_num_mul (& t , a , & c -> g1 );
344+ secp256k1_num_trunc (& d1 , & t , 272 );
345+ if (secp256k1_num_get_bit (& t , 271 ))
346+ secp256k1_num_inc (& d1 );
347+
348+ secp256k1_num_mul (& t , a , & c -> g2 );
349+ secp256k1_num_trunc (& d2 , & t , 272 );
350+ if (secp256k1_num_get_bit (& t , 271 ))
351+ secp256k1_num_inc (& d2 );
352+
353+ secp256k1_num_mul (& t , & d1 , & c -> a1b2 );
354+ secp256k1_num_sub (r1 , a , & t );
355+ secp256k1_num_mul (& t , & d2 , & c -> a2 );
356+ secp256k1_num_sub (r1 , r1 , & t );
357+
358+ secp256k1_num_mul (r2 , & d1 , & c -> b1 );
359+ secp256k1_num_mul (& t , & d2 , & c -> a1b2 );
360+ secp256k1_num_sub (r2 , r2 , & t );
360361}
361362#endif
362363
@@ -407,6 +408,33 @@ void static secp256k1_ge_start(void) {
407408 0x14 ,0xca ,0x50 ,0xf7 ,0xa8 ,0xe2 ,0xf3 ,0xf6 ,
408409 0x57 ,0xc1 ,0x10 ,0x8d ,0x9d ,0x44 ,0xcf ,0xd8
409410 };
411+ /**
412+ * g1, g2 are precomputed constants used to replace division with a rounded multiplication
413+ * when decomposing the scalar for an endomorphism-based point multiplication.
414+ *
415+ * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
416+ * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
417+ *
418+ * The derivation is described in the paper "Efficient Software Implementation of Public-Key
419+ * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
420+ * Section 4.3 (here we use a somewhat higher-precision estimate):
421+ * d = a1*b2 - b1*a2
422+ * g1 = round((2^272)*b2/d)
423+ * g2 = round((2^272)*b1/d)
424+ *
425+ * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
426+ * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
427+ */
428+ static const unsigned char secp256k1_ge_consts_g1 [] = {
429+ 0x30 ,0x86 ,
430+ 0xd2 ,0x21 ,0xa7 ,0xd4 ,0x6b ,0xcd ,0xe8 ,0x6c ,
431+ 0x90 ,0xe4 ,0x92 ,0x84 ,0xeb ,0x15 ,0x3d ,0xab
432+ };
433+ static const unsigned char secp256k1_ge_consts_g2 [] = {
434+ 0xe4 ,0x43 ,
435+ 0x7e ,0xd6 ,0x01 ,0x0e ,0x88 ,0x28 ,0x6f ,0x54 ,
436+ 0x7f ,0xa9 ,0x0a ,0xbf ,0xe4 ,0xc4 ,0x22 ,0x12
437+ };
410438#endif
411439 if (secp256k1_ge_consts == NULL ) {
412440 secp256k1_ge_consts_t * ret = (secp256k1_ge_consts_t * )malloc (sizeof (secp256k1_ge_consts_t ));
@@ -418,6 +446,8 @@ void static secp256k1_ge_start(void) {
418446 secp256k1_num_set_bin (& ret -> a1b2 , secp256k1_ge_consts_a1b2 , sizeof (secp256k1_ge_consts_a1b2 ));
419447 secp256k1_num_set_bin (& ret -> a2 , secp256k1_ge_consts_a2 , sizeof (secp256k1_ge_consts_a2 ));
420448 secp256k1_num_set_bin (& ret -> b1 , secp256k1_ge_consts_b1 , sizeof (secp256k1_ge_consts_b1 ));
449+ secp256k1_num_set_bin (& ret -> g1 , secp256k1_ge_consts_g1 , sizeof (secp256k1_ge_consts_g1 ));
450+ secp256k1_num_set_bin (& ret -> g2 , secp256k1_ge_consts_g2 , sizeof (secp256k1_ge_consts_g2 ));
421451 secp256k1_fe_set_b32 (& ret -> beta , secp256k1_ge_consts_beta );
422452#endif
423453 secp256k1_fe_t g_x , g_y ;
0 commit comments