@@ -1233,6 +1233,7 @@ static int uECC_sign_with_k(const uint8_t *private_key,
12331233 const uint8_t * message_hash ,
12341234 unsigned hash_size ,
12351235 uECC_word_t * k ,
1236+ uint8_t * recid ,
12361237 uint8_t * signature ,
12371238 uECC_Curve curve ) {
12381239
@@ -1245,9 +1246,9 @@ static int uECC_sign_with_k(const uint8_t *private_key,
12451246 uECC_word_t p [uECC_MAX_WORDS * 2 ];
12461247#endif
12471248 uECC_word_t carry ;
1248- wordcount_t num_words = curve -> num_words ;
1249- wordcount_t num_n_words = BITS_TO_WORDS (curve -> num_n_bits );
1250- bitcount_t num_n_bits = curve -> num_n_bits ;
1249+ const wordcount_t num_words = curve -> num_words ;
1250+ const wordcount_t num_n_words = BITS_TO_WORDS (curve -> num_n_bits );
1251+ const bitcount_t num_n_bits = curve -> num_n_bits ;
12511252
12521253 /* Make sure 0 < k < curve_n */
12531254 if (uECC_vli_isZero (k , num_words ) || uECC_vli_cmp (curve -> n , k , num_n_words ) != 1 ) {
@@ -1269,14 +1270,18 @@ static int uECC_sign_with_k(const uint8_t *private_key,
12691270 return 0 ;
12701271 }
12711272
1273+ if (recid ) {
1274+ * recid = uECC_vli_testBit (p + num_words , 0 );
1275+ }
1276+
12721277 /* Prevent side channel analysis of uECC_vli_modInv() to determine
12731278 bits of k / the private key by premultiplying by a random number */
12741279 uECC_vli_modMult (k , k , tmp , curve -> n , num_n_words ); /* k' = rand * k */
12751280 uECC_vli_modInv (k , k , curve -> n , num_n_words ); /* k = 1 / k' */
12761281 uECC_vli_modMult (k , k , tmp , curve -> n , num_n_words ); /* k = 1 / k */
12771282
12781283#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
1279- uECC_vli_nativeToBytes (signature , curve -> num_bytes , p ); /* store r */
1284+ uECC_vli_nativeToBytes (signature , curve -> num_bytes , p ); /* store r = p.x */
12801285#endif
12811286
12821287#if uECC_VLI_NATIVE_LITTLE_ENDIAN
@@ -1316,13 +1321,34 @@ int uECC_sign(const uint8_t *private_key,
13161321 return 0 ;
13171322 }
13181323
1319- if (uECC_sign_with_k (private_key , message_hash , hash_size , k , signature , curve )) {
1324+ if (uECC_sign_with_k (private_key , message_hash , hash_size , k , 0 , signature , curve )) {
13201325 return 1 ;
13211326 }
13221327 }
13231328 return 0 ;
13241329}
13251330
1331+ int uECC_sign_recoverable (const uint8_t * private_key ,
1332+ const uint8_t * message_hash ,
1333+ unsigned hash_size ,
1334+ uint8_t * recid ,
1335+ uint8_t * signature ,
1336+ uECC_Curve curve ) {
1337+ uECC_word_t k [uECC_MAX_WORDS ];
1338+ uECC_word_t tries ;
1339+
1340+ for (tries = 0 ; tries < uECC_RNG_MAX_TRIES ; ++ tries ) {
1341+ if (!uECC_generate_random_int (k , curve -> n , BITS_TO_WORDS (curve -> num_n_bits ))) {
1342+ return 0 ;
1343+ }
1344+
1345+ if (uECC_sign_with_k (private_key , message_hash , hash_size , k , recid , signature , curve )) {
1346+ return 1 ;
1347+ }
1348+ }
1349+ return 0 ;
1350+ }
1351+
13261352/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
13271353 the same size as the hash result size. */
13281354static void HMAC_init (const uECC_HashContext * hash_context , const uint8_t * K ) {
@@ -1432,7 +1458,7 @@ int uECC_sign_deterministic(const uint8_t *private_key,
14321458 mask >> ((bitcount_t )(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits ));
14331459 }
14341460
1435- if (uECC_sign_with_k (private_key , message_hash , hash_size , T , signature , curve )) {
1461+ if (uECC_sign_with_k (private_key , message_hash , hash_size , T , 0 , signature , curve )) {
14361462 return 1 ;
14371463 }
14381464
0 commit comments