From 03fee345506b6e2ac10fd5caff3afbf4938cee28 Mon Sep 17 00:00:00 2001 From: Ondrej Mikle Date: Mon, 7 Jul 2014 14:38:14 +0200 Subject: [PATCH 1/3] Validating of public key curve point. --- ecdsa.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- ecdsa.h | 1 + 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/ecdsa.c b/ecdsa.c index 8dcfd0748..14d1d9914 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -459,17 +459,60 @@ int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub) if (pub_key[0] == 0x04) { bn_read_be(pub_key + 1, &(pub->x)); bn_read_be(pub_key + 33, &(pub->y)); - return 1; + return ecdsa_validate_pubkey(pub); } if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords bn_read_be(pub_key + 1, &(pub->x)); uncompress_coords(pub_key[0], &(pub->x), &(pub->y)); - return 1; + return ecdsa_validate_pubkey(pub); } // error return 0; } +// Verifies that: +// - pub is not the point at infinity. +// - pub->x and pub->y are in range [0,p-1]. +// - pub is on the curve. +// - n*pub is the point at infinity. + +int ecdsa_validate_pubkey(const curve_point *pub) +{ + bignum256 y_2, x_3_b; + curve_point temp; + + if (point_is_infinity(pub)) { + return 0; + } + + if (!bn_is_less(&(pub->x), &prime256k1) || !bn_is_less(&(pub->y), &prime256k1)) { + return 0; + } + + memcpy(&y_2, &(pub->y), sizeof(bignum256)); + memcpy(&x_3_b, &(pub->x), sizeof(bignum256)); + + // y^2 + bn_multiply(&(pub->y), &y_2, &prime256k1); + // x^3 + b + bn_multiply(&(pub->x), &x_3_b, &prime256k1); + bn_multiply(&(pub->x), &x_3_b, &prime256k1); + bn_addmodi(&x_3_b, 7, &prime256k1); + + if (!bn_is_equal(&x_3_b, &y_2)) { + return 0; + } + + point_copy(pub, &temp); + point_multiply(&order256k1, pub, &temp); + + if (!point_is_infinity(&temp)) { + return 0; + } + + return 1; +} + // uses secp256k1 curve // pub_key - 65 bytes uncompressed key // signature - 64 bytes signature diff --git a/ecdsa.h b/ecdsa.h index 5aaf7d633..b1a1e7e37 100644 --- a/ecdsa.h +++ b/ecdsa.h @@ -53,6 +53,7 @@ void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr); void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif); int ecdsa_address_decode(const char *addr, uint8_t *out); int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub); +int ecdsa_validate_pubkey(const curve_point *pub); int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len); int ecdsa_verify_double(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len); int ecdsa_verify_digest(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest); From 02048f88b5b99d6ad3a630b461c5be956f00bb30 Mon Sep 17 00:00:00 2001 From: Ondrej Mikle Date: Mon, 7 Jul 2014 15:13:36 +0200 Subject: [PATCH 2/3] Tests for public key validity check. --- tests.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests.c b/tests.c index af80c74a5..a3f45fd5a 100644 --- a/tests.c +++ b/tests.c @@ -852,6 +852,54 @@ START_TEST(test_address) } END_TEST +START_TEST(test_pubkey_validity) +{ + uint8_t pub_key[65]; + curve_point pub; + int res; + + memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf00000000"), 65); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 0); + + memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b8211111111111111111111111111111111"), 65); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 0); + + memcpy(pub_key, fromhex("00"), 1); + res = ecdsa_read_pubkey(pub_key, &pub); + ck_assert_int_eq(res, 0); +} +END_TEST + START_TEST(test_wif) { uint8_t priv_key[32]; @@ -1031,6 +1079,10 @@ Suite *test_suite(void) tcase_add_test(tc, test_mnemonic_check); suite_add_tcase(s, tc); + tc = tcase_create("pubkey_validity"); + tcase_add_test(tc, test_pubkey_validity); + suite_add_tcase(s, tc); + return s; } From b34516bc49cb9dbae6fb6eeb95e325a03a11c036 Mon Sep 17 00:00:00 2001 From: Ondrej Mikle Date: Mon, 7 Jul 2014 16:35:53 +0200 Subject: [PATCH 3/3] Removed unnessary point copy. --- ecdsa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ecdsa.c b/ecdsa.c index 14d1d9914..df7847533 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -503,7 +503,6 @@ int ecdsa_validate_pubkey(const curve_point *pub) return 0; } - point_copy(pub, &temp); point_multiply(&order256k1, pub, &temp); if (!point_is_infinity(&temp)) {