Skip to content

Commit

Permalink
make uECC_sign_deterministic conform to RFC 6979
Browse files Browse the repository at this point in the history
  • Loading branch information
Jong-Shian Wu committed Aug 8, 2015
1 parent 81ff1f5 commit e29363a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 5 deletions.
59 changes: 54 additions & 5 deletions uECC.c
Original file line number Diff line number Diff line change
Expand Up @@ -2594,17 +2594,38 @@ 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]; // 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);

// Modular reduction: tmp <- tmp mod n (ONLY FOR RFC6979)
while (vli_cmp_n(tmp, curve_n) >= 0) {
vli_sub(tmp, tmp, curve_n);
}

// Convert the integer tmp back to an octet string (ONLY FOR RFC6979)
#if (uECC_CURVE == uECC_secp160r1)
vli_nativeToBytes(reduced_msg_hash + 1, tmp);
#else
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 +2635,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 @@ -2630,10 +2652,37 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
}
}
#if (uECC_CURVE == uECC_secp160r1)
T[uECC_WORDS] &= 0x01;
//
// NOTE:
//
// The function vli_bytesToNative converts a big-endian array of
// length uECC_BYTES=20 where each unit is 1-byte long into a native
// little-endian array of length uECC_WORDS=20/5/3 where each unit is
// 1/4/8-byte long.
//
// Maybe we should have a version of vli_bytesToNative that does the
// same thing for uECC_N_BYTES=21 and uECC_N_WORDS=21/6/3?
//
// TODO:
//
// Before vli_bytesToNative() we should right-shift all bits in T by 7
// so that the leftmost 161 bits in T are used in order to comform to
// RFC6979.
//
vli_bytesToNative(k, T + 1);
if (T[0] & 1) {
// k <- k + 2^160
#if (uECC_WORD_SIZE == 1 || uECC_WORD_SIZE == 4)
k[uECC_N_WORDS - 1] = 1;
#elif (uECC_WORD_SIZE == 8)
k[uECC_N_WORDS - 1] ^= (1 << 32);
#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

0 comments on commit e29363a

Please sign in to comment.