@@ -2594,17 +2594,38 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
25942594 uint8_t * V = K + hash_context -> result_size ;
25952595 uECC_word_t tries ;
25962596 unsigned i ;
2597+ uECC_word_t tmp [uECC_N_WORDS ]; // an integer converted from message_hash
2598+ uint8_t reduced_msg_hash [uECC_N_BYTES ] = { 0 };
2599+
25972600 for (i = 0 ; i < hash_context -> result_size ; ++ i ) {
25982601 V [i ] = 0x01 ;
25992602 K [i ] = 0 ;
26002603 }
26012604
2605+ // Convert the octet string of length `uECC_BYTES` into an integer tmp.
2606+ // Since this must be done when generating an ECDSA signature, we may
2607+ // choose to refactor the codebase so that this operation is done only
2608+ // once.
2609+ vli_bytesToNative (tmp , message_hash );
2610+
2611+ // Modular reduction: tmp <- tmp mod n (ONLY FOR RFC6979)
2612+ while (vli_cmp_n (tmp , curve_n ) >= 0 ) {
2613+ vli_sub (tmp , tmp , curve_n );
2614+ }
2615+
2616+ // Convert the integer tmp back to an octet string (ONLY FOR RFC6979)
2617+ #if (uECC_CURVE == uECC_secp160r1 )
2618+ vli_nativeToBytes (reduced_msg_hash + 1 , tmp );
2619+ #else
2620+ vli_nativeToBytes (reduced_msg_hash , tmp );
2621+ #endif
2622+
26022623 // K = HMAC_K(V || 0x00 || int2octets(x) || h(m))
26032624 HMAC_init (hash_context , K );
26042625 V [hash_context -> result_size ] = 0x00 ;
26052626 HMAC_update (hash_context , V , hash_context -> result_size + 1 );
26062627 HMAC_update (hash_context , private_key , uECC_BYTES );
2607- HMAC_update (hash_context , message_hash , uECC_BYTES );
2628+ HMAC_update (hash_context , reduced_msg_hash , uECC_N_BYTES );
26082629 HMAC_finish (hash_context , K , K );
26092630
26102631 update_V (hash_context , K , V );
@@ -2614,13 +2635,14 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
26142635 V [hash_context -> result_size ] = 0x01 ;
26152636 HMAC_update (hash_context , V , hash_context -> result_size + 1 );
26162637 HMAC_update (hash_context , private_key , uECC_BYTES );
2617- HMAC_update (hash_context , message_hash , uECC_BYTES );
2638+ HMAC_update (hash_context , reduced_msg_hash , uECC_N_BYTES );
26182639 HMAC_finish (hash_context , K , K );
26192640
26202641 update_V (hash_context , K , V );
26212642
26222643 for (tries = 0 ; tries < MAX_TRIES ; ++ tries ) {
2623- uECC_word_t T [uECC_N_WORDS ];
2644+ uECC_word_t k [uECC_N_WORDS ] = { 0 }; // the RFC6979 ephemeral key in each round
2645+ uint8_t T [uECC_N_BYTES ];
26242646 uint8_t * T_ptr = (uint8_t * )T ;
26252647 unsigned T_bytes = 0 ;
26262648 while (T_bytes < sizeof (T )) {
@@ -2630,10 +2652,37 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
26302652 }
26312653 }
26322654 #if (uECC_CURVE == uECC_secp160r1 )
2633- T [uECC_WORDS ] &= 0x01 ;
2655+ //
2656+ // NOTE:
2657+ //
2658+ // The function vli_bytesToNative converts a big-endian array of
2659+ // length uECC_BYTES=20 where each unit is 1-byte long into a native
2660+ // little-endian array of length uECC_WORDS=20/5/3 where each unit is
2661+ // 1/4/8-byte long.
2662+ //
2663+ // Maybe we should have a version of vli_bytesToNative that does the
2664+ // same thing for uECC_N_BYTES=21 and uECC_N_WORDS=21/6/3?
2665+ //
2666+ // TODO:
2667+ //
2668+ // Before vli_bytesToNative() we should right-shift all bits in T by 7
2669+ // so that the leftmost 161 bits in T are used in order to comform to
2670+ // RFC6979.
2671+ //
2672+ vli_bytesToNative (k , T + 1 );
2673+ if (T [0 ] & 1 ) {
2674+ // k <- k + 2^160
2675+ #if (uECC_WORD_SIZE == 1 || uECC_WORD_SIZE == 4 )
2676+ k [uECC_N_WORDS - 1 ] = 1 ;
2677+ #elif (uECC_WORD_SIZE == 8 )
2678+ k [uECC_N_WORDS - 1 ] ^= (1 << 32 );
2679+ #endif
2680+ }
2681+ #else
2682+ vli_bytesToNative (k , T );
26342683 #endif
26352684
2636- if (uECC_sign_with_k (private_key , message_hash , T , signature )) {
2685+ if (uECC_sign_with_k (private_key , message_hash , k , signature )) {
26372686 return 1 ;
26382687 }
26392688
0 commit comments