From a46621eb5789749e0e54e97fb6d95390c712a27d Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Tue, 19 May 2015 13:26:24 -0400 Subject: [PATCH 1/6] Added uECC_compute_public_key. --- test/test_compute.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ uECC.c | 12 ++++++++++ uECC.h | 12 ++++++++++ 3 files changed, 82 insertions(+) create mode 100644 test/test_compute.c diff --git a/test/test_compute.c b/test/test_compute.c new file mode 100644 index 0000000..160fac5 --- /dev/null +++ b/test/test_compute.c @@ -0,0 +1,58 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include +#include + +void vli_print(uint8_t *p_vli, unsigned int p_size) +{ + while(p_size) + { + printf("%02X ", (unsigned)p_vli[p_size - 1]); + --p_size; + } +} + +int main() +{ + int i; + + uint8_t l_private[uECC_BYTES]; + + uint8_t l_public[uECC_BYTES * 2]; + uint8_t l_public_computed[uECC_BYTES * 2]; + + printf("Testing 256 random private key pairs\n"); + + for(i=0; i<256; ++i) + { + printf("."); + fflush(stdout); + + int success = uECC_make_key(l_public, l_private); + if (!success) { + printf("uECC_make_key() failed\n"); + return 1; + } + + uECC_compute_public_key(l_private, l_public_computed); + + if(memcmp(l_public, l_public_computed, sizeof(l_public)) != 0) + { + printf("Computed and provided public keys are not identical!\n"); + printf("Computed public key = "); + vli_print(l_public_computed, uECC_BYTES); + printf("\n"); + printf("Provided public key = "); + vli_print(l_public, uECC_BYTES); + printf("\n"); + printf("Private key = "); + vli_print(l_private, uECC_BYTES); + printf("\n"); + } + } + printf("\n"); + + return 0; +} diff --git a/uECC.c b/uECC.c index 96726a9..33cae0c 100644 --- a/uECC.c +++ b/uECC.c @@ -2380,6 +2380,18 @@ int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uE return vli_equal(rx, r); } +void uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]) { + EccPoint l_public; + uECC_word_t l_private[uECC_WORDS]; + + vli_bytesToNative(l_private, p_privateKey); + + EccPoint_mult(&l_public, &curve_G, l_private, 0, vli_numBits(l_private, uECC_WORDS)); + + vli_nativeToBytes(p_publicKey, l_public.x); + vli_nativeToBytes(p_publicKey + uECC_BYTES, l_public.y); +} + int uECC_bytes(void) { return uECC_BYTES; diff --git a/uECC.h b/uECC.h index 18c1adb..e1a4fa8 100644 --- a/uECC.h +++ b/uECC.h @@ -178,6 +178,18 @@ Returns 1 if the public key is valid, 0 if it is invalid. */ int uECC_valid_public_key(const uint8_t p_publicKey[uECC_BYTES*2]); +/* uECC_compute_public_key() function. +Compute the corresponding public key for a private key. + +Inputs: + p_privateKey - The private key to compute the public key for + +Outputs: + p_publicKey - Will be filled in with the corresponding public key +*/ +void uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]); + + /* uECC_bytes() function. Returns the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages. */ From 08b675503d913bb6226e8c89101bbb6df7c05602 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 20 May 2015 11:50:08 -0400 Subject: [PATCH 2/6] Removed some stray whitespace. --- uECC.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uECC.h b/uECC.h index e1a4fa8..ace1f4e 100644 --- a/uECC.h +++ b/uECC.h @@ -78,7 +78,7 @@ return 1 if the random data was generated, or 0 if the random data could not be On platforms where there is no predefined RNG function (eg embedded platforms), this must be called before uECC_make_key() or uECC_sign() are used. - + Inputs: p_rng - The function that will be used to generate random bytes. */ @@ -86,7 +86,7 @@ void uECC_set_rng(uECC_RNG_Function p_rng); /* uECC_make_key() function. Create a public/private key pair. - + Outputs: p_publicKey - Will be filled in with the public key. p_privateKey - Will be filled in with the private key. From ae3e85813614402347f143bd1df3caa148a5a48e Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 20 May 2015 12:02:51 -0400 Subject: [PATCH 3/6] Added error checking to uECC_compute_public_key. --- test/test_compute.c | 23 ++++++++++++++++++----- uECC.c | 26 +++++++++++++++++++++++--- uECC.h | 4 +++- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/test/test_compute.c b/test/test_compute.c index 160fac5..88b6703 100644 --- a/test/test_compute.c +++ b/test/test_compute.c @@ -17,12 +17,13 @@ void vli_print(uint8_t *p_vli, unsigned int p_size) int main() { int i; - + int success; + uint8_t l_private[uECC_BYTES]; - + uint8_t l_public[uECC_BYTES * 2]; uint8_t l_public_computed[uECC_BYTES * 2]; - + printf("Testing 256 random private key pairs\n"); for(i=0; i<256; ++i) @@ -36,7 +37,10 @@ int main() return 1; } - uECC_compute_public_key(l_private, l_public_computed); + success = uECC_compute_public_key(l_private, l_public_computed); + if (!success) { + printf("uECC_compute_public_key() failed\n"); + } if(memcmp(l_public, l_public_computed, sizeof(l_public)) != 0) { @@ -52,7 +56,16 @@ int main() printf("\n"); } } + printf("\n"); - + + printf("Testing private key = 0\n"); + + memset(l_private, 0, uECC_BYTES); + success = uECC_compute_public_key(l_private, l_public_computed); + if (success) { + printf("uECC_compute_public_key() should have failed\n"); + } + return 0; } diff --git a/uECC.c b/uECC.c index 33cae0c..dd9da34 100644 --- a/uECC.c +++ b/uECC.c @@ -2380,16 +2380,36 @@ int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uE return vli_equal(rx, r); } -void uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]) { - EccPoint l_public; +int uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]) { uECC_word_t l_private[uECC_WORDS]; - vli_bytesToNative(l_private, p_privateKey); + /* Make sure the private key is in the range [1, n-1]. */ + if(vli_isZero(l_private)) + { + return 0; + } + +#if uECC_CURVE != uECC_secp160r1 + if(vli_cmp(curve_n, l_private) != 1) + { + return 0; + } +#endif + + /* Compute the public point */ + EccPoint l_public; EccPoint_mult(&l_public, &curve_G, l_private, 0, vli_numBits(l_private, uECC_WORDS)); + if (EccPoint_isZero(&l_public)) + { + return 0; + } + vli_nativeToBytes(p_publicKey, l_public.x); vli_nativeToBytes(p_publicKey + uECC_BYTES, l_public.y); + + return 1; } int uECC_bytes(void) diff --git a/uECC.h b/uECC.h index ace1f4e..4787457 100644 --- a/uECC.h +++ b/uECC.h @@ -186,8 +186,10 @@ Inputs: Outputs: p_publicKey - Will be filled in with the corresponding public key + +Returns 1 if the key was computed successfully, 0 if an error occurred. */ -void uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]); +int uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]); /* uECC_bytes() function. From d360398681165122e3ed1c226c2282cfab7d81fb Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 20 May 2015 12:13:18 -0400 Subject: [PATCH 4/6] Refactor uECC_make_key to use uECC_compute_public_key. --- uECC.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/uECC.c b/uECC.c index dd9da34..5aa7840 100644 --- a/uECC.c +++ b/uECC.c @@ -1789,36 +1789,26 @@ static void vli_bytesToNative(uint64_t *p_native, const uint8_t *p_bytes) int uECC_make_key(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_privateKey[uECC_BYTES]) { - EccPoint l_public; uECC_word_t l_private[uECC_WORDS]; uECC_word_t l_tries = 0; - - do + + while (1) { - repeat: if(!g_rng((uint8_t *)l_private, sizeof(l_private)) || (l_tries++ >= MAX_TRIES)) { return 0; } if(vli_isZero(l_private)) { - goto repeat; + continue; } - - /* Make sure the private key is in the range [1, n-1]. */ - #if uECC_CURVE != uECC_secp160r1 - if(vli_cmp(curve_n, l_private) != 1) - { - goto repeat; - } - #endif - EccPoint_mult(&l_public, &curve_G, l_private, 0, vli_numBits(l_private, uECC_WORDS)); - } while(EccPoint_isZero(&l_public)); - - vli_nativeToBytes(p_privateKey, l_private); - vli_nativeToBytes(p_publicKey, l_public.x); - vli_nativeToBytes(p_publicKey + uECC_BYTES, l_public.y); + vli_nativeToBytes(p_privateKey, l_private); + if (uECC_compute_public_key(p_privateKey, p_publicKey)) { + break; + } + } + return 1; } From 9bbd41962a58ecf461f8e204a96efa51017598dd Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 20 May 2015 21:04:27 -0400 Subject: [PATCH 5/6] Refactored compute_public_key, created native version. --- uECC.c | 58 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/uECC.c b/uECC.c index 5aa7840..3f83a31 100644 --- a/uECC.c +++ b/uECC.c @@ -1696,6 +1696,32 @@ static void EccPoint_mult(EccPoint * RESTRICT p_result, const EccPoint * RESTRIC vli_set(p_result->y, Ry[0]); } +static int EccPoint_compute_public_key(EccPoint *p_result, const uECC_word_t *p_private) { + + /* Make sure the private key is in the range [1, n-1]. */ + if(vli_isZero(p_private)) + { + return 0; + } + +#if uECC_CURVE != uECC_secp160r1 + if(vli_cmp(curve_n, p_private) != 1) + { + return 0; + } +#endif + + /* Compute the public point */ + EccPoint_mult(p_result, &curve_G, p_private, 0, vli_numBits(p_private, uECC_WORDS)); + + if (EccPoint_isZero(p_result)) + { + return 0; + } + + return 1; +} + /* Compute a = sqrt(a) (mod curve_p). */ static void mod_sqrt(uECC_word_t *a) { @@ -1792,6 +1818,8 @@ int uECC_make_key(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_privateKey[uECC_B uECC_word_t l_private[uECC_WORDS]; uECC_word_t l_tries = 0; + EccPoint l_public; + while (1) { if(!g_rng((uint8_t *)l_private, sizeof(l_private)) || (l_tries++ >= MAX_TRIES)) @@ -1803,12 +1831,16 @@ int uECC_make_key(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_privateKey[uECC_B continue; } - vli_nativeToBytes(p_privateKey, l_private); - if (uECC_compute_public_key(p_privateKey, p_publicKey)) { + if (EccPoint_compute_public_key(&l_public, l_private)) { break; } } + vli_nativeToBytes(p_privateKey, l_private); + + vli_nativeToBytes(p_publicKey, l_public.x); + vli_nativeToBytes(p_publicKey + uECC_BYTES, l_public.y); + return 1; } @@ -2370,29 +2402,13 @@ int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uE return vli_equal(rx, r); } -int uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]) { +int uECC_compute_public_key(const uint8_t p_privateKey[uECC_BYTES], uint8_t p_publicKey[uECC_BYTES * 2]) +{ uECC_word_t l_private[uECC_WORDS]; vli_bytesToNative(l_private, p_privateKey); - /* Make sure the private key is in the range [1, n-1]. */ - if(vli_isZero(l_private)) - { - return 0; - } - -#if uECC_CURVE != uECC_secp160r1 - if(vli_cmp(curve_n, l_private) != 1) - { - return 0; - } -#endif - - /* Compute the public point */ EccPoint l_public; - EccPoint_mult(&l_public, &curve_G, l_private, 0, vli_numBits(l_private, uECC_WORDS)); - - if (EccPoint_isZero(&l_public)) - { + if (!EccPoint_compute_public_key(&l_public, l_private)) { return 0; } From b1907a64f088cf6a446a2a27d26ab4b59095e35b Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 20 May 2015 22:50:37 -0400 Subject: [PATCH 6/6] Removed unnecessary private key check in uECC_make_key. --- uECC.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/uECC.c b/uECC.c index 3f83a31..4c3a14c 100644 --- a/uECC.c +++ b/uECC.c @@ -1826,10 +1826,6 @@ int uECC_make_key(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_privateKey[uECC_B { return 0; } - if(vli_isZero(l_private)) - { - continue; - } if (EccPoint_compute_public_key(&l_public, l_private)) { break;