Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC 6979 conformance #51

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions uECC.c
Original file line number Diff line number Diff line change
Expand Up @@ -2594,17 +2594,37 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
uint8_t *V = K + hash_context->result_size;
uECC_word_t tries;
unsigned i;
uECC_word_t tmp[uECC_N_WORDS] = { 0 }; // an integer converted from message_hash
uint8_t reduced_msg_hash[uECC_N_BYTES] = { 0 };

for (i = 0; i < hash_context->result_size; ++i) {
V[i] = 0x01;
K[i] = 0;
}

// Convert the octet string of length `uECC_BYTES` into an integer tmp.
// Since this must be done when generating an ECDSA signature, we may
// choose to refactor the codebase so that this operation is done only
// once.
vli_bytesToNative(tmp, message_hash);

// Perform modular reduction tmp <- tmp mod n, and then
// convert tmp back to an octet string (ONLY FOR RFC6979)
#if (uECC_CURVE == uECC_secp160r1)
vli_nativeToBytes(reduced_msg_hash + 1, tmp);
#else
if (vli_cmp_n(tmp, curve_n) >= 0) {
vli_sub(tmp, tmp, curve_n);
}
vli_nativeToBytes(reduced_msg_hash, tmp);
#endif

// K = HMAC_K(V || 0x00 || int2octets(x) || h(m))
HMAC_init(hash_context, K);
V[hash_context->result_size] = 0x00;
HMAC_update(hash_context, V, hash_context->result_size + 1);
HMAC_update(hash_context, private_key, uECC_BYTES);
HMAC_update(hash_context, message_hash, uECC_BYTES);
HMAC_update(hash_context, reduced_msg_hash, uECC_N_BYTES);
HMAC_finish(hash_context, K, K);

update_V(hash_context, K, V);
Expand All @@ -2614,13 +2634,14 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
V[hash_context->result_size] = 0x01;
HMAC_update(hash_context, V, hash_context->result_size + 1);
HMAC_update(hash_context, private_key, uECC_BYTES);
HMAC_update(hash_context, message_hash, uECC_BYTES);
HMAC_update(hash_context, reduced_msg_hash, uECC_N_BYTES);
HMAC_finish(hash_context, K, K);

update_V(hash_context, K, V);

for (tries = 0; tries < MAX_TRIES; ++tries) {
uECC_word_t T[uECC_N_WORDS];
uECC_word_t k[uECC_N_WORDS] = { 0 }; // the RFC6979 ephemeral key in each round
uint8_t T[uECC_N_BYTES];
uint8_t *T_ptr = (uint8_t *)T;
unsigned T_bytes = 0;
while (T_bytes < sizeof(T)) {
Expand All @@ -2629,11 +2650,32 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
T_ptr[T_bytes] = V[i];
}
}

#if (uECC_CURVE == uECC_secp160r1)
T[uECC_WORDS] &= 0x01;

// Now T is an array containing uECC_N_BYTES=21 random bytes.

// TODO: In order to comform to RFC6979 for secp160r1, we should right-shift all bits in T by 7 here.

// Convert the 20 rightmost bytes into an integer k.
vli_bytesToNative(k, T + 1);

// If the lowest bit in the leftmost byte is 1, add 2^160 to k.
if (T[0] & 1) {
#if (uECC_WORD_SIZE == 1)
k[uECC_N_WORDS - 1] = 0x01;
#elif (uECC_WORD_SIZE == 4)
k[uECC_N_WORDS - 1] = 0x00000001;
#elif (uECC_WORD_SIZE == 8)
k[uECC_N_WORDS - 1] ^= 0x0000000100000000;
#endif
}

#else
vli_bytesToNative(k, T);
#endif

if (uECC_sign_with_k(private_key, message_hash, T, signature)) {
if (uECC_sign_with_k(private_key, message_hash, k, signature)) {
return 1;
}

Expand Down
8 changes: 8 additions & 0 deletions uECC.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ faster by about 8% but increases the code size. */

#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)

#define uECC_n_size_1 21 /* secp160r1 */
#define uECC_n_size_2 24 /* secp192r1 */
#define uECC_n_size_3 32 /* secp256r1 */
#define uECC_n_size_4 32 /* secp256k1 */
#define uECC_n_size_5 28 /* secp224r1 */

#define uECC_N_BYTES uECC_CONCAT(uECC_n_size_, uECC_CURVE)

#ifdef __cplusplus
extern "C"
{
Expand Down