From 1730601d3017bf3fab271663895abff8457e3652 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 10 Jul 2018 20:02:53 +0200 Subject: [PATCH] refactor mnemonic_check and mnemonic_to_entropy, style changes --- Makefile | 2 +- bip32.c | 54 ++++---- bip32.h | 2 +- bip39.c | 94 ++++--------- ed25519-donna/ed25519.c | 4 +- ed25519-donna/ed25519.h | 4 +- tests/test_check.c | 255 ++++-------------------------------- tests/test_check_cardano.h | 216 ++++++++++++++++++++++++++++++ tests/test_check_cashaddr.h | 6 - tests/test_check_segwit.h | 6 - 10 files changed, 292 insertions(+), 351 deletions(-) create mode 100644 tests/test_check_cardano.h diff --git a/Makefile b/Makefile index 9bf421eca..6ccba84e5 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ tests: tests/test_check tests/test_openssl tests/test_speed tests/libtrezor-cryp tests/aestst: aes/aestst.o aes/aescrypt.o aes/aeskey.o aes/aestab.o $(CC) $^ -o $@ -tests/test_check.o: tests/test_check_segwit.h tests/test_check_cashaddr.h +tests/test_check.o: tests/test_check_cardano.h tests/test_check_cashaddr.h tests/test_check_segwit.h tests/test_check: tests/test_check.o $(OBJS) $(CC) tests/test_check.o $(OBJS) $(TESTLIBS) -o tests/test_check diff --git a/bip32.c b/bip32.c index b36ddde78..8baa885b7 100644 --- a/bip32.c +++ b/bip32.c @@ -268,12 +268,11 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i) return 1; } -#ifdef USE_CARDANO +#if USE_CARDANO static void multiply8(uint8_t *dst, uint8_t *src, int bytes) { - int i; uint8_t prev_acc = 0; - for (i = 0; i < bytes; i++) { + for (int i = 0; i < bytes; i++) { dst[i] = (src[i] << 3) + (prev_acc & 0x8); prev_acc = src[i] >> 5; } @@ -281,8 +280,7 @@ static void multiply8(uint8_t *dst, uint8_t *src, int bytes) static void add_256bits(uint8_t *dst, uint8_t *src1, uint8_t *src2) { - int i; - for (i = 0; i < 32; i++) { + for (int i = 0; i < 32; i++) { uint8_t a = src1[i]; uint8_t b = src2[i]; uint16_t r = a + b; @@ -290,7 +288,7 @@ static void add_256bits(uint8_t *dst, uint8_t *src1, uint8_t *src2) } } -int ed25519_scalar_add(const uint8_t *sk1, const uint8_t *sk2, uint8_t *res) +static int ed25519_scalar_add(const uint8_t *sk1, const uint8_t *sk2, uint8_t *res) { bignum256modm s1, s2; expand256_modm(s1, sk1, 32); @@ -302,9 +300,9 @@ int ed25519_scalar_add(const uint8_t *sk1, const uint8_t *sk2, uint8_t *res) int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i) { - //checks for hardened/non-hardened derivation, keysize 32 means we are dealing with public key and thus non-h, keysize 64 is for private key + // checks for hardened/non-hardened derivation, keysize 32 means we are dealing with public key and thus non-h, keysize 64 is for private key int keysize = 32; - if(i & 0x80000000){ + if (i & 0x80000000) { keysize = 64; } @@ -342,10 +340,10 @@ int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i) memcpy(inout->private_key, res_key, 32); memcpy(inout->private_key_extension, res_key + 32, 32); - if(keysize == 64){ - data[0]=1; - }else{ - data[0]=3; + if (keysize == 64) { + data[0] = 1; + } else { + data[0] = 3; } hmac_sha512_Init(&ctx, inout->chain_code, 32); hmac_sha512_Update(&ctx, data, 1 + keysize + 4); @@ -366,28 +364,24 @@ int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i) return 1; } -void decitoa(int val, char * out){ - - static char buf[32] = {0}; - - int i = 30; - - for(; val && i ; --i, val /= 10){ - buf[i] = "0123456789"[val % 10]; - } - - memcpy(out,&buf[i+1],strlen(&buf[i+1])+1); +static void decitoa(int val, char *out) { + static char buf[32] = {0}; + int i = 30; + for (; val && i; --i, val /= 10) { + buf[i] = "0123456789"[val % 10]; + } + memcpy(out, &buf[i + 1], strlen(&buf[i + 1]) + 1); } -int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out){ +int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out) { uint8_t hash[32]; uint8_t cbor[32+2]; - if(seed_len < 24){ + if (seed_len < 24) { // cbor encodes length directly into first byte if its smaller than 24 seed[1] = 64 | seed_len; blake2b(seed + 1, seed_len + 1, hash, 32); - }else{ + } else { seed[0] = 88; seed[1] = seed_len; blake2b(seed, seed_len + 2, hash, 32); @@ -410,7 +404,7 @@ int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out){ out->curve = get_curve_by_name(ED25519_CARDANO_NAME); static CONFIDENTIAL HMAC_SHA512_CTX ctx; - for(int i = 1; i <= 1000; i++){ + for (int i = 1; i <= 1000; i++){ hmac_sha512_Init(&ctx, cbor, 34); decitoa(i, c); memcpy(salt + 16, c, strlen(c) + 1); @@ -434,7 +428,7 @@ int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out){ memzero(salt, strlen(salt) + 1); memzero(c, strlen(c) + 1); - if(failed){ + if (failed) { memzero(seed, sizeof(seed)); memzero(secret, sizeof(secret)); memzero(chain_code, sizeof(chain_code)); @@ -642,8 +636,8 @@ void hdnode_fill_public_key(HDNode *node) #endif } else if (node->curve == &curve25519_info) { curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key); -#ifdef USE_CARDANO - } else if (node->curve == &ed25519_cardano_info){ +#if USE_CARDANO + } else if (node->curve == &ed25519_cardano_info) { ed25519_publickey_ext(node->private_key, node->private_key_extension, node->public_key + 1); #endif } diff --git a/bip32.h b/bip32.h index 1cdc01621..c98019658 100644 --- a/bip32.h +++ b/bip32.h @@ -62,7 +62,7 @@ int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNod #define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000)) int hdnode_private_ckd(HDNode *inout, uint32_t i); -#ifdef USE_CARDANO +#if USE_CARDANO int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out); #endif diff --git a/bip39.c b/bip39.c index 464294620..ac4e4fb36 100644 --- a/bip39.c +++ b/bip39.c @@ -136,14 +136,14 @@ const uint16_t *mnemonic_from_data_indexes(const uint8_t *data, int len) return mnemo; } -int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy){ +int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) +{ if (!mnemonic) { return 0; } - uint32_t i, n; + uint32_t i = 0, n = 0; - i = 0; n = 0; while (mnemonic[i]) { if (mnemonic[i] == ' ') { n++; @@ -151,17 +151,18 @@ int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy){ i++; } n++; + // check number of words if (n != 12 && n != 18 && n != 24) { return 0; } char current_word[10]; - uint32_t j, k, ki, bi; + uint32_t j, k, ki, bi = 0; uint8_t bits[32 + 1]; memzero(bits, sizeof(bits)); - i = 0; bi = 0; + i = 0; while (mnemonic[i]) { j = 0; while (mnemonic[i] != ' ' && mnemonic[i] != 0) { @@ -172,7 +173,9 @@ int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy){ i++; j++; } current_word[j] = 0; - if (mnemonic[i] != 0) i++; + if (mnemonic[i] != 0) { + i++; + } k = 0; for (;;) { if (!wordlist[k]) { // word not found @@ -193,78 +196,27 @@ int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy){ if (bi != n * 11) { return 0; } - memcpy(entropy,bits,sizeof(bits)); - return (n*11); + memcpy(entropy, bits, sizeof(bits)); + return n * 11; } int mnemonic_check(const char *mnemonic) { - if (!mnemonic) { - return 0; - } - - uint32_t i, n; - - i = 0; n = 0; - while (mnemonic[i]) { - if (mnemonic[i] == ' ') { - n++; - } - i++; - } - n++; - // check number of words - if (n != 12 && n != 18 && n != 24) { - return 0; - } - - char current_word[10]; - uint32_t j, k, ki, bi; uint8_t bits[32 + 1]; - - memzero(bits, sizeof(bits)); - i = 0; bi = 0; - while (mnemonic[i]) { - j = 0; - while (mnemonic[i] != ' ' && mnemonic[i] != 0) { - if (j >= sizeof(current_word) - 1) { - return 0; - } - current_word[j] = mnemonic[i]; - i++; j++; - } - current_word[j] = 0; - if (mnemonic[i] != 0) i++; - k = 0; - for (;;) { - if (!wordlist[k]) { // word not found - return 0; - } - if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k - for (ki = 0; ki < 11; ki++) { - if (k & (1 << (10 - ki))) { - bits[bi / 8] |= 1 << (7 - (bi % 8)); - } - bi++; - } - break; - } - k++; - } - } - if (bi != n * 11) { + int seed_len = mnemonic_to_entropy(mnemonic, bits); + if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) { return 0; } - bits[32] = bits[n * 4 / 3]; - sha256_Raw(bits, n * 4 / 3, bits); - if (n == 12) { - return (bits[0] & 0xF0) == (bits[32] & 0xF0); // compare first 4 bits - } else - if (n == 18) { - return (bits[0] & 0xFC) == (bits[32] & 0xFC); // compare first 6 bits - } else - if (n == 24) { - return bits[0] == bits[32]; // compare 8 bits + int words = seed_len / 11; + + uint8_t checksum = bits[words * 4 / 3]; + sha256_Raw(bits, words * 4 / 3, bits); + if (words == 12) { + return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits + } else if (words == 18) { + return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits + } else if (words == 24) { + return bits[0] == checksum; // compare 8 bits } return 0; } diff --git a/ed25519-donna/ed25519.c b/ed25519-donna/ed25519.c index 46b676a62..880b59d84 100644 --- a/ed25519-donna/ed25519.c +++ b/ed25519-donna/ed25519.c @@ -54,7 +54,7 @@ ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key p ge25519_pack(pk, &A); } -#ifdef USE_CARDANO +#if USE_CARDANO void ED25519_FN(ed25519_publickey_ext) (const ed25519_secret_key sk, const ed25519_secret_key skext, ed25519_public_key pk) { bignum256modm a; @@ -133,7 +133,7 @@ ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_sec contract256_modm(RS + 32, S); } -#ifdef USE_CARDANO +#if USE_CARDANO void ED25519_FN(ed25519_sign_ext) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_secret_key skext, const ed25519_public_key pk, ed25519_signature RS) { ed25519_hash_context ctx; diff --git a/ed25519-donna/ed25519.h b/ed25519-donna/ed25519.h index 78b77eec4..9d9838d14 100644 --- a/ed25519-donna/ed25519.h +++ b/ed25519-donna/ed25519.h @@ -14,13 +14,13 @@ typedef unsigned char curve25519_key[32]; typedef unsigned char ed25519_cosi_signature[32]; void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk); -#ifdef USE_CARDANO +#if USE_CARDANO void ed25519_publickey_ext(const ed25519_secret_key sk, const ed25519_secret_key skext, ed25519_public_key pk); #endif int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS); void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS); -#ifdef USE_CARDANO +#if USE_CARDANO void ed25519_sign_ext(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_secret_key skext, const ed25519_public_key pk, ed25519_signature RS); #endif diff --git a/tests/test_check.c b/tests/test_check.c index d9d55ab9f..7db4e1d63 100644 --- a/tests/test_check.c +++ b/tests/test_check.c @@ -1872,141 +1872,6 @@ START_TEST(test_bip32_decred_vector_2) } END_TEST -// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128 -START_TEST(test_bip32_cardano_hdnode_vector_1) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - ck_assert_mem_eq(node.chain_code, fromhex("739f4b3caca4c9ad4fcd4bdc2ef42c8601af8d6946999ef85ef6ae84f66e72eb"), 32); - ck_assert_mem_eq(node.private_key, fromhex("6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_2) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - - ck_assert_mem_eq(node.chain_code, fromhex("6755cb82e892d6614c007a5efbceb21d95a5244e269d0e206b48b9a495390b03"), 32); - ck_assert_mem_eq(node.private_key, fromhex("e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_3) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000001); - - ck_assert_mem_eq(node.chain_code, fromhex("47a242713bd18608231147c066b6083bfc1e9066fec9f621844c84fed6228a34"), 32); - ck_assert_mem_eq(node.private_key, fromhex("9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_4) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - - ck_assert_mem_eq(node.chain_code, fromhex("d6798491b9fa4612370ae5ef3c623a0b6872f3ad8f26970885fa67c83bdc425e"), 32); - ck_assert_mem_eq(node.private_key, fromhex("52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_5) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - - ck_assert_mem_eq(node.chain_code, fromhex("4169a2a32e3618a903e930bd1a713033a38f92389093408394e29ac37a1752ea"), 32); - ck_assert_mem_eq(node.private_key, fromhex("11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_6) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); - - ck_assert_mem_eq(node.chain_code, fromhex("3ae9c99a5925cba2dcf121baf3a0254f3dea23c129f9eb70a8a7e8897c5199ba"), 32); - ck_assert_mem_eq(node.private_key, fromhex("5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76"), 32); -} -END_TEST - -START_TEST(test_bip32_cardano_hdnode_vector_7) -{ - HDNode node; - - uint8_t seed[66]; - int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); - hdnode_from_seed_cardano(seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0xBB9ACA00); - - ck_assert_mem_eq(node.chain_code, fromhex("15c450b86dd7dd83b31951d9ee03eb1a7925161d817bd517c69cf09e3671f1ca"), 32); - ck_assert_mem_eq(node.private_key, fromhex("624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00"), 32); -} -END_TEST - START_TEST(test_ecdsa_signature) { int res; @@ -2014,7 +1879,6 @@ START_TEST(test_ecdsa_signature) uint8_t pubkey[65]; const ecdsa_curve *curve = &secp256k1; - // sha2(sha2("\x18Bitcoin Signed Message:\n\x0cHello World!")) memcpy(digest, fromhex("de4e9524586d6fce45667f9ff12f661e79870c4105fa0fb58af976619bb11432"), 32); // r = 2: Four points should exist @@ -2968,8 +2832,11 @@ START_TEST(test_mnemonic_to_entropy) a = vectors; b = vectors + 1; while (*a && *b) { - mnemonic_to_entropy(*b,entropy); - ck_assert_mem_eq(entropy, fromhex(*a), strlen(*a) / 2); + int seed_len = mnemonic_to_entropy(*b, entropy); + ck_assert_int_eq(seed_len % 33, 0); + seed_len = seed_len * 4 / 33; + ck_assert_int_eq(seed_len, strlen(*a) / 2); + ck_assert_mem_eq(entropy, fromhex(*a), seed_len); a += 2; b += 2; } } @@ -3810,81 +3677,6 @@ START_TEST(test_ge25519_double_scalarmult_vartime2) } END_TEST -// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128 -START_TEST(test_ed25519_cardano_sign_vectors) -{ - ed25519_public_key public_key; - ed25519_secret_key secret_key; - ed25519_secret_key secret_key_extension; - ed25519_signature signature; - - static const char *vectors[] = { - "6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53", // private key - "60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e", // private key extension - "64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1", // public key - "45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c79331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10d", // signature - - "e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c", // private key - "794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4", // private key extension - "95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df", // public key - "f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b19ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560f", // signature - - "9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c", // private key - "b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb", // private key extension - "79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f", // public key - "2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800f", // signature - - "52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c", // private key - "6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803", // private key extension - "dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6", // public key - "0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a62a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd781602", // signature - - "11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04", // private key - "c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352", // private key extension - "839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78", // public key - "e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa4905", // signature - - "5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505", // private key - "ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd", // private key extension - "75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76", // public key - "631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fbc10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda598906", // signature - - "624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d", // private key - "097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02", // private key extension - "0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00", // public key - "1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f901", // signature - - 0, 0, - }; - - const char **test_data; - test_data = vectors; - while (*test_data) { - memcpy(secret_key, fromhex(*test_data), 32); - MARK_SECRET_DATA(secret_key, sizeof(secret_key)); - - memcpy(secret_key_extension, fromhex(*(test_data + 1)), 32); - MARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension)); - - ed25519_publickey_ext(secret_key, secret_key_extension, public_key); - UNMARK_SECRET_DATA(public_key, sizeof(public_key)); - - ck_assert_mem_eq(public_key, fromhex(*(test_data + 2)), 32); - - const uint8_t * message = (const uint8_t *) "Hello World"; - ed25519_sign_ext(message, 11, secret_key, secret_key_extension, public_key, signature); - UNMARK_SECRET_DATA(signature, sizeof(signature)); - - ck_assert_mem_eq(signature, fromhex(*(test_data + 3)), 64); - - UNMARK_SECRET_DATA(secret_key, sizeof(secret_key)); - UNMARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension)); - - test_data += 4; - } -} -END_TEST - static void test_bip32_ecdh_init_node(HDNode *node, const char *seed_str, const char *curve_name) { hdnode_from_seed((const uint8_t *)seed_str, strlen(seed_str), curve_name, node); hdnode_fill_public_key(node); @@ -4957,9 +4749,12 @@ START_TEST(test_rc4_rfc6229) END_TEST #include "test_check_segwit.h" - #include "test_check_cashaddr.h" +#if USE_CARDANO +#include "test_check_cardano.h" +#endif + // define test suite and cases Suite *test_suite(void) { @@ -5040,16 +4835,6 @@ Suite *test_suite(void) tcase_add_test(tc, test_bip32_decred_vector_2); suite_add_tcase(s, tc); - tc = tcase_create("bip32-cardano"); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_1); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_2); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_3); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_4); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_5); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_6); - tcase_add_test(tc, test_bip32_cardano_hdnode_vector_7); - suite_add_tcase(s,tc); - tc = tcase_create("ecdsa"); tcase_add_test(tc, test_ecdsa_signature); suite_add_tcase(s, tc); @@ -5115,11 +4900,8 @@ Suite *test_suite(void) tc = tcase_create("bip39"); tcase_add_test(tc, test_mnemonic); tcase_add_test(tc, test_mnemonic_check); - suite_add_tcase(s, tc); - - tc = tcase_create("bip39-cardano"); tcase_add_test(tc, test_mnemonic_to_entropy); - suite_add_tcase(s,tc); + suite_add_tcase(s, tc); tc = tcase_create("pubkey_validity"); tcase_add_test(tc, test_pubkey_validity); @@ -5176,10 +4958,6 @@ Suite *test_suite(void) tcase_add_test(tc, test_ge25519_double_scalarmult_vartime2); suite_add_tcase(s, tc); - tc = tcase_create("ed25519-cardano"); - tcase_add_test(tc, test_ed25519_cardano_sign_vectors); - suite_add_tcase(s,tc); - tc = tcase_create("script"); tcase_add_test(tc, test_output_script); suite_add_tcase(s, tc); @@ -5222,6 +5000,19 @@ Suite *test_suite(void) tcase_add_test(tc, test_cashaddr); suite_add_tcase(s, tc); +#if USE_CARDANO + tc = tcase_create("bip32-cardano"); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_1); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_2); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_3); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_4); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_5); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_6); + tcase_add_test(tc, test_bip32_cardano_hdnode_vector_7); + tcase_add_test(tc, test_ed25519_cardano_sign_vectors); + suite_add_tcase(s,tc); +#endif + return s; } diff --git a/tests/test_check_cardano.h b/tests/test_check_cardano.h new file mode 100644 index 000000000..58f87b989 --- /dev/null +++ b/tests/test_check_cardano.h @@ -0,0 +1,216 @@ +// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128 +START_TEST(test_bip32_cardano_hdnode_vector_1) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + ck_assert_mem_eq(node.chain_code, fromhex("739f4b3caca4c9ad4fcd4bdc2ef42c8601af8d6946999ef85ef6ae84f66e72eb"), 32); + ck_assert_mem_eq(node.private_key, fromhex("6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_2) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + + ck_assert_mem_eq(node.chain_code, fromhex("6755cb82e892d6614c007a5efbceb21d95a5244e269d0e206b48b9a495390b03"), 32); + ck_assert_mem_eq(node.private_key, fromhex("e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_3) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000001); + + ck_assert_mem_eq(node.chain_code, fromhex("47a242713bd18608231147c066b6083bfc1e9066fec9f621844c84fed6228a34"), 32); + ck_assert_mem_eq(node.private_key, fromhex("9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_4) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + hdnode_private_ckd_cardano(&node, 0x80000001); + + ck_assert_mem_eq(node.chain_code, fromhex("d6798491b9fa4612370ae5ef3c623a0b6872f3ad8f26970885fa67c83bdc425e"), 32); + ck_assert_mem_eq(node.private_key, fromhex("52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_5) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + hdnode_private_ckd_cardano(&node, 0x80000001); + hdnode_private_ckd_cardano(&node, 0x80000002); + + ck_assert_mem_eq(node.chain_code, fromhex("4169a2a32e3618a903e930bd1a713033a38f92389093408394e29ac37a1752ea"), 32); + ck_assert_mem_eq(node.private_key, fromhex("11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_6) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + hdnode_private_ckd_cardano(&node, 0x80000001); + hdnode_private_ckd_cardano(&node, 0x80000002); + hdnode_private_ckd_cardano(&node, 0x80000002); + + ck_assert_mem_eq(node.chain_code, fromhex("3ae9c99a5925cba2dcf121baf3a0254f3dea23c129f9eb70a8a7e8897c5199ba"), 32); + ck_assert_mem_eq(node.private_key, fromhex("5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76"), 32); +} +END_TEST + +START_TEST(test_bip32_cardano_hdnode_vector_7) +{ + HDNode node; + + uint8_t seed[66]; + int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed + 2); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano(seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + hdnode_private_ckd_cardano(&node, 0x80000001); + hdnode_private_ckd_cardano(&node, 0x80000002); + hdnode_private_ckd_cardano(&node, 0x80000002); + hdnode_private_ckd_cardano(&node, 0xBB9ACA00); + + ck_assert_mem_eq(node.chain_code, fromhex("15c450b86dd7dd83b31951d9ee03eb1a7925161d817bd517c69cf09e3671f1ca"), 32); + ck_assert_mem_eq(node.private_key, fromhex("624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d"), 32); + ck_assert_mem_eq(node.private_key_extension, fromhex("097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02"), 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq(node.public_key + 1, fromhex("0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00"), 32); +} +END_TEST + +// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128 +START_TEST(test_ed25519_cardano_sign_vectors) +{ + ed25519_public_key public_key; + ed25519_secret_key secret_key; + ed25519_secret_key secret_key_extension; + ed25519_signature signature; + + static const char *vectors[] = { + "6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53", // private key + "60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e", // private key extension + "64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1", // public key + "45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c79331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10d", // signature + + "e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c", // private key + "794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4", // private key extension + "95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df", // public key + "f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b19ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560f", // signature + + "9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c", // private key + "b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb", // private key extension + "79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f", // public key + "2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800f", // signature + + "52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c", // private key + "6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803", // private key extension + "dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6", // public key + "0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a62a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd781602", // signature + + "11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04", // private key + "c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352", // private key extension + "839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78", // public key + "e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa4905", // signature + + "5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505", // private key + "ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd", // private key extension + "75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76", // public key + "631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fbc10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda598906", // signature + + "624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d", // private key + "097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02", // private key extension + "0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00", // public key + "1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f901", // signature + + 0, 0, + }; + + const char **test_data; + test_data = vectors; + while (*test_data) { + memcpy(secret_key, fromhex(*test_data), 32); + MARK_SECRET_DATA(secret_key, sizeof(secret_key)); + + memcpy(secret_key_extension, fromhex(*(test_data + 1)), 32); + MARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension)); + + ed25519_publickey_ext(secret_key, secret_key_extension, public_key); + UNMARK_SECRET_DATA(public_key, sizeof(public_key)); + + ck_assert_mem_eq(public_key, fromhex(*(test_data + 2)), 32); + + const uint8_t * message = (const uint8_t *) "Hello World"; + ed25519_sign_ext(message, 11, secret_key, secret_key_extension, public_key, signature); + UNMARK_SECRET_DATA(signature, sizeof(signature)); + + ck_assert_mem_eq(signature, fromhex(*(test_data + 3)), 64); + + UNMARK_SECRET_DATA(secret_key, sizeof(secret_key)); + UNMARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension)); + + test_data += 4; + } +} +END_TEST diff --git a/tests/test_check_cashaddr.h b/tests/test_check_cashaddr.h index de93d0140..cc4608730 100644 --- a/tests/test_check_cashaddr.h +++ b/tests/test_check_cashaddr.h @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "cash_addr.h" static const char* valid_cashchecksum[] = { @@ -79,4 +74,3 @@ START_TEST(test_cashaddr) } } END_TEST - diff --git a/tests/test_check_segwit.h b/tests/test_check_segwit.h index 6ebae766f..c0b7ef403 100644 --- a/tests/test_check_segwit.h +++ b/tests/test_check_segwit.h @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "segwit_addr.h" static const char* valid_checksum[] = { @@ -187,4 +182,3 @@ START_TEST(test_segwit) } } END_TEST -