Skip to content

Commit 29c8d1b

Browse files
author
Jong-Shian Wu
committed
make uECC_sign_deterministic conform to RFC 6979
1 parent 81ff1f5 commit 29c8d1b

2 files changed

Lines changed: 56 additions & 5 deletions

File tree

uECC.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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)) {
@@ -2629,11 +2651,32 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
26292651
T_ptr[T_bytes] = V[i];
26302652
}
26312653
}
2654+
26322655
#if (uECC_CURVE == uECC_secp160r1)
2633-
T[uECC_WORDS] &= 0x01;
2656+
2657+
// Now T is an array containing uECC_N_BYTES=21 random bytes.
2658+
2659+
// TODO: In order to comform to RFC6979 for secp160r1, we should right-shift all bits in T by 7 here.
2660+
2661+
// Convert the 20 rightmost bytes into an integer k.
2662+
vli_bytesToNative(k, T + 1);
2663+
2664+
// If the lowest bit in the leftmost byte is 1, add 2^160 to k.
2665+
if (T[0] & 1) {
2666+
#if (uECC_WORD_SIZE == 1)
2667+
k[uECC_N_WORDS - 1] = 0x01;
2668+
#elif (uECC_WORD_SIZE == 4)
2669+
k[uECC_N_WORDS - 1] = 0x00000001;
2670+
#elif (uECC_WORD_SIZE == 8)
2671+
k[uECC_N_WORDS - 1] ^= 0x0000000100000000;
2672+
#endif
2673+
}
2674+
2675+
#else
2676+
vli_bytesToNative(k, T);
26342677
#endif
26352678

2636-
if (uECC_sign_with_k(private_key, message_hash, T, signature)) {
2679+
if (uECC_sign_with_k(private_key, message_hash, k, signature)) {
26372680
return 1;
26382681
}
26392682

uECC.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ faster by about 8% but increases the code size. */
6060

6161
#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)
6262

63+
#define uECC_n_size_1 21 /* secp160r1 */
64+
#define uECC_n_size_2 24 /* secp192r1 */
65+
#define uECC_n_size_3 32 /* secp256r1 */
66+
#define uECC_n_size_4 32 /* secp256k1 */
67+
#define uECC_n_size_5 28 /* secp224r1 */
68+
69+
#define uECC_N_BYTES uECC_CONCAT(uECC_n_size_, uECC_CURVE)
70+
6371
#ifdef __cplusplus
6472
extern "C"
6573
{

0 commit comments

Comments
 (0)