From 0c622d62e1f1e052c2292d39093222ce358ca7b0 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Fri, 29 Mar 2019 15:44:55 +0100 Subject: [PATCH] format: start using clang-format with style=Google --- .clang-format | 2 + address.c | 102 +- address.h | 5 +- base32.c | 317 +- base32.h | 9 +- base58.c | 417 +- base58.h | 14 +- bignum.c | 1696 +++-- bignum.h | 57 +- bip32.c | 1378 ++-- bip32.h | 96 +- bip39.c | 355 +- bip39.h | 9 +- bip39_english.h | 2393 +------ blake2_common.h | 38 +- cash_addr.c | 262 +- cash_addr.h | 41 +- ecdsa.c | 1968 +++--- ecdsa.h | 91 +- hasher.c | 195 +- hasher.h | 54 +- hmac.c | 248 +- hmac.h | 32 +- memzero.c | 32 +- memzero.h | 2 +- monero/monero.h | 4 +- monero/range_proof.c | 162 +- monero/range_proof.h | 19 +- monero/serialize.c | 85 +- monero/serialize.h | 6 +- monero/xmr.c | 181 +- monero/xmr.h | 41 +- nem.c | 833 +-- nem.h | 219 +- nist256p1.c | 55 +- nist256p1.h | 2 +- options.h | 2 +- pbkdf2.c | 240 +- pbkdf2.h | 42 +- rand.c | 69 +- rc4.c | 44 +- rc4.h | 6 +- rfc6979.c | 71 +- rfc6979.h | 5 +- ripemd160.h | 16 +- script.c | 68 +- script.h | 3 +- secp256k1.c | 89 +- secp256k1.h | 2 +- segwit_addr.h | 44 +- shell.nix | 2 +- tests/test_check.c | 12755 ++++++++++++++++++++++------------ tests/test_check_cardano.h | 546 +- tests/test_check_cashaddr.h | 119 +- tests/test_check_monero.h | 2187 +++--- tests/test_check_segwit.h | 292 +- tests/test_openssl.c | 179 +- tests/test_speed.c | 308 +- tools/bip39bruteforce.c | 125 +- tools/mktable.c | 106 +- tools/xpubaddrgen.c | 74 +- 61 files changed, 15355 insertions(+), 13459 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..58d4b3b68 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +--- +BasedOnStyle: Google diff --git a/address.c b/address.c index c63b501ac..2862c9548 100644 --- a/address.c +++ b/address.c @@ -24,66 +24,68 @@ #include "address.h" #include "bignum.h" -size_t address_prefix_bytes_len(uint32_t address_type) -{ - if (address_type <= 0xFF) return 1; - if (address_type <= 0xFFFF) return 2; - if (address_type <= 0xFFFFFF) return 3; - return 4; +size_t address_prefix_bytes_len(uint32_t address_type) { + if (address_type <= 0xFF) return 1; + if (address_type <= 0xFFFF) return 2; + if (address_type <= 0xFFFFFF) return 3; + return 4; } -void address_write_prefix_bytes(uint32_t address_type, uint8_t *out) -{ - if (address_type > 0xFFFFFF) *(out++) = address_type >> 24; - if (address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF; - if (address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF; - *(out++) = address_type & 0xFF; +void address_write_prefix_bytes(uint32_t address_type, uint8_t *out) { + if (address_type > 0xFFFFFF) *(out++) = address_type >> 24; + if (address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF; + if (address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF; + *(out++) = address_type & 0xFF; } -bool address_check_prefix(const uint8_t *addr, uint32_t address_type) -{ - if (address_type <= 0xFF) { - return address_type == (uint32_t)(addr[0]); - } - if (address_type <= 0xFFFF) { - return address_type == (((uint32_t) addr[0] << 8) | ((uint32_t) addr[1])); - } - if (address_type <= 0xFFFFFF) { - return address_type == (((uint32_t) addr[0] << 16) | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2])); - } - return address_type == (((uint32_t) addr[0] << 24) | ((uint32_t) addr[1] << 16) | ((uint32_t) addr[2] << 8) | ((uint32_t) addr[3])); +bool address_check_prefix(const uint8_t *addr, uint32_t address_type) { + if (address_type <= 0xFF) { + return address_type == (uint32_t)(addr[0]); + } + if (address_type <= 0xFFFF) { + return address_type == (((uint32_t)addr[0] << 8) | ((uint32_t)addr[1])); + } + if (address_type <= 0xFFFFFF) { + return address_type == (((uint32_t)addr[0] << 16) | + ((uint32_t)addr[1] << 8) | ((uint32_t)addr[2])); + } + return address_type == + (((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | + ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3])); } #if USE_ETHEREUM #include "sha3.h" -void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id) -{ - const char *hex = "0123456789abcdef"; - for (int i = 0; i < 20; i++) { - address[i * 2] = hex[(addr[i] >> 4) & 0xF]; - address[i * 2 + 1] = hex[addr[i] & 0xF]; - } - address[40] = 0; +void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, + uint32_t chain_id) { + const char *hex = "0123456789abcdef"; + for (int i = 0; i < 20; i++) { + address[i * 2] = hex[(addr[i] >> 4) & 0xF]; + address[i * 2 + 1] = hex[addr[i] & 0xF]; + } + address[40] = 0; - SHA3_CTX ctx; - uint8_t hash[32]; - keccak_256_Init(&ctx); - if (rskip60) { - char prefix[16]; - int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, prefix, sizeof(prefix)); - keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size); - } - keccak_Update(&ctx, (const uint8_t *)address, 40); - keccak_Final(&ctx, hash); + SHA3_CTX ctx; + uint8_t hash[32]; + keccak_256_Init(&ctx); + if (rskip60) { + char prefix[16]; + int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, + prefix, sizeof(prefix)); + keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size); + } + keccak_Update(&ctx, (const uint8_t *)address, 40); + keccak_Final(&ctx, hash); - for (int i = 0; i < 20; i++) { - if (hash[i] & 0x80 && address[i * 2 ] >= 'a' && address[i * 2 ] <= 'f') { - address[i * 2] -= 0x20; - } - if (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' && address[i * 2 + 1] <= 'f') { - address[i * 2 + 1] -= 0x20; - } - } + for (int i = 0; i < 20; i++) { + if (hash[i] & 0x80 && address[i * 2] >= 'a' && address[i * 2] <= 'f') { + address[i * 2] -= 0x20; + } + if (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' && + address[i * 2 + 1] <= 'f') { + address[i * 2 + 1] -= 0x20; + } + } } #endif diff --git a/address.h b/address.h index 7c5925e06..8147f2c35 100644 --- a/address.h +++ b/address.h @@ -24,16 +24,17 @@ #ifndef __ADDRESS_H__ #define __ADDRESS_H__ -#include #include #include +#include #include "options.h" size_t address_prefix_bytes_len(uint32_t address_type); void address_write_prefix_bytes(uint32_t address_type, uint8_t *out); bool address_check_prefix(const uint8_t *addr, uint32_t address_type); #if USE_ETHEREUM -void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id); +void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, + uint32_t chain_id); #endif #endif diff --git a/base32.c b/base32.c index 06760ccae..b2dccad8a 100644 --- a/base32.c +++ b/base32.c @@ -27,207 +27,214 @@ const char *BASE32_ALPHABET_RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789"; static inline void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out); -static inline bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet); -static inline void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out); +static inline bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, + const char *alphabet); +static inline void base32_8to5_raw(const uint8_t *in, uint8_t length, + uint8_t *out); -static inline int base32_encode_character(uint8_t decoded, const char *alphabet); +static inline int base32_encode_character(uint8_t decoded, + const char *alphabet); static inline int base32_decode_character(char encoded, const char *alphabet); -char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet) { - size_t length = base32_encoded_length(inlen); - if (outlen <= length) { - return NULL; - } +char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, + const char *alphabet) { + size_t length = base32_encoded_length(inlen); + if (outlen <= length) { + return NULL; + } - base32_encode_unsafe(in, inlen, (uint8_t *) out); + base32_encode_unsafe(in, inlen, (uint8_t *)out); - for (size_t i = 0; i < length; i++) { - int ret = base32_encode_character(out[i], alphabet); + for (size_t i = 0; i < length; i++) { + int ret = base32_encode_character(out[i], alphabet); - if (ret == -1) { - return false; - } else { - out[i] = ret; - } - } + if (ret == -1) { + return false; + } else { + out[i] = ret; + } + } - out[length] = '\0'; - return &out[length]; + out[length] = '\0'; + return &out[length]; } -uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet) { - size_t length = base32_decoded_length(inlen); - if (outlen < length) { - return NULL; - } +uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, + size_t outlen, const char *alphabet) { + size_t length = base32_decoded_length(inlen); + if (outlen < length) { + return NULL; + } - if (!base32_decode_unsafe((uint8_t *) in, inlen, (uint8_t *) out, alphabet)) { - return NULL; - } + if (!base32_decode_unsafe((uint8_t *)in, inlen, (uint8_t *)out, alphabet)) { + return NULL; + } - return &out[length]; + return &out[length]; } void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out) { - uint8_t remainder = inlen % 5; - size_t limit = inlen - remainder; + uint8_t remainder = inlen % 5; + size_t limit = inlen - remainder; - size_t i, j; - for (i = 0, j = 0; i < limit; i += 5, j += 8) { - base32_5to8(&in[i], 5, &out[j]); - } + size_t i, j; + for (i = 0, j = 0; i < limit; i += 5, j += 8) { + base32_5to8(&in[i], 5, &out[j]); + } - if (remainder) base32_5to8(&in[i], remainder, &out[j]); + if (remainder) base32_5to8(&in[i], remainder, &out[j]); } -bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet) { - uint8_t remainder = inlen % 8; - size_t limit = inlen - remainder; +bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, + const char *alphabet) { + uint8_t remainder = inlen % 8; + size_t limit = inlen - remainder; - size_t i, j; - for (i = 0, j = 0; i < limit; i += 8, j += 5) { - if (!base32_8to5(&in[i], 8, &out[j], alphabet)) { - return false; - } - } + size_t i, j; + for (i = 0, j = 0; i < limit; i += 8, j += 5) { + if (!base32_8to5(&in[i], 8, &out[j], alphabet)) { + return false; + } + } - if (remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) { - return false; - } + if (remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) { + return false; + } - return true; + return true; } size_t base32_encoded_length(size_t inlen) { - uint8_t remainder = inlen % 5; + uint8_t remainder = inlen % 5; - return (inlen / 5) * 8 + (remainder * 8 + 4) / 5; + return (inlen / 5) * 8 + (remainder * 8 + 4) / 5; } size_t base32_decoded_length(size_t inlen) { - uint8_t remainder = inlen % 8; + uint8_t remainder = inlen % 8; - return (inlen / 8) * 5 + (remainder * 5) / 8; + return (inlen / 8) * 5 + (remainder * 5) / 8; } void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out) { - if (length >= 1) { - out[0] = (in[0] >> 3); - out[1] = (in[0] & 7) << 2; - } - - if (length >= 2) { - out[1] |= (in[1] >> 6); - out[2] = (in[1] >> 1) & 31; - out[3] = (in[1] & 1) << 4; - } - - if (length >= 3) { - out[3] |= (in[2] >> 4); - out[4] = (in[2] & 15) << 1; - } - - if (length >= 4) { - out[4] |= (in[3] >> 7); - out[5] = (in[3] >> 2) & 31; - out[6] = (in[3] & 3) << 3; - } - - if (length >= 5) { - out[6] |= (in[4] >> 5); - out[7] = (in[4] & 31); - } + if (length >= 1) { + out[0] = (in[0] >> 3); + out[1] = (in[0] & 7) << 2; + } + + if (length >= 2) { + out[1] |= (in[1] >> 6); + out[2] = (in[1] >> 1) & 31; + out[3] = (in[1] & 1) << 4; + } + + if (length >= 3) { + out[3] |= (in[2] >> 4); + out[4] = (in[2] & 15) << 1; + } + + if (length >= 4) { + out[4] |= (in[3] >> 7); + out[5] = (in[3] >> 2) & 31; + out[6] = (in[3] & 3) << 3; + } + + if (length >= 5) { + out[6] |= (in[4] >> 5); + out[7] = (in[4] & 31); + } } -bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet) { - if (length == 1 || length == 3 || length == 6 || length > 8) { - return false; - } +bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, + const char *alphabet) { + if (length == 1 || length == 3 || length == 6 || length > 8) { + return false; + } - if (alphabet) { - uint8_t decoded[length]; + if (alphabet) { + uint8_t decoded[length]; - for (size_t i = 0; i < length; i++) { - int ret = base32_decode_character(in[i], alphabet); + for (size_t i = 0; i < length; i++) { + int ret = base32_decode_character(in[i], alphabet); - if (ret == -1) { - return false; - } else { - decoded[i] = ret; - } - } + if (ret == -1) { + return false; + } else { + decoded[i] = ret; + } + } - base32_8to5_raw(decoded, length, out); - } else { - base32_8to5_raw(in, length, out); - } + base32_8to5_raw(decoded, length, out); + } else { + base32_8to5_raw(in, length, out); + } - return true; + return true; } void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out) { - if (length >= 2) { - out[0] = (in[0] << 3); - out[0] |= (in[1] >> 2); - } - - if (length >= 4) { - out[1] = (in[1] & 3) << 6; - out[1] |= (in[2] << 1); - out[1] |= (in[3] >> 4); - } - - if (length >= 5) { - out[2] = (in[3] & 15) << 4; - out[2] |= (in[4] >> 1); - } - - if (length >= 7) { - out[3] = (in[4] & 1) << 7; - out[3] |= (in[5] << 2); - out[3] |= (in[6] >> 3); - } - - if (length >= 8) { - out[4] = (in[6] & 7) << 5; - out[4] |= (in[7] & 31); - } + if (length >= 2) { + out[0] = (in[0] << 3); + out[0] |= (in[1] >> 2); + } + + if (length >= 4) { + out[1] = (in[1] & 3) << 6; + out[1] |= (in[2] << 1); + out[1] |= (in[3] >> 4); + } + + if (length >= 5) { + out[2] = (in[3] & 15) << 4; + out[2] |= (in[4] >> 1); + } + + if (length >= 7) { + out[3] = (in[4] & 1) << 7; + out[3] |= (in[5] << 2); + out[3] |= (in[6] >> 3); + } + + if (length >= 8) { + out[4] = (in[6] & 7) << 5; + out[4] |= (in[7] & 31); + } } int base32_encode_character(uint8_t decoded, const char *alphabet) { - if (decoded >> 5) { - return -1; - } - - if (alphabet == BASE32_ALPHABET_RFC4648) { - if (decoded < 26) { - return 'A' + decoded; - } else { - return '2' - 26 + decoded; - } - } - - return alphabet[decoded]; + if (decoded >> 5) { + return -1; + } + + if (alphabet == BASE32_ALPHABET_RFC4648) { + if (decoded < 26) { + return 'A' + decoded; + } else { + return '2' - 26 + decoded; + } + } + + return alphabet[decoded]; } int base32_decode_character(char encoded, const char *alphabet) { - if (alphabet == BASE32_ALPHABET_RFC4648) { - if (encoded >= 'A' && encoded <= 'Z') { - return encoded - 'A'; - } else if (encoded >= 'a' && encoded <= 'z') { - return encoded - 'a'; - } else if (encoded >= '2' && encoded <= '7') { - return encoded - '2' + 26; - } else { - return -1; - } - } - - const char *occurrence = strchr(alphabet, encoded); - - if (occurrence) { - return occurrence - alphabet; - } else { - return -1; - } + if (alphabet == BASE32_ALPHABET_RFC4648) { + if (encoded >= 'A' && encoded <= 'Z') { + return encoded - 'A'; + } else if (encoded >= 'a' && encoded <= 'z') { + return encoded - 'a'; + } else if (encoded >= '2' && encoded <= '7') { + return encoded - '2' + 26; + } else { + return -1; + } + } + + const char *occurrence = strchr(alphabet, encoded); + + if (occurrence) { + return occurrence - alphabet; + } else { + return -1; + } } diff --git a/base32.h b/base32.h index 250997967..8b5cc8513 100644 --- a/base32.h +++ b/base32.h @@ -29,11 +29,14 @@ extern const char *BASE32_ALPHABET_RFC4648; -char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet); +char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, + const char *alphabet); void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out); -uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet); -bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet); +uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, + size_t outlen, const char *alphabet); +bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, + const char *alphabet); size_t base32_encoded_length(size_t inlen); size_t base32_decoded_length(size_t inlen); diff --git a/base58.c b/base58.c index cd74617b8..d3a1ddb7e 100644 --- a/base58.c +++ b/base58.c @@ -21,265 +21,248 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include "base58.h" #include +#include #include -#include "base58.h" -#include "sha2.h" -#include "ripemd160.h" #include "memzero.h" +#include "ripemd160.h" +#include "sha2.h" -const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +const char b58digits_ordered[] = + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; const int8_t b58digits_map[] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, - -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1, - 22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1, - -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46, - 47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, + 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, + 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, }; -bool b58tobin(void *bin, size_t *binszp, const char *b58) -{ - size_t binsz = *binszp; +bool b58tobin(void *bin, size_t *binszp, const char *b58) { + size_t binsz = *binszp; - if (binsz == 0) { - return false; - } + if (binsz == 0) { + return false; + } - const unsigned char *b58u = (const unsigned char*)b58; - unsigned char *binu = bin; - size_t outisz = (binsz + 3) / 4; - uint32_t outi[outisz]; - uint64_t t; - uint32_t c; - size_t i, j; - uint8_t bytesleft = binsz % 4; - uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; - unsigned zerocount = 0; - size_t b58sz; + const unsigned char *b58u = (const unsigned char *)b58; + unsigned char *binu = bin; + size_t outisz = (binsz + 3) / 4; + uint32_t outi[outisz]; + uint64_t t; + uint32_t c; + size_t i, j; + uint8_t bytesleft = binsz % 4; + uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; + unsigned zerocount = 0; + size_t b58sz; - b58sz = strlen(b58); + b58sz = strlen(b58); - memzero(outi, sizeof(outi)); + memzero(outi, sizeof(outi)); - // Leading zeros, just count - for (i = 0; i < b58sz && b58u[i] == '1'; ++i) - ++zerocount; + // Leading zeros, just count + for (i = 0; i < b58sz && b58u[i] == '1'; ++i) ++zerocount; - for ( ; i < b58sz; ++i) - { - if (b58u[i] & 0x80) - // High-bit set on invalid digit - return false; - if (b58digits_map[b58u[i]] == -1) - // Invalid base58 digit - return false; - c = (unsigned)b58digits_map[b58u[i]]; - for (j = outisz; j--; ) - { - t = ((uint64_t)outi[j]) * 58 + c; - c = (t & 0x3f00000000) >> 32; - outi[j] = t & 0xffffffff; - } - if (c) - // Output number too big (carry to the next int32) - return false; - if (outi[0] & zeromask) - // Output number too big (last int32 filled too far) - return false; - } + for (; i < b58sz; ++i) { + if (b58u[i] & 0x80) + // High-bit set on invalid digit + return false; + if (b58digits_map[b58u[i]] == -1) + // Invalid base58 digit + return false; + c = (unsigned)b58digits_map[b58u[i]]; + for (j = outisz; j--;) { + t = ((uint64_t)outi[j]) * 58 + c; + c = (t & 0x3f00000000) >> 32; + outi[j] = t & 0xffffffff; + } + if (c) + // Output number too big (carry to the next int32) + return false; + if (outi[0] & zeromask) + // Output number too big (last int32 filled too far) + return false; + } - j = 0; - switch (bytesleft) { - case 3: - *(binu++) = (outi[0] & 0xff0000) >> 16; - //-fallthrough - case 2: - *(binu++) = (outi[0] & 0xff00) >> 8; - //-fallthrough - case 1: - *(binu++) = (outi[0] & 0xff); - ++j; - //-fallthrough - default: - break; - } + j = 0; + switch (bytesleft) { + case 3: + *(binu++) = (outi[0] & 0xff0000) >> 16; + //-fallthrough + case 2: + *(binu++) = (outi[0] & 0xff00) >> 8; + //-fallthrough + case 1: + *(binu++) = (outi[0] & 0xff); + ++j; + //-fallthrough + default: + break; + } - for (; j < outisz; ++j) - { - *(binu++) = (outi[j] >> 0x18) & 0xff; - *(binu++) = (outi[j] >> 0x10) & 0xff; - *(binu++) = (outi[j] >> 8) & 0xff; - *(binu++) = (outi[j] >> 0) & 0xff; - } + for (; j < outisz; ++j) { + *(binu++) = (outi[j] >> 0x18) & 0xff; + *(binu++) = (outi[j] >> 0x10) & 0xff; + *(binu++) = (outi[j] >> 8) & 0xff; + *(binu++) = (outi[j] >> 0) & 0xff; + } - // Count canonical base58 byte count - binu = bin; - for (i = 0; i < binsz; ++i) - { - if (binu[i]) { - if (zerocount > i) { - /* result too large */ - return false; - } - break; - } - --*binszp; - } - *binszp += zerocount; + // Count canonical base58 byte count + binu = bin; + for (i = 0; i < binsz; ++i) { + if (binu[i]) { + if (zerocount > i) { + /* result too large */ + return false; + } + break; + } + --*binszp; + } + *binszp += zerocount; - return true; + return true; } -int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str) -{ - unsigned char buf[32]; - const uint8_t *binc = bin; - unsigned i; - if (binsz < 4) - return -4; - hasher_Raw(hasher_type, bin, binsz - 4, buf); - if (memcmp(&binc[binsz - 4], buf, 4)) - return -1; +int b58check(const void *bin, size_t binsz, HasherType hasher_type, + const char *base58str) { + unsigned char buf[32]; + const uint8_t *binc = bin; + unsigned i; + if (binsz < 4) return -4; + hasher_Raw(hasher_type, bin, binsz - 4, buf); + if (memcmp(&binc[binsz - 4], buf, 4)) return -1; - // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) - for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) - {} // Just finding the end of zeros, nothing to do in loop - if (binc[i] == '\0' || base58str[i] == '1') - return -3; + // Check number of zeros is correct AFTER verifying checksum (to avoid + // possibility of accessing base58str beyond the end) + for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) { + } // Just finding the end of zeros, nothing to do in loop + if (binc[i] == '\0' || base58str[i] == '1') return -3; - return binc[0]; + return binc[0]; } -bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) -{ - const uint8_t *bin = data; - int carry; - ssize_t i, j, high, zcount = 0; - size_t size; +bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) { + const uint8_t *bin = data; + int carry; + ssize_t i, j, high, zcount = 0; + size_t size; - while (zcount < (ssize_t)binsz && !bin[zcount]) - ++zcount; + while (zcount < (ssize_t)binsz && !bin[zcount]) ++zcount; - size = (binsz - zcount) * 138 / 100 + 1; - uint8_t buf[size]; - memzero(buf, size); + size = (binsz - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memzero(buf, size); - for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) - { - for (carry = bin[i], j = size - 1; (j > high) || carry; --j) - { - carry += 256 * buf[j]; - buf[j] = carry % 58; - carry /= 58; - } - } + for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) { + for (carry = bin[i], j = size - 1; (j > high) || carry; --j) { + carry += 256 * buf[j]; + buf[j] = carry % 58; + carry /= 58; + } + } - for (j = 0; j < (ssize_t)size && !buf[j]; ++j); + for (j = 0; j < (ssize_t)size && !buf[j]; ++j) + ; - if (*b58sz <= zcount + size - j) - { - *b58sz = zcount + size - j + 1; - return false; - } + if (*b58sz <= zcount + size - j) { + *b58sz = zcount + size - j + 1; + return false; + } - if (zcount) - memset(b58, '1', zcount); - for (i = zcount; j < (ssize_t)size; ++i, ++j) - b58[i] = b58digits_ordered[buf[j]]; - b58[i] = '\0'; - *b58sz = i + 1; + if (zcount) memset(b58, '1', zcount); + for (i = zcount; j < (ssize_t)size; ++i, ++j) + b58[i] = b58digits_ordered[buf[j]]; + b58[i] = '\0'; + *b58sz = i + 1; - return true; + return true; } -int base58_encode_check(const uint8_t *data, int datalen, HasherType hasher_type, char *str, int strsize) -{ - if (datalen > 128) { - return 0; - } - uint8_t buf[datalen + 32]; - uint8_t *hash = buf + datalen; - memcpy(buf, data, datalen); - hasher_Raw(hasher_type, data, datalen, hash); - size_t res = strsize; - bool success = b58enc(str, &res, buf, datalen + 4); - memzero(buf, sizeof(buf)); - return success ? res : 0; +int base58_encode_check(const uint8_t *data, int datalen, + HasherType hasher_type, char *str, int strsize) { + if (datalen > 128) { + return 0; + } + uint8_t buf[datalen + 32]; + uint8_t *hash = buf + datalen; + memcpy(buf, data, datalen); + hasher_Raw(hasher_type, data, datalen, hash); + size_t res = strsize; + bool success = b58enc(str, &res, buf, datalen + 4); + memzero(buf, sizeof(buf)); + return success ? res : 0; } -int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen) -{ - if (datalen > 128) { - return 0; - } - uint8_t d[datalen + 4]; - size_t res = datalen + 4; - if (b58tobin(d, &res, str) != true) { - return 0; - } - uint8_t *nd = d + datalen + 4 - res; - if (b58check(nd, res, hasher_type, str) < 0) { - return 0; - } - memcpy(data, nd, res - 4); - return res - 4; +int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, + int datalen) { + if (datalen > 128) { + return 0; + } + uint8_t d[datalen + 4]; + size_t res = datalen + 4; + if (b58tobin(d, &res, str) != true) { + return 0; + } + uint8_t *nd = d + datalen + 4 - res; + if (b58check(nd, res, hasher_type, str) < 0) { + return 0; + } + memcpy(data, nd, res - 4); + return res - 4; } #if USE_GRAPHENE -int b58gphcheck(const void *bin, size_t binsz, const char *base58str) -{ - unsigned char buf[32]; - const uint8_t *binc = bin; - unsigned i; - if (binsz < 4) - return -4; - ripemd160(bin, binsz - 4, buf); // No double SHA256, but a single RIPEMD160 - if (memcmp(&binc[binsz - 4], buf, 4)) - return -1; +int b58gphcheck(const void *bin, size_t binsz, const char *base58str) { + unsigned char buf[32]; + const uint8_t *binc = bin; + unsigned i; + if (binsz < 4) return -4; + ripemd160(bin, binsz - 4, buf); // No double SHA256, but a single RIPEMD160 + if (memcmp(&binc[binsz - 4], buf, 4)) return -1; - // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) - for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) - {} // Just finding the end of zeros, nothing to do in loop - if (binc[i] == '\0' || base58str[i] == '1') - return -3; + // Check number of zeros is correct AFTER verifying checksum (to avoid + // possibility of accessing base58str beyond the end) + for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) { + } // Just finding the end of zeros, nothing to do in loop + if (binc[i] == '\0' || base58str[i] == '1') return -3; - return binc[0]; + return binc[0]; } -int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize) -{ - if (datalen > 128) { - return 0; - } - uint8_t buf[datalen + 32]; - uint8_t *hash = buf + datalen; - memcpy(buf, data, datalen); - ripemd160(data, datalen, hash); // No double SHA256, but a single RIPEMD160 - size_t res = strsize; - bool success = b58enc(str, &res, buf, datalen + 4); - memzero(buf, sizeof(buf)); - return success ? res : 0; +int base58gph_encode_check(const uint8_t *data, int datalen, char *str, + int strsize) { + if (datalen > 128) { + return 0; + } + uint8_t buf[datalen + 32]; + uint8_t *hash = buf + datalen; + memcpy(buf, data, datalen); + ripemd160(data, datalen, hash); // No double SHA256, but a single RIPEMD160 + size_t res = strsize; + bool success = b58enc(str, &res, buf, datalen + 4); + memzero(buf, sizeof(buf)); + return success ? res : 0; } -int base58gph_decode_check(const char *str, uint8_t *data, int datalen) -{ - if (datalen > 128) { - return 0; - } - uint8_t d[datalen + 4]; - size_t res = datalen + 4; - if (b58tobin(d, &res, str) != true) { - return 0; - } - uint8_t *nd = d + datalen + 4 - res; - if (b58gphcheck(nd, res, str) < 0) { - return 0; - } - memcpy(data, nd, res - 4); - return res - 4; +int base58gph_decode_check(const char *str, uint8_t *data, int datalen) { + if (datalen > 128) { + return 0; + } + uint8_t d[datalen + 4]; + size_t res = datalen + 4; + if (b58tobin(d, &res, str) != true) { + return 0; + } + uint8_t *nd = d + datalen + 4 - res; + if (b58gphcheck(nd, res, str) < 0) { + return 0; + } + memcpy(data, nd, res - 4); + return res - 4; } #endif diff --git a/base58.h b/base58.h index 0fa9167bf..97cb54e60 100644 --- a/base58.h +++ b/base58.h @@ -24,24 +24,28 @@ #ifndef __BASE58_H__ #define __BASE58_H__ -#include #include +#include #include "hasher.h" #include "options.h" extern const char b58digits_ordered[]; extern const int8_t b58digits_map[]; -int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize); -int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen); +int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, + char *str, int strsize); +int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, + int datalen); // Private bool b58tobin(void *bin, size_t *binszp, const char *b58); -int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str); +int b58check(const void *bin, size_t binsz, HasherType hasher_type, + const char *base58str); bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz); #if USE_GRAPHENE -int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize); +int base58gph_encode_check(const uint8_t *data, int datalen, char *str, + int strsize); int base58gph_decode_check(const char *str, uint8_t *data, int datalen); int b58gphcheck(const void *bin, size_t binsz, const char *base58str); #endif diff --git a/bignum.c b/bignum.c index 30e711d02..11f3dba52 100644 --- a/bignum.c +++ b/bignum.c @@ -23,10 +23,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "bignum.h" +#include #include #include -#include -#include "bignum.h" #include "memzero.h" /* big number library */ @@ -54,298 +54,272 @@ * 2^256 and it must be a prime number. */ -inline uint32_t read_be(const uint8_t *data) -{ - return (((uint32_t)data[0]) << 24) | - (((uint32_t)data[1]) << 16) | - (((uint32_t)data[2]) << 8) | - (((uint32_t)data[3])); +inline uint32_t read_be(const uint8_t *data) { + return (((uint32_t)data[0]) << 24) | (((uint32_t)data[1]) << 16) | + (((uint32_t)data[2]) << 8) | (((uint32_t)data[3])); } -inline void write_be(uint8_t *data, uint32_t x) -{ - data[0] = x >> 24; - data[1] = x >> 16; - data[2] = x >> 8; - data[3] = x; +inline void write_be(uint8_t *data, uint32_t x) { + data[0] = x >> 24; + data[1] = x >> 16; + data[2] = x >> 8; + data[3] = x; } -inline uint32_t read_le(const uint8_t *data) -{ - return (((uint32_t)data[3]) << 24) | - (((uint32_t)data[2]) << 16) | - (((uint32_t)data[1]) << 8) | - (((uint32_t)data[0])); +inline uint32_t read_le(const uint8_t *data) { + return (((uint32_t)data[3]) << 24) | (((uint32_t)data[2]) << 16) | + (((uint32_t)data[1]) << 8) | (((uint32_t)data[0])); } -inline void write_le(uint8_t *data, uint32_t x) -{ - data[3] = x >> 24; - data[2] = x >> 16; - data[1] = x >> 8; - data[0] = x; +inline void write_le(uint8_t *data, uint32_t x) { + data[3] = x >> 24; + data[2] = x >> 16; + data[1] = x >> 8; + data[0] = x; } // convert a raw bigendian 256 bit value into a normalized bignum. // out_number is partly reduced (since it fits in 256 bit). -void bn_read_be(const uint8_t *in_number, bignum256 *out_number) -{ - int i; - uint32_t temp = 0; - for (i = 0; i < 8; i++) { - // invariant: temp = (in_number % 2^(32i)) >> 30i - // get next limb = (in_number % 2^(32(i+1))) >> 32i - uint32_t limb = read_be(in_number + (7 - i) * 4); - // temp = (in_number % 2^(32(i+1))) << 30i - temp |= limb << (2*i); - // store 30 bits into val[i] - out_number->val[i]= temp & 0x3FFFFFFF; - // prepare temp for next round - temp = limb >> (30 - 2*i); - } - out_number->val[8] = temp; +void bn_read_be(const uint8_t *in_number, bignum256 *out_number) { + int i; + uint32_t temp = 0; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number % 2^(32i)) >> 30i + // get next limb = (in_number % 2^(32(i+1))) >> 32i + uint32_t limb = read_be(in_number + (7 - i) * 4); + // temp = (in_number % 2^(32(i+1))) << 30i + temp |= limb << (2 * i); + // store 30 bits into val[i] + out_number->val[i] = temp & 0x3FFFFFFF; + // prepare temp for next round + temp = limb >> (30 - 2 * i); + } + out_number->val[8] = temp; } // convert a normalized bignum to a raw bigendian 256 bit number. // in_number must be fully reduced. -void bn_write_be(const bignum256 *in_number, uint8_t *out_number) -{ - int i; - uint32_t temp = in_number->val[8]; - for (i = 0; i < 8; i++) { - // invariant: temp = (in_number >> 30*(8-i)) - uint32_t limb = in_number->val[7 - i]; - temp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i)); - write_be(out_number + i * 4, temp); - temp = limb; - } +void bn_write_be(const bignum256 *in_number, uint8_t *out_number) { + int i; + uint32_t temp = in_number->val[8]; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number >> 30*(8-i)) + uint32_t limb = in_number->val[7 - i]; + temp = (temp << (16 + 2 * i)) | (limb >> (14 - 2 * i)); + write_be(out_number + i * 4, temp); + temp = limb; + } } // convert a raw little endian 256 bit value into a normalized bignum. // out_number is partly reduced (since it fits in 256 bit). -void bn_read_le(const uint8_t *in_number, bignum256 *out_number) -{ - int i; - uint32_t temp = 0; - for (i = 0; i < 8; i++) { - // invariant: temp = (in_number % 2^(32i)) >> 30i - // get next limb = (in_number % 2^(32(i+1))) >> 32i - uint32_t limb = read_le(in_number + i * 4); - // temp = (in_number % 2^(32(i+1))) << 30i - temp |= limb << (2*i); - // store 30 bits into val[i] - out_number->val[i]= temp & 0x3FFFFFFF; - // prepare temp for next round - temp = limb >> (30 - 2*i); - } - out_number->val[8] = temp; +void bn_read_le(const uint8_t *in_number, bignum256 *out_number) { + int i; + uint32_t temp = 0; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number % 2^(32i)) >> 30i + // get next limb = (in_number % 2^(32(i+1))) >> 32i + uint32_t limb = read_le(in_number + i * 4); + // temp = (in_number % 2^(32(i+1))) << 30i + temp |= limb << (2 * i); + // store 30 bits into val[i] + out_number->val[i] = temp & 0x3FFFFFFF; + // prepare temp for next round + temp = limb >> (30 - 2 * i); + } + out_number->val[8] = temp; } // convert a normalized bignum to a raw little endian 256 bit number. // in_number must be fully reduced. -void bn_write_le(const bignum256 *in_number, uint8_t *out_number) -{ - int i; - uint32_t temp = in_number->val[8]; - for (i = 0; i < 8; i++) { - // invariant: temp = (in_number >> 30*(8-i)) - uint32_t limb = in_number->val[7 - i]; - temp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i)); - write_le(out_number + (7 - i) * 4, temp); - temp = limb; - } +void bn_write_le(const bignum256 *in_number, uint8_t *out_number) { + int i; + uint32_t temp = in_number->val[8]; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number >> 30*(8-i)) + uint32_t limb = in_number->val[7 - i]; + temp = (temp << (16 + 2 * i)) | (limb >> (14 - 2 * i)); + write_le(out_number + (7 - i) * 4, temp); + temp = limb; + } } -void bn_read_uint32(uint32_t in_number, bignum256 *out_number) -{ - out_number->val[0] = in_number & 0x3FFFFFFF; - out_number->val[1] = in_number >> 30; - out_number->val[2] = 0; - out_number->val[3] = 0; - out_number->val[4] = 0; - out_number->val[5] = 0; - out_number->val[6] = 0; - out_number->val[7] = 0; - out_number->val[8] = 0; +void bn_read_uint32(uint32_t in_number, bignum256 *out_number) { + out_number->val[0] = in_number & 0x3FFFFFFF; + out_number->val[1] = in_number >> 30; + out_number->val[2] = 0; + out_number->val[3] = 0; + out_number->val[4] = 0; + out_number->val[5] = 0; + out_number->val[6] = 0; + out_number->val[7] = 0; + out_number->val[8] = 0; } -void bn_read_uint64(uint64_t in_number, bignum256 *out_number) -{ - out_number->val[0] = in_number & 0x3FFFFFFF; - out_number->val[1] = (in_number >>= 30) & 0x3FFFFFFF; - out_number->val[2] = in_number >>= 30; - out_number->val[3] = 0; - out_number->val[4] = 0; - out_number->val[5] = 0; - out_number->val[6] = 0; - out_number->val[7] = 0; - out_number->val[8] = 0; +void bn_read_uint64(uint64_t in_number, bignum256 *out_number) { + out_number->val[0] = in_number & 0x3FFFFFFF; + out_number->val[1] = (in_number >>= 30) & 0x3FFFFFFF; + out_number->val[2] = in_number >>= 30; + out_number->val[3] = 0; + out_number->val[4] = 0; + out_number->val[5] = 0; + out_number->val[6] = 0; + out_number->val[7] = 0; + out_number->val[8] = 0; } // a must be normalized -int bn_bitcount(const bignum256 *a) -{ - int i; - for (i = 8; i >= 0; i--) { - int tmp = a->val[i]; - if (tmp != 0) { - return i * 30 + (32 - __builtin_clz(tmp)); - } - } - return 0; +int bn_bitcount(const bignum256 *a) { + int i; + for (i = 8; i >= 0; i--) { + int tmp = a->val[i]; + if (tmp != 0) { + return i * 30 + (32 - __builtin_clz(tmp)); + } + } + return 0; } -#define DIGITS 78 // log10(2 ^ 256) +#define DIGITS 78 // log10(2 ^ 256) -unsigned int bn_digitcount(const bignum256 *a) -{ - bignum256 val; - memcpy(&val, a, sizeof(bignum256)); +unsigned int bn_digitcount(const bignum256 *a) { + bignum256 val; + memcpy(&val, a, sizeof(bignum256)); - unsigned int digits = 1; + unsigned int digits = 1; - for (unsigned int i = 0; i < DIGITS; i += 3) { - uint32_t limb; - bn_divmod1000(&val, &limb); + for (unsigned int i = 0; i < DIGITS; i += 3) { + uint32_t limb; + bn_divmod1000(&val, &limb); - if (limb >= 100) { - digits = i + 3; - } else if (limb >= 10) { - digits = i + 2; - } else if (limb >= 1) { - digits = i + 1; - } - } + if (limb >= 100) { + digits = i + 3; + } else if (limb >= 10) { + digits = i + 2; + } else if (limb >= 1) { + digits = i + 1; + } + } - return digits; + return digits; } // sets a bignum to zero. -void bn_zero(bignum256 *a) -{ - int i; - for (i = 0; i < 9; i++) { - a->val[i] = 0; - } +void bn_zero(bignum256 *a) { + int i; + for (i = 0; i < 9; i++) { + a->val[i] = 0; + } } // sets a bignum to one. -void bn_one(bignum256 *a) -{ - a->val[0] = 1; - a->val[1] = 0; - a->val[2] = 0; - a->val[3] = 0; - a->val[4] = 0; - a->val[5] = 0; - a->val[6] = 0; - a->val[7] = 0; - a->val[8] = 0; +void bn_one(bignum256 *a) { + a->val[0] = 1; + a->val[1] = 0; + a->val[2] = 0; + a->val[3] = 0; + a->val[4] = 0; + a->val[5] = 0; + a->val[6] = 0; + a->val[7] = 0; + a->val[8] = 0; } // checks that a bignum is zero. // a must be normalized // function is constant time (on some architectures, in particular ARM). -int bn_is_zero(const bignum256 *a) -{ - int i; - uint32_t result = 0; - for (i = 0; i < 9; i++) { - result |= a->val[i]; - } - return !result; +int bn_is_zero(const bignum256 *a) { + int i; + uint32_t result = 0; + for (i = 0; i < 9; i++) { + result |= a->val[i]; + } + return !result; } // Check whether a < b // a and b must be normalized // function is constant time (on some architectures, in particular ARM). -int bn_is_less(const bignum256 *a, const bignum256 *b) -{ - int i; - uint32_t res1 = 0; - uint32_t res2 = 0; - for (i = 8; i >= 0; i--) { - res1 = (res1 << 1) | (a->val[i] < b->val[i]); - res2 = (res2 << 1) | (a->val[i] > b->val[i]); - } - return res1 > res2; +int bn_is_less(const bignum256 *a, const bignum256 *b) { + int i; + uint32_t res1 = 0; + uint32_t res2 = 0; + for (i = 8; i >= 0; i--) { + res1 = (res1 << 1) | (a->val[i] < b->val[i]); + res2 = (res2 << 1) | (a->val[i] > b->val[i]); + } + return res1 > res2; } // Check whether a == b // a and b must be normalized // function is constant time (on some architectures, in particular ARM). int bn_is_equal(const bignum256 *a, const bignum256 *b) { - int i; - uint32_t result = 0; - for (i = 0; i < 9; i++) { - result |= (a->val[i] ^ b->val[i]); - } - return !result; + int i; + uint32_t result = 0; + for (i = 0; i < 9; i++) { + result |= (a->val[i] ^ b->val[i]); + } + return !result; } // Assigns res = cond ? truecase : falsecase // assumes that cond is either 0 or 1. // function is constant time. -void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase) -{ - int i; - uint32_t tmask = (uint32_t) -cond; - uint32_t fmask = ~tmask; - - assert (cond == 1 || cond == 0); - for (i = 0; i < 9; i++) { - res->val[i] = (truecase->val[i] & tmask) | - (falsecase->val[i] & fmask); - } +void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, + const bignum256 *falsecase) { + int i; + uint32_t tmask = (uint32_t)-cond; + uint32_t fmask = ~tmask; + + assert(cond == 1 || cond == 0); + for (i = 0; i < 9; i++) { + res->val[i] = (truecase->val[i] & tmask) | (falsecase->val[i] & fmask); + } } // shift number to the left, i.e multiply it by 2. // a must be normalized. The result is normalized but not reduced. -void bn_lshift(bignum256 *a) -{ - int i; - for (i = 8; i > 0; i--) { - a->val[i] = ((a->val[i] << 1) & 0x3FFFFFFF) | ((a->val[i - 1] & 0x20000000) >> 29); - } - a->val[0] = (a->val[0] << 1) & 0x3FFFFFFF; +void bn_lshift(bignum256 *a) { + int i; + for (i = 8; i > 0; i--) { + a->val[i] = + ((a->val[i] << 1) & 0x3FFFFFFF) | ((a->val[i - 1] & 0x20000000) >> 29); + } + a->val[0] = (a->val[0] << 1) & 0x3FFFFFFF; } // shift number to the right, i.e divide by 2 while rounding down. // a must be normalized. The result is normalized. -void bn_rshift(bignum256 *a) -{ - int i; - for (i = 0; i < 8; i++) { - a->val[i] = (a->val[i] >> 1) | ((a->val[i + 1] & 1) << 29); - } - a->val[8] >>= 1; +void bn_rshift(bignum256 *a) { + int i; + for (i = 0; i < 8; i++) { + a->val[i] = (a->val[i] >> 1) | ((a->val[i + 1] & 1) << 29); + } + a->val[8] >>= 1; } // sets bit in bignum -void bn_setbit(bignum256 *a, uint8_t bit) -{ - a->val[bit / 30] |= (1u << (bit % 30)); +void bn_setbit(bignum256 *a, uint8_t bit) { + a->val[bit / 30] |= (1u << (bit % 30)); } // clears bit in bignum -void bn_clearbit(bignum256 *a, uint8_t bit) -{ - a->val[bit / 30] &= ~(1u << (bit % 30)); +void bn_clearbit(bignum256 *a, uint8_t bit) { + a->val[bit / 30] &= ~(1u << (bit % 30)); } // tests bit in bignum -uint32_t bn_testbit(bignum256 *a, uint8_t bit) -{ - return a->val[bit / 30] & (1u << (bit % 30)); +uint32_t bn_testbit(bignum256 *a, uint8_t bit) { + return a->val[bit / 30] & (1u << (bit % 30)); } // a = b ^ c -void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c) -{ - int i; - for (i = 0; i < 9; i++) { - a->val[i] = b->val[i] ^ c->val[i]; - } +void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c) { + int i; + for (i = 0; i < 9; i++) { + a->val[i] = b->val[i] ^ c->val[i]; + } } // multiply x by 1/2 modulo prime. @@ -353,74 +327,69 @@ void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c) // assumes x is normalized. // if x was partly reduced, it is also partly reduced on exit. // function is constant time. -void bn_mult_half(bignum256 * x, const bignum256 *prime) -{ - int j; - uint32_t xodd = -(x->val[0] & 1); - // compute x = x/2 mod prime - // if x is odd compute (x+prime)/2 - uint32_t tmp1 = (x->val[0] + (prime->val[0] & xodd)) >> 1; - for (j = 0; j < 8; j++) { - uint32_t tmp2 = (x->val[j+1] + (prime->val[j+1] & xodd)); - tmp1 += (tmp2 & 1) << 29; - x->val[j] = tmp1 & 0x3fffffff; - tmp1 >>= 30; - tmp1 += tmp2 >> 1; - } - x->val[8] = tmp1; +void bn_mult_half(bignum256 *x, const bignum256 *prime) { + int j; + uint32_t xodd = -(x->val[0] & 1); + // compute x = x/2 mod prime + // if x is odd compute (x+prime)/2 + uint32_t tmp1 = (x->val[0] + (prime->val[0] & xodd)) >> 1; + for (j = 0; j < 8; j++) { + uint32_t tmp2 = (x->val[j + 1] + (prime->val[j + 1] & xodd)); + tmp1 += (tmp2 & 1) << 29; + x->val[j] = tmp1 & 0x3fffffff; + tmp1 >>= 30; + tmp1 += tmp2 >> 1; + } + x->val[8] = tmp1; } // multiply x by k modulo prime. // assumes x is normalized, 0 <= k <= 4. // guarantees x is partly reduced. -void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime) -{ - int j; - for (j = 0; j < 9; j++) { - x->val[j] = k * x->val[j]; - } - bn_fast_mod(x, prime); +void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime) { + int j; + for (j = 0; j < 9; j++) { + x->val[j] = k * x->val[j]; + } + bn_fast_mod(x, prime); } // compute x = x mod prime by computing x >= prime ? x - prime : x. // assumes x partly reduced, guarantees x fully reduced. -void bn_mod(bignum256 *x, const bignum256 *prime) -{ - const int flag = bn_is_less(x, prime); // x < prime - bignum256 temp; - bn_subtract(x, prime, &temp); // temp = x - prime - bn_cmov(x, flag, x, &temp); +void bn_mod(bignum256 *x, const bignum256 *prime) { + const int flag = bn_is_less(x, prime); // x < prime + bignum256 temp; + bn_subtract(x, prime, &temp); // temp = x - prime + bn_cmov(x, flag, x, &temp); } // auxiliary function for multiplication. // compute k * x as a 540 bit number in base 2^30 (normalized). // assumes that k and x are normalized. -void bn_multiply_long(const bignum256 *k, const bignum256 *x, uint32_t res[18]) -{ - int i, j; - uint64_t temp = 0; - - // compute lower half of long multiplication - for (i = 0; i < 9; i++) - { - for (j = 0; j <= i; j++) { - // no overflow, since 9*2^60 < 2^64 - temp += k->val[j] * (uint64_t)x->val[i - j]; - } - res[i] = temp & 0x3FFFFFFFu; - temp >>= 30; - } - // compute upper half - for (; i < 17; i++) - { - for (j = i - 8; j < 9 ; j++) { - // no overflow, since 9*2^60 < 2^64 - temp += k->val[j] * (uint64_t)x->val[i - j]; - } - res[i] = temp & 0x3FFFFFFFu; - temp >>= 30; - } - res[17] = temp; +void bn_multiply_long(const bignum256 *k, const bignum256 *x, + uint32_t res[18]) { + int i, j; + uint64_t temp = 0; + + // compute lower half of long multiplication + for (i = 0; i < 9; i++) { + for (j = 0; j <= i; j++) { + // no overflow, since 9*2^60 < 2^64 + temp += k->val[j] * (uint64_t)x->val[i - j]; + } + res[i] = temp & 0x3FFFFFFFu; + temp >>= 30; + } + // compute upper half + for (; i < 17; i++) { + for (j = i - 8; j < 9; j++) { + // no overflow, since 9*2^60 < 2^64 + temp += k->val[j] * (uint64_t)x->val[i - j]; + } + res[i] = temp & 0x3FFFFFFFu; + temp >>= 30; + } + res[17] = temp; } // auxiliary function for multiplication. @@ -428,71 +397,72 @@ void bn_multiply_long(const bignum256 *k, const bignum256 *x, uint32_t res[18]) // assumes i >= 8 and i <= 16 // assumes res normalized, res < 2^(30(i-7)) * 2 * prime // guarantees res normalized, res < 2^(30(i-8)) * 2 * prime -void bn_multiply_reduce_step(uint32_t res[18], const bignum256 *prime, uint32_t i) { - // let k = i-8. - // on entry: - // 0 <= res < 2^(30k + 31) * prime - // estimate coef = (res / prime / 2^30k) - // by coef = res / 2^(30k + 256) rounded down - // 0 <= coef < 2^31 - // subtract (coef * 2^(30k) * prime) from res - // note that we unrolled the first iteration - assert(i >= 8 && i <= 16); - uint32_t j; - uint32_t coef = (res[i] >> 16) + (res[i + 1] << 14); - uint64_t temp = 0x2000000000000000ull + res[i - 8] - prime->val[0] * (uint64_t)coef; - assert (coef < 0x80000000u); - res[i - 8] = temp & 0x3FFFFFFF; - for (j = 1; j < 9; j++) { - temp >>= 30; - // Note: coeff * prime->val[j] <= (2^31-1) * (2^30-1) - // Hence, this addition will not underflow. - temp += 0x1FFFFFFF80000000ull + res[i - 8 + j] - prime->val[j] * (uint64_t)coef; - res[i - 8 + j] = temp & 0x3FFFFFFF; - // 0 <= temp < 2^61 + 2^30 - } - temp >>= 30; - temp += 0x1FFFFFFF80000000ull + res[i - 8 + j]; - res[i - 8 + j] = temp & 0x3FFFFFFF; - // we rely on the fact that prime > 2^256 - 2^224 - // res = oldres - coef*2^(30k) * prime; - // and - // coef * 2^(30k + 256) <= oldres < (coef+1) * 2^(30k + 256) - // Hence, 0 <= res < 2^30k (2^256 + coef * (2^256 - prime)) - // < 2^30k (2^256 + 2^31 * 2^224) - // < 2^30k (2 * prime) +void bn_multiply_reduce_step(uint32_t res[18], const bignum256 *prime, + uint32_t i) { + // let k = i-8. + // on entry: + // 0 <= res < 2^(30k + 31) * prime + // estimate coef = (res / prime / 2^30k) + // by coef = res / 2^(30k + 256) rounded down + // 0 <= coef < 2^31 + // subtract (coef * 2^(30k) * prime) from res + // note that we unrolled the first iteration + assert(i >= 8 && i <= 16); + uint32_t j; + uint32_t coef = (res[i] >> 16) + (res[i + 1] << 14); + uint64_t temp = + 0x2000000000000000ull + res[i - 8] - prime->val[0] * (uint64_t)coef; + assert(coef < 0x80000000u); + res[i - 8] = temp & 0x3FFFFFFF; + for (j = 1; j < 9; j++) { + temp >>= 30; + // Note: coeff * prime->val[j] <= (2^31-1) * (2^30-1) + // Hence, this addition will not underflow. + temp += + 0x1FFFFFFF80000000ull + res[i - 8 + j] - prime->val[j] * (uint64_t)coef; + res[i - 8 + j] = temp & 0x3FFFFFFF; + // 0 <= temp < 2^61 + 2^30 + } + temp >>= 30; + temp += 0x1FFFFFFF80000000ull + res[i - 8 + j]; + res[i - 8 + j] = temp & 0x3FFFFFFF; + // we rely on the fact that prime > 2^256 - 2^224 + // res = oldres - coef*2^(30k) * prime; + // and + // coef * 2^(30k + 256) <= oldres < (coef+1) * 2^(30k + 256) + // Hence, 0 <= res < 2^30k (2^256 + coef * (2^256 - prime)) + // < 2^30k (2^256 + 2^31 * 2^224) + // < 2^30k (2 * prime) } - // auxiliary function for multiplication. // reduces x = res modulo prime. // assumes res normalized, res < 2^270 * 2 * prime // guarantees x partly reduced, i.e., x < 2 * prime -void bn_multiply_reduce(bignum256 *x, uint32_t res[18], const bignum256 *prime) -{ - int i; - // res = k * x is a normalized number (every limb < 2^30) - // 0 <= res < 2^270 * 2 * prime. - for (i = 16; i >= 8; i--) { - bn_multiply_reduce_step(res, prime, i); - assert(res[i + 1] == 0); - } - // store the result - for (i = 0; i < 9; i++) { - x->val[i] = res[i]; - } +void bn_multiply_reduce(bignum256 *x, uint32_t res[18], + const bignum256 *prime) { + int i; + // res = k * x is a normalized number (every limb < 2^30) + // 0 <= res < 2^270 * 2 * prime. + for (i = 16; i >= 8; i--) { + bn_multiply_reduce_step(res, prime, i); + assert(res[i + 1] == 0); + } + // store the result + for (i = 0; i < 9; i++) { + x->val[i] = res[i]; + } } // Compute x := k * x (mod prime) // both inputs must be smaller than 180 * prime. // result is partly reduced (0 <= x < 2 * prime) // This only works for primes between 2^256-2^224 and 2^256. -void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime) -{ - uint32_t res[18] = {0}; - bn_multiply_long(k, x, res); - bn_multiply_reduce(x, res, prime); - memzero(res, sizeof(res)); +void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime) { + uint32_t res[18] = {0}; + bn_multiply_long(k, x, res); + bn_multiply_reduce(x, res, prime); + memzero(res, sizeof(res)); } // partly reduce x modulo prime @@ -500,97 +470,95 @@ void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime) // x can be any number that fits. // prime must be between (2^256 - 2^224) and 2^256 // result is partly reduced, smaller than 2*prime -void bn_fast_mod(bignum256 *x, const bignum256 *prime) -{ - int j; - uint32_t coef; - uint64_t temp; - - coef = x->val[8] >> 16; - // substract (coef * prime) from x - // note that we unrolled the first iteration - temp = 0x2000000000000000ull + x->val[0] - prime->val[0] * (uint64_t)coef; - x->val[0] = temp & 0x3FFFFFFF; - for (j = 1; j < 9; j++) { - temp >>= 30; - temp += 0x1FFFFFFF80000000ull + x->val[j] - prime->val[j] * (uint64_t)coef; - x->val[j] = temp & 0x3FFFFFFF; - } +void bn_fast_mod(bignum256 *x, const bignum256 *prime) { + int j; + uint32_t coef; + uint64_t temp; + + coef = x->val[8] >> 16; + // substract (coef * prime) from x + // note that we unrolled the first iteration + temp = 0x2000000000000000ull + x->val[0] - prime->val[0] * (uint64_t)coef; + x->val[0] = temp & 0x3FFFFFFF; + for (j = 1; j < 9; j++) { + temp >>= 30; + temp += 0x1FFFFFFF80000000ull + x->val[j] - prime->val[j] * (uint64_t)coef; + x->val[j] = temp & 0x3FFFFFFF; + } } // square root of x = x^((p+1)/4) // http://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus // assumes x is normalized but not necessarily reduced. // guarantees x is reduced -void bn_sqrt(bignum256 *x, const bignum256 *prime) -{ - // this method compute x^1/2 = x^(prime+1)/4 - uint32_t i, j, limb; - bignum256 res, p; - bn_one(&res); - // compute p = (prime+1)/4 - memcpy(&p, prime, sizeof(bignum256)); - bn_addi(&p, 1); - bn_rshift(&p); - bn_rshift(&p); - for (i = 0; i < 9; i++) { - // invariants: - // x = old(x)^(2^(i*30)) - // res = old(x)^(p % 2^(i*30)) - // get the i-th limb of prime - 2 - limb = p.val[i]; - for (j = 0; j < 30; j++) { - // invariants: - // x = old(x)^(2^(i*30+j)) - // res = old(x)^(p % 2^(i*30+j)) - // limb = (p % 2^(i*30+30)) / 2^(i*30+j) - if (i == 8 && limb == 0) break; - if (limb & 1) { - bn_multiply(x, &res, prime); - } - limb >>= 1; - bn_multiply(x, x, prime); - } - } - bn_mod(&res, prime); - memcpy(x, &res, sizeof(bignum256)); - memzero(&res, sizeof(res)); - memzero(&p, sizeof(p)); +void bn_sqrt(bignum256 *x, const bignum256 *prime) { + // this method compute x^1/2 = x^(prime+1)/4 + uint32_t i, j, limb; + bignum256 res, p; + bn_one(&res); + // compute p = (prime+1)/4 + memcpy(&p, prime, sizeof(bignum256)); + bn_addi(&p, 1); + bn_rshift(&p); + bn_rshift(&p); + for (i = 0; i < 9; i++) { + // invariants: + // x = old(x)^(2^(i*30)) + // res = old(x)^(p % 2^(i*30)) + // get the i-th limb of prime - 2 + limb = p.val[i]; + for (j = 0; j < 30; j++) { + // invariants: + // x = old(x)^(2^(i*30+j)) + // res = old(x)^(p % 2^(i*30+j)) + // limb = (p % 2^(i*30+30)) / 2^(i*30+j) + if (i == 8 && limb == 0) break; + if (limb & 1) { + bn_multiply(x, &res, prime); + } + limb >>= 1; + bn_multiply(x, x, prime); + } + } + bn_mod(&res, prime); + memcpy(x, &res, sizeof(bignum256)); + memzero(&res, sizeof(res)); + memzero(&p, sizeof(p)); } -#if ! USE_INVERSE_FAST +#if !USE_INVERSE_FAST // in field G_prime, small but slow -void bn_inverse(bignum256 *x, const bignum256 *prime) -{ - // this method compute x^-1 = x^(prime-2) - uint32_t i, j, limb; - bignum256 res; - bn_one(&res); - for (i = 0; i < 9; i++) { - // invariants: - // x = old(x)^(2^(i*30)) - // res = old(x)^((prime-2) % 2^(i*30)) - // get the i-th limb of prime - 2 - limb = prime->val[i]; - // this is not enough in general but fine for secp256k1 & nist256p1 because prime->val[0] > 1 - if (i == 0) limb -= 2; - for (j = 0; j < 30; j++) { - // invariants: - // x = old(x)^(2^(i*30+j)) - // res = old(x)^((prime-2) % 2^(i*30+j)) - // limb = ((prime-2) % 2^(i*30+30)) / 2^(i*30+j) - // early abort when only zero bits follow - if (i == 8 && limb == 0) break; - if (limb & 1) { - bn_multiply(x, &res, prime); - } - limb >>= 1; - bn_multiply(x, x, prime); - } - } - bn_mod(&res, prime); - memcpy(x, &res, sizeof(bignum256)); +void bn_inverse(bignum256 *x, const bignum256 *prime) { + // this method compute x^-1 = x^(prime-2) + uint32_t i, j, limb; + bignum256 res; + bn_one(&res); + for (i = 0; i < 9; i++) { + // invariants: + // x = old(x)^(2^(i*30)) + // res = old(x)^((prime-2) % 2^(i*30)) + // get the i-th limb of prime - 2 + limb = prime->val[i]; + // this is not enough in general but fine for secp256k1 & nist256p1 because + // prime->val[0] > 1 + if (i == 0) limb -= 2; + for (j = 0; j < 30; j++) { + // invariants: + // x = old(x)^(2^(i*30+j)) + // res = old(x)^((prime-2) % 2^(i*30+j)) + // limb = ((prime-2) % 2^(i*30+30)) / 2^(i*30+j) + // early abort when only zero bits follow + if (i == 8 && limb == 0) break; + if (limb & 1) { + bn_multiply(x, &res, prime); + } + limb >>= 1; + bn_multiply(x, x, prime); + } + } + bn_mod(&res, prime); + memcpy(x, &res, sizeof(bignum256)); } #else @@ -598,513 +566,503 @@ void bn_inverse(bignum256 *x, const bignum256 *prime) // in field G_prime, big and complicated but fast // the input must not be 0 mod prime. // the result is smaller than prime -void bn_inverse(bignum256 *x, const bignum256 *prime) -{ - int i, j, k, cmp; - struct combo { - uint32_t a[9]; - int len1; - } us, vr, *odd, *even; - uint32_t pp[8]; - uint32_t temp32; - uint64_t temp; - - // The algorithm is based on Schroeppel et. al. "Almost Modular Inverse" - // algorithm. We keep four values u,v,r,s in the combo registers - // us and vr. us stores u in the first len1 limbs (little endian) - // and s in the last 9-len1 limbs (big endian). vr stores v and r. - // This is because both u*s and v*r are guaranteed to fit in 8 limbs, so - // their components are guaranteed to fit in 9. During the algorithm, - // the length of u and v shrinks while r and s grow. - // u,v,r,s correspond to F,G,B,C in Schroeppel's algorithm. - - // reduce x modulo prime. This is necessary as it has to fit in 8 limbs. - bn_fast_mod(x, prime); - bn_mod(x, prime); - // convert x and prime to 8x32 bit limb form - temp32 = prime->val[0]; - for (i = 0; i < 8; i++) { - temp32 |= prime->val[i + 1] << (30-2*i); - us.a[i] = pp[i] = temp32; - temp32 = prime->val[i + 1] >> (2+2*i); - } - temp32 = x->val[0]; - for (i = 0; i < 8; i++) { - temp32 |= x->val[i + 1] << (30-2*i); - vr.a[i] = temp32; - temp32 = x->val[i + 1] >> (2+2*i); - } - us.len1 = 8; - vr.len1 = 8; - // set s = 1 and r = 0 - us.a[8] = 1; - vr.a[8] = 0; - // set k = 0. - k = 0; - - // only one of the numbers u,v can be even at any time. We - // let even point to that number and odd to the other. - // Initially the prime u is guaranteed to be odd. - odd = &us; - even = &vr; - - // u = prime, v = x - // r = 0 , s = 1 - // k = 0 - for (;;) { - // invariants: - // let u = limbs us.a[0..u.len1-1] in little endian, - // let s = limbs us.a[u.len..8] in big endian, - // let v = limbs vr.a[0..u.len1-1] in little endian, - // let r = limbs vr.a[u.len..8] in big endian, - // r,s >= 0 ; u,v >= 1 - // x*-r = u*2^k mod prime - // x*s = v*2^k mod prime - // u*s + v*r = prime - // floor(log2(u)) + floor(log2(v)) + k <= 510 - // max(u,v) <= 2^k (*) see comment at end of loop - // gcd(u,v) = 1 - // {odd,even} = {&us, &vr} - // odd->a[0] and odd->a[8] are odd - // even->a[0] or even->a[8] is even - // - // first u/v are large and r/s small - // later u/v are small and r/s large - assert(odd->a[0] & 1); - assert(odd->a[8] & 1); - - // adjust length of even. - while (even->a[even->len1 - 1] == 0) { - even->len1--; - // if input was 0, return. - // This simple check prevents crashing with stack underflow - // or worse undesired behaviour for illegal input. - if (even->len1 < 0) - return; - } - - // reduce even->a while it is even - while (even->a[0] == 0) { - // shift right first part of even by a limb - // and shift left second part of even by a limb. - for (i = 0; i < 8; i++) { - even->a[i] = even->a[i+1]; - } - even->a[i] = 0; - even->len1--; - k += 32; - } - // count up to 32 zero bits of even->a. - j = 0; - while ((even->a[0] & (1u << j)) == 0) { - j++; - } - if (j > 0) { - // shift first part of even right by j bits. - for (i = 0; i + 1 < even->len1; i++) { - even->a[i] = (even->a[i] >> j) | (even->a[i + 1] << (32 - j)); - } - even->a[i] = (even->a[i] >> j); - if (even->a[i] == 0) { - even->len1--; - } else { - i++; - } - - // shift second part of even left by j bits. - for (; i < 8; i++) { - even->a[i] = (even->a[i] << j) | (even->a[i + 1] >> (32 - j)); - } - even->a[i] = (even->a[i] << j); - // add j bits to k. - k += j; - } - // invariant is reestablished. - // now both a[0] are odd. - assert(odd->a[0] & 1); - assert(odd->a[8] & 1); - assert(even->a[0] & 1); - assert((even->a[8] & 1) == 0); - - // cmp > 0 if us.a[0..len1-1] > vr.a[0..len1-1], - // cmp = 0 if equal, < 0 if less. - cmp = us.len1 - vr.len1; - if (cmp == 0) { - i = us.len1 - 1; - while (i >= 0 && us.a[i] == vr.a[i]) i--; - // both are equal to 1 and we are done. - if (i == -1) - break; - cmp = us.a[i] > vr.a[i] ? 1 : -1; - } - if (cmp > 0) { - even = &us; - odd = &vr; - } else { - even = &vr; - odd = &us; - } - - // now even > odd. - - // even->a[0..len1-1] = (even->a[0..len1-1] - odd->a[0..len1-1]); - temp = 1; - for (i = 0; i < odd->len1; i++) { - temp += 0xFFFFFFFFull + even->a[i] - odd->a[i]; - even->a[i] = temp & 0xFFFFFFFF; - temp >>= 32; - } - for (; i < even->len1; i++) { - temp += 0xFFFFFFFFull + even->a[i]; - even->a[i] = temp & 0xFFFFFFFF; - temp >>= 32; - } - // odd->a[len1..8] = (odd->b[len1..8] + even->b[len1..8]); - temp = 0; - for (i = 8; i >= even->len1; i--) { - temp += (uint64_t) odd->a[i] + even->a[i]; - odd->a[i] = temp & 0xFFFFFFFF; - temp >>= 32; - } - for (; i >= odd->len1; i--) { - temp += (uint64_t) odd->a[i]; - odd->a[i] = temp & 0xFFFFFFFF; - temp >>= 32; - } - // note that - // if u > v: - // u'2^k = (u - v) 2^k = x(-r) - xs = x(-(r+s)) = x(-r') mod prime - // u's' + v'r' = (u-v)s + v(r+s) = us + vr - // if u < v: - // v'2^k = (v - u) 2^k = xs - x(-r) = x(s+r) = xs' mod prime - // u's' + v'r' = u(s+r) + (v-u)r = us + vr - - // even->a[0] is difference between two odd numbers, hence even. - // odd->a[8] is sum of even and odd number, hence odd. - assert(odd->a[0] & 1); - assert(odd->a[8] & 1); - assert((even->a[0] & 1) == 0); - - // The invariants are (almost) reestablished. - // The invariant max(u,v) <= 2^k can be invalidated at this point, - // because odd->a[len1..8] was changed. We only have - // - // odd->a[len1..8] <= 2^{k+1} - // - // Since even->a[0] is even, k will be incremented at the beginning - // of the next loop while odd->a[len1..8] remains unchanged. - // So after that, odd->a[len1..8] <= 2^k will hold again. - } - // In the last iteration we had u = v and gcd(u,v) = 1. - // Hence, u=1, v=1, s+r = prime, k <= 510, 2^k > max(s,r) >= prime/2 - // This implies 0 <= s < prime and 255 <= k <= 510. - // - // The invariants also give us x*s = 2^k mod prime, - // hence s = 2^k * x^-1 mod prime. - // We need to compute s/2^k mod prime. - - // First we compute inverse = -prime^-1 mod 2^32, which we need later. - // We use the Explicit Quadratic Modular inverse algorithm. - // http://arxiv.org/pdf/1209.6626.pdf - // a^-1 = (2-a) * PROD_i (1 + (a - 1)^(2^i)) mod 2^32 - // the product will converge quickly, because (a-1)^(2^i) will be - // zero mod 2^32 after at most five iterations. - // We want to compute -prime^-1 so we start with (pp[0]-2). - assert(pp[0] & 1); - uint32_t amone = pp[0]-1; - uint32_t inverse = pp[0] - 2; - while (amone) { - amone *= amone; - inverse *= (amone + 1); - } - - while (k >= 32) { - // compute s / 2^32 modulo prime. - // Idea: compute factor, such that - // s + factor*prime mod 2^32 == 0 - // i.e. factor = s * -1/prime mod 2^32. - // Then compute s + factor*prime and shift right by 32 bits. - uint32_t factor = (inverse * us.a[8]) & 0xffffffff; - temp = us.a[8] + (uint64_t) pp[0] * factor; - assert((temp & 0xffffffff) == 0); - temp >>= 32; - for (i = 0; i < 7; i++) { - temp += us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor; - us.a[8-i] = temp & 0xffffffff; - temp >>= 32; - } - us.a[8-i] = temp & 0xffffffff; - k -= 32; - } - if (k > 0) { - // compute s / 2^k modulo prime. - // Same idea: compute factor, such that - // s + factor*prime mod 2^k == 0 - // i.e. factor = s * -1/prime mod 2^k. - // Then compute s + factor*prime and shift right by k bits. - uint32_t mask = (1u << k) - 1; - uint32_t factor = (inverse * us.a[8]) & mask; - temp = (us.a[8] + (uint64_t) pp[0] * factor) >> k; - assert(((us.a[8] + pp[0] * factor) & mask) == 0); - for (i = 0; i < 7; i++) { - temp += (us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor) << (32 - k); - us.a[8-i] = temp & 0xffffffff; - temp >>= 32; - } - us.a[8-i] = temp & 0xffffffff; - } - - // convert s to bignum style - temp32 = 0; - for (i = 0; i < 8; i++) { - x->val[i] = ((us.a[8-i] << (2 * i)) & 0x3FFFFFFFu) | temp32; - temp32 = us.a[8-i] >> (30 - 2 * i); - } - x->val[i] = temp32; - - // let's wipe all temp buffers - memzero(pp, sizeof(pp)); - memzero(&us, sizeof(us)); - memzero(&vr, sizeof(vr)); +void bn_inverse(bignum256 *x, const bignum256 *prime) { + int i, j, k, cmp; + struct combo { + uint32_t a[9]; + int len1; + } us, vr, *odd, *even; + uint32_t pp[8]; + uint32_t temp32; + uint64_t temp; + + // The algorithm is based on Schroeppel et. al. "Almost Modular Inverse" + // algorithm. We keep four values u,v,r,s in the combo registers + // us and vr. us stores u in the first len1 limbs (little endian) + // and s in the last 9-len1 limbs (big endian). vr stores v and r. + // This is because both u*s and v*r are guaranteed to fit in 8 limbs, so + // their components are guaranteed to fit in 9. During the algorithm, + // the length of u and v shrinks while r and s grow. + // u,v,r,s correspond to F,G,B,C in Schroeppel's algorithm. + + // reduce x modulo prime. This is necessary as it has to fit in 8 limbs. + bn_fast_mod(x, prime); + bn_mod(x, prime); + // convert x and prime to 8x32 bit limb form + temp32 = prime->val[0]; + for (i = 0; i < 8; i++) { + temp32 |= prime->val[i + 1] << (30 - 2 * i); + us.a[i] = pp[i] = temp32; + temp32 = prime->val[i + 1] >> (2 + 2 * i); + } + temp32 = x->val[0]; + for (i = 0; i < 8; i++) { + temp32 |= x->val[i + 1] << (30 - 2 * i); + vr.a[i] = temp32; + temp32 = x->val[i + 1] >> (2 + 2 * i); + } + us.len1 = 8; + vr.len1 = 8; + // set s = 1 and r = 0 + us.a[8] = 1; + vr.a[8] = 0; + // set k = 0. + k = 0; + + // only one of the numbers u,v can be even at any time. We + // let even point to that number and odd to the other. + // Initially the prime u is guaranteed to be odd. + odd = &us; + even = &vr; + + // u = prime, v = x + // r = 0 , s = 1 + // k = 0 + for (;;) { + // invariants: + // let u = limbs us.a[0..u.len1-1] in little endian, + // let s = limbs us.a[u.len..8] in big endian, + // let v = limbs vr.a[0..u.len1-1] in little endian, + // let r = limbs vr.a[u.len..8] in big endian, + // r,s >= 0 ; u,v >= 1 + // x*-r = u*2^k mod prime + // x*s = v*2^k mod prime + // u*s + v*r = prime + // floor(log2(u)) + floor(log2(v)) + k <= 510 + // max(u,v) <= 2^k (*) see comment at end of loop + // gcd(u,v) = 1 + // {odd,even} = {&us, &vr} + // odd->a[0] and odd->a[8] are odd + // even->a[0] or even->a[8] is even + // + // first u/v are large and r/s small + // later u/v are small and r/s large + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + + // adjust length of even. + while (even->a[even->len1 - 1] == 0) { + even->len1--; + // if input was 0, return. + // This simple check prevents crashing with stack underflow + // or worse undesired behaviour for illegal input. + if (even->len1 < 0) return; + } + + // reduce even->a while it is even + while (even->a[0] == 0) { + // shift right first part of even by a limb + // and shift left second part of even by a limb. + for (i = 0; i < 8; i++) { + even->a[i] = even->a[i + 1]; + } + even->a[i] = 0; + even->len1--; + k += 32; + } + // count up to 32 zero bits of even->a. + j = 0; + while ((even->a[0] & (1u << j)) == 0) { + j++; + } + if (j > 0) { + // shift first part of even right by j bits. + for (i = 0; i + 1 < even->len1; i++) { + even->a[i] = (even->a[i] >> j) | (even->a[i + 1] << (32 - j)); + } + even->a[i] = (even->a[i] >> j); + if (even->a[i] == 0) { + even->len1--; + } else { + i++; + } + + // shift second part of even left by j bits. + for (; i < 8; i++) { + even->a[i] = (even->a[i] << j) | (even->a[i + 1] >> (32 - j)); + } + even->a[i] = (even->a[i] << j); + // add j bits to k. + k += j; + } + // invariant is reestablished. + // now both a[0] are odd. + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + assert(even->a[0] & 1); + assert((even->a[8] & 1) == 0); + + // cmp > 0 if us.a[0..len1-1] > vr.a[0..len1-1], + // cmp = 0 if equal, < 0 if less. + cmp = us.len1 - vr.len1; + if (cmp == 0) { + i = us.len1 - 1; + while (i >= 0 && us.a[i] == vr.a[i]) i--; + // both are equal to 1 and we are done. + if (i == -1) break; + cmp = us.a[i] > vr.a[i] ? 1 : -1; + } + if (cmp > 0) { + even = &us; + odd = &vr; + } else { + even = &vr; + odd = &us; + } + + // now even > odd. + + // even->a[0..len1-1] = (even->a[0..len1-1] - odd->a[0..len1-1]); + temp = 1; + for (i = 0; i < odd->len1; i++) { + temp += 0xFFFFFFFFull + even->a[i] - odd->a[i]; + even->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + for (; i < even->len1; i++) { + temp += 0xFFFFFFFFull + even->a[i]; + even->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + // odd->a[len1..8] = (odd->b[len1..8] + even->b[len1..8]); + temp = 0; + for (i = 8; i >= even->len1; i--) { + temp += (uint64_t)odd->a[i] + even->a[i]; + odd->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + for (; i >= odd->len1; i--) { + temp += (uint64_t)odd->a[i]; + odd->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + // note that + // if u > v: + // u'2^k = (u - v) 2^k = x(-r) - xs = x(-(r+s)) = x(-r') mod prime + // u's' + v'r' = (u-v)s + v(r+s) = us + vr + // if u < v: + // v'2^k = (v - u) 2^k = xs - x(-r) = x(s+r) = xs' mod prime + // u's' + v'r' = u(s+r) + (v-u)r = us + vr + + // even->a[0] is difference between two odd numbers, hence even. + // odd->a[8] is sum of even and odd number, hence odd. + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + assert((even->a[0] & 1) == 0); + + // The invariants are (almost) reestablished. + // The invariant max(u,v) <= 2^k can be invalidated at this point, + // because odd->a[len1..8] was changed. We only have + // + // odd->a[len1..8] <= 2^{k+1} + // + // Since even->a[0] is even, k will be incremented at the beginning + // of the next loop while odd->a[len1..8] remains unchanged. + // So after that, odd->a[len1..8] <= 2^k will hold again. + } + // In the last iteration we had u = v and gcd(u,v) = 1. + // Hence, u=1, v=1, s+r = prime, k <= 510, 2^k > max(s,r) >= prime/2 + // This implies 0 <= s < prime and 255 <= k <= 510. + // + // The invariants also give us x*s = 2^k mod prime, + // hence s = 2^k * x^-1 mod prime. + // We need to compute s/2^k mod prime. + + // First we compute inverse = -prime^-1 mod 2^32, which we need later. + // We use the Explicit Quadratic Modular inverse algorithm. + // http://arxiv.org/pdf/1209.6626.pdf + // a^-1 = (2-a) * PROD_i (1 + (a - 1)^(2^i)) mod 2^32 + // the product will converge quickly, because (a-1)^(2^i) will be + // zero mod 2^32 after at most five iterations. + // We want to compute -prime^-1 so we start with (pp[0]-2). + assert(pp[0] & 1); + uint32_t amone = pp[0] - 1; + uint32_t inverse = pp[0] - 2; + while (amone) { + amone *= amone; + inverse *= (amone + 1); + } + + while (k >= 32) { + // compute s / 2^32 modulo prime. + // Idea: compute factor, such that + // s + factor*prime mod 2^32 == 0 + // i.e. factor = s * -1/prime mod 2^32. + // Then compute s + factor*prime and shift right by 32 bits. + uint32_t factor = (inverse * us.a[8]) & 0xffffffff; + temp = us.a[8] + (uint64_t)pp[0] * factor; + assert((temp & 0xffffffff) == 0); + temp >>= 32; + for (i = 0; i < 7; i++) { + temp += us.a[8 - (i + 1)] + (uint64_t)pp[i + 1] * factor; + us.a[8 - i] = temp & 0xffffffff; + temp >>= 32; + } + us.a[8 - i] = temp & 0xffffffff; + k -= 32; + } + if (k > 0) { + // compute s / 2^k modulo prime. + // Same idea: compute factor, such that + // s + factor*prime mod 2^k == 0 + // i.e. factor = s * -1/prime mod 2^k. + // Then compute s + factor*prime and shift right by k bits. + uint32_t mask = (1u << k) - 1; + uint32_t factor = (inverse * us.a[8]) & mask; + temp = (us.a[8] + (uint64_t)pp[0] * factor) >> k; + assert(((us.a[8] + pp[0] * factor) & mask) == 0); + for (i = 0; i < 7; i++) { + temp += (us.a[8 - (i + 1)] + (uint64_t)pp[i + 1] * factor) << (32 - k); + us.a[8 - i] = temp & 0xffffffff; + temp >>= 32; + } + us.a[8 - i] = temp & 0xffffffff; + } + + // convert s to bignum style + temp32 = 0; + for (i = 0; i < 8; i++) { + x->val[i] = ((us.a[8 - i] << (2 * i)) & 0x3FFFFFFFu) | temp32; + temp32 = us.a[8 - i] >> (30 - 2 * i); + } + x->val[i] = temp32; + + // let's wipe all temp buffers + memzero(pp, sizeof(pp)); + memzero(&us, sizeof(us)); + memzero(&vr, sizeof(vr)); } #endif -void bn_normalize(bignum256 *a) { - bn_addi(a, 0); -} +void bn_normalize(bignum256 *a) { bn_addi(a, 0); } // add two numbers a = a + b // assumes that a, b are normalized // guarantees that a is normalized -void bn_add(bignum256 *a, const bignum256 *b) -{ - int i; - uint32_t tmp = 0; - for (i = 0; i < 9; i++) { - tmp += a->val[i] + b->val[i]; - a->val[i] = tmp & 0x3FFFFFFF; - tmp >>= 30; - } +void bn_add(bignum256 *a, const bignum256 *b) { + int i; + uint32_t tmp = 0; + for (i = 0; i < 9; i++) { + tmp += a->val[i] + b->val[i]; + a->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } } -void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime) -{ - int i; - for (i = 0; i < 9; i++) { - a->val[i] += b->val[i]; - } - bn_fast_mod(a, prime); +void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime) { + int i; + for (i = 0; i < 9; i++) { + a->val[i] += b->val[i]; + } + bn_fast_mod(a, prime); } void bn_addi(bignum256 *a, uint32_t b) { - int i; - uint32_t tmp = b; - for (i = 0; i < 9; i++) { - tmp += a->val[i]; - a->val[i] = tmp & 0x3FFFFFFF; - tmp >>= 30; - } + int i; + uint32_t tmp = b; + for (i = 0; i < 9; i++) { + tmp += a->val[i]; + a->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } } void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime) { - assert (b <= prime->val[0]); - // the possible underflow will be taken care of when adding the prime - a->val[0] -= b; - bn_add(a, prime); + assert(b <= prime->val[0]); + // the possible underflow will be taken care of when adding the prime + a->val[0] -= b; + bn_add(a, prime); } // res = a - b mod prime. More exactly res = a + (2*prime - b). // b must be a partly reduced number // result is normalized but not reduced. -void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime) -{ - int i; - uint32_t temp = 1; - for (i = 0; i < 9; i++) { - temp += 0x3FFFFFFF + a->val[i] + 2u * prime->val[i] - b->val[i]; - res->val[i] = temp & 0x3FFFFFFF; - temp >>= 30; - } +void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, + const bignum256 *prime) { + int i; + uint32_t temp = 1; + for (i = 0; i < 9; i++) { + temp += 0x3FFFFFFF + a->val[i] + 2u * prime->val[i] - b->val[i]; + res->val[i] = temp & 0x3FFFFFFF; + temp >>= 30; + } } // res = a - b ; a > b -void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res) -{ - int i; - uint32_t tmp = 1; - for (i = 0; i < 9; i++) { - tmp += 0x3FFFFFFF + a->val[i] - b->val[i]; - res->val[i] = tmp & 0x3FFFFFFF; - tmp >>= 30; - } +void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res) { + int i; + uint32_t tmp = 1; + for (i = 0; i < 9; i++) { + tmp += 0x3FFFFFFF + a->val[i] - b->val[i]; + res->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } } // a / 58 = a (+r) -void bn_divmod58(bignum256 *a, uint32_t *r) -{ - int i; - uint32_t rem, tmp; - rem = a->val[8] % 58; - a->val[8] /= 58; - for (i = 7; i >= 0; i--) { - // invariants: - // rem = old(a) >> 30(i+1) % 58 - // a[i+1..8] = old(a[i+1..8])/58 - // a[0..i] = old(a[0..i]) - // 2^30 == 18512790*58 + 4 - tmp = rem * 4 + a->val[i]; - // set a[i] = (rem * 2^30 + a[i])/58 - // = rem * 18512790 + (rem * 4 + a[i])/58 - a->val[i] = rem * 18512790 + (tmp / 58); - // set rem = (rem * 2^30 + a[i]) mod 58 - // = (rem * 4 + a[i]) mod 58 - rem = tmp % 58; - } - *r = rem; +void bn_divmod58(bignum256 *a, uint32_t *r) { + int i; + uint32_t rem, tmp; + rem = a->val[8] % 58; + a->val[8] /= 58; + for (i = 7; i >= 0; i--) { + // invariants: + // rem = old(a) >> 30(i+1) % 58 + // a[i+1..8] = old(a[i+1..8])/58 + // a[0..i] = old(a[0..i]) + // 2^30 == 18512790*58 + 4 + tmp = rem * 4 + a->val[i]; + // set a[i] = (rem * 2^30 + a[i])/58 + // = rem * 18512790 + (rem * 4 + a[i])/58 + a->val[i] = rem * 18512790 + (tmp / 58); + // set rem = (rem * 2^30 + a[i]) mod 58 + // = (rem * 4 + a[i]) mod 58 + rem = tmp % 58; + } + *r = rem; } // a / 1000 = a (+r) -void bn_divmod1000(bignum256 *a, uint32_t *r) -{ - int i; - uint32_t rem, tmp; - rem = a->val[8] % 1000; - a->val[8] /= 1000; - for (i = 7; i >= 0; i--) { - // invariants: - // rem = old(a) >> 30(i+1) % 1000 - // a[i+1..8] = old(a[i+1..8])/1000 - // a[0..i] = old(a[0..i]) - // 2^30 == 1073741*1000 + 824 - tmp = rem * 824 + a->val[i]; - // set a[i] = (rem * 2^30 + a[i])/1000 - // = rem * 1073741 + (rem * 824 + a[i])/1000 - a->val[i] = rem * 1073741 + (tmp / 1000); - // set rem = (rem * 2^30 + a[i]) mod 1000 - // = (rem * 824 + a[i]) mod 1000 - rem = tmp % 1000; - } - *r = rem; +void bn_divmod1000(bignum256 *a, uint32_t *r) { + int i; + uint32_t rem, tmp; + rem = a->val[8] % 1000; + a->val[8] /= 1000; + for (i = 7; i >= 0; i--) { + // invariants: + // rem = old(a) >> 30(i+1) % 1000 + // a[i+1..8] = old(a[i+1..8])/1000 + // a[0..i] = old(a[0..i]) + // 2^30 == 1073741*1000 + 824 + tmp = rem * 824 + a->val[i]; + // set a[i] = (rem * 2^30 + a[i])/1000 + // = rem * 1073741 + (rem * 824 + a[i])/1000 + a->val[i] = rem * 1073741 + (tmp / 1000); + // set rem = (rem * 2^30 + a[i]) mod 1000 + // = (rem * 824 + a[i]) mod 1000 + rem = tmp % 1000; + } + *r = rem; } -size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen) -{ - // sanity check, 2**256 ~ 10**77; we should never need decimals/exponent bigger than that - if (decimals > 80 || exponent < -20 || exponent > 80) { - memzero(out, outlen); - return 0; - } - - size_t prefixlen = prefix ? strlen(prefix) : 0; - size_t suffixlen = suffix ? strlen(suffix) : 0; - - /* add prefix to beginning of out buffer */ - if (prefixlen) { - memcpy(out, prefix, prefixlen); - } - /* add suffix to end of out buffer */ - if (suffixlen) { - memcpy(&out[outlen - suffixlen - 1], suffix, suffixlen); - } - /* nul terminate (even if suffix = NULL) */ - out[outlen - 1] = '\0'; - - /* fill number between prefix and suffix (between start and end) */ - char *start = &out[prefixlen], *end = &out[outlen - suffixlen - 1]; - char *str = end; +size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, + unsigned int decimals, int exponent, bool trailing, char *out, + size_t outlen) { + // sanity check, 2**256 ~ 10**77; we should never need decimals/exponent + // bigger than that + if (decimals > 80 || exponent < -20 || exponent > 80) { + memzero(out, outlen); + return 0; + } + + size_t prefixlen = prefix ? strlen(prefix) : 0; + size_t suffixlen = suffix ? strlen(suffix) : 0; + + /* add prefix to beginning of out buffer */ + if (prefixlen) { + memcpy(out, prefix, prefixlen); + } + /* add suffix to end of out buffer */ + if (suffixlen) { + memcpy(&out[outlen - suffixlen - 1], suffix, suffixlen); + } + /* nul terminate (even if suffix = NULL) */ + out[outlen - 1] = '\0'; + + /* fill number between prefix and suffix (between start and end) */ + char *start = &out[prefixlen], *end = &out[outlen - suffixlen - 1]; + char *str = end; #define BN_FORMAT_PUSH_CHECKED(c) \ - do { \ - if (str == start) return 0; \ - *--str = (c); \ - } while (0) - -#define BN_FORMAT_PUSH(n) \ - do { \ - if (exponent < 0) { \ - exponent++; \ - } else { \ - if ((n) > 0 || trailing || str != end || decimals <= 1) { \ - BN_FORMAT_PUSH_CHECKED('0' + (n)); \ - } \ - if (decimals > 0 && decimals-- == 1) { \ - BN_FORMAT_PUSH_CHECKED('.'); \ - } \ - } \ - } while (0) - - bignum256 val; - memcpy(&val, amnt, sizeof(bignum256)); - - if (bn_is_zero(&val)) { - exponent = 0; - } - - for (; exponent > 0; exponent--) { - BN_FORMAT_PUSH(0); - } - - unsigned int digits = bn_digitcount(&val); - for (unsigned int i = 0; i < digits / 3; i++) { - uint32_t limb; - bn_divmod1000(&val, &limb); - - BN_FORMAT_PUSH(limb % 10); - limb /= 10; - BN_FORMAT_PUSH(limb % 10); - limb /= 10; - BN_FORMAT_PUSH(limb % 10); - } - - if (digits % 3 != 0) { - uint32_t limb; - bn_divmod1000(&val, &limb); - - switch (digits % 3) { - case 2: - BN_FORMAT_PUSH(limb % 10); - limb /= 10; - //-fallthrough - - case 1: - BN_FORMAT_PUSH(limb % 10); - break; - } - } - - while (decimals > 0 || str[0] == '\0' || str[0] == '.') { - BN_FORMAT_PUSH(0); - } - - /* finally move number to &out[prefixlen] to close the gap between - * prefix and str. len is length of number + suffix + traling 0 - */ - size_t len = &out[outlen] - str; - memmove(&out[prefixlen], str, len); - - /* return length of number including prefix and suffix without trailing 0 */ - return prefixlen + len - 1; + do { \ + if (str == start) return 0; \ + *--str = (c); \ + } while (0) + +#define BN_FORMAT_PUSH(n) \ + do { \ + if (exponent < 0) { \ + exponent++; \ + } else { \ + if ((n) > 0 || trailing || str != end || decimals <= 1) { \ + BN_FORMAT_PUSH_CHECKED('0' + (n)); \ + } \ + if (decimals > 0 && decimals-- == 1) { \ + BN_FORMAT_PUSH_CHECKED('.'); \ + } \ + } \ + } while (0) + + bignum256 val; + memcpy(&val, amnt, sizeof(bignum256)); + + if (bn_is_zero(&val)) { + exponent = 0; + } + + for (; exponent > 0; exponent--) { + BN_FORMAT_PUSH(0); + } + + unsigned int digits = bn_digitcount(&val); + for (unsigned int i = 0; i < digits / 3; i++) { + uint32_t limb; + bn_divmod1000(&val, &limb); + + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + BN_FORMAT_PUSH(limb % 10); + } + + if (digits % 3 != 0) { + uint32_t limb; + bn_divmod1000(&val, &limb); + + switch (digits % 3) { + case 2: + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + //-fallthrough + + case 1: + BN_FORMAT_PUSH(limb % 10); + break; + } + } + + while (decimals > 0 || str[0] == '\0' || str[0] == '.') { + BN_FORMAT_PUSH(0); + } + + /* finally move number to &out[prefixlen] to close the gap between + * prefix and str. len is length of number + suffix + traling 0 + */ + size_t len = &out[outlen] - str; + memmove(&out[prefixlen], str, len); + + /* return length of number including prefix and suffix without trailing 0 */ + return prefixlen + len - 1; } #if USE_BN_PRINT -void bn_print(const bignum256 *a) -{ - printf("%04x", a->val[8] & 0x0000FFFF); - printf("%08x", (a->val[7] << 2) | ((a->val[6] & 0x30000000) >> 28)); - printf("%07x", a->val[6] & 0x0FFFFFFF); - printf("%08x", (a->val[5] << 2) | ((a->val[4] & 0x30000000) >> 28)); - printf("%07x", a->val[4] & 0x0FFFFFFF); - printf("%08x", (a->val[3] << 2) | ((a->val[2] & 0x30000000) >> 28)); - printf("%07x", a->val[2] & 0x0FFFFFFF); - printf("%08x", (a->val[1] << 2) | ((a->val[0] & 0x30000000) >> 28)); - printf("%07x", a->val[0] & 0x0FFFFFFF); +void bn_print(const bignum256 *a) { + printf("%04x", a->val[8] & 0x0000FFFF); + printf("%08x", (a->val[7] << 2) | ((a->val[6] & 0x30000000) >> 28)); + printf("%07x", a->val[6] & 0x0FFFFFFF); + printf("%08x", (a->val[5] << 2) | ((a->val[4] & 0x30000000) >> 28)); + printf("%07x", a->val[4] & 0x0FFFFFFF); + printf("%08x", (a->val[3] << 2) | ((a->val[2] & 0x30000000) >> 28)); + printf("%07x", a->val[2] & 0x0FFFFFFF); + printf("%08x", (a->val[1] << 2) | ((a->val[0] & 0x30000000) >> 28)); + printf("%07x", a->val[0] & 0x0FFFFFFF); } -void bn_print_raw(const bignum256 *a) -{ - int i; - for (i = 0; i <= 8; i++) { - printf("0x%08x, ", a->val[i]); - } +void bn_print_raw(const bignum256 *a) { + int i; + for (i = 0; i <= 8; i++) { + printf("0x%08x, ", a->val[i]); + } } #endif diff --git a/bignum.h b/bignum.h index f96cad665..e0225be20 100644 --- a/bignum.h +++ b/bignum.h @@ -33,7 +33,7 @@ // bignum256 are 256 bits stored as 8*30 bit + 1*16 bit // val[0] are lowest 30 bits, val[8] highest 16 bits typedef struct { - uint32_t val[9]; + uint32_t val[9]; } bignum256; // read 4 big endian bytes into uint32 @@ -60,26 +60,22 @@ void bn_read_uint32(uint32_t in_number, bignum256 *out_number); void bn_read_uint64(uint64_t in_number, bignum256 *out_number); -static inline uint32_t bn_write_uint32(const bignum256 *in_number) -{ - return in_number->val[0] | (in_number->val[1] << 30); +static inline uint32_t bn_write_uint32(const bignum256 *in_number) { + return in_number->val[0] | (in_number->val[1] << 30); } -static inline uint64_t bn_write_uint64(const bignum256 *in_number) -{ - uint64_t tmp; - tmp = in_number->val[2]; - tmp <<= 30; - tmp |= in_number->val[1]; - tmp <<= 30; - tmp |= in_number->val[0]; - return tmp; +static inline uint64_t bn_write_uint64(const bignum256 *in_number) { + uint64_t tmp; + tmp = in_number->val[2]; + tmp <<= 30; + tmp |= in_number->val[1]; + tmp <<= 30; + tmp |= in_number->val[0]; + return tmp; } // copies number a to b -static inline void bn_copy(const bignum256 *a, bignum256 *b) { - *b = *a; -} +static inline void bn_copy(const bignum256 *a, bignum256 *b) { *b = *a; } int bn_bitcount(const bignum256 *a); @@ -92,18 +88,17 @@ int bn_is_zero(const bignum256 *a); void bn_one(bignum256 *a); static inline int bn_is_even(const bignum256 *a) { - return (a->val[0] & 1) == 0; + return (a->val[0] & 1) == 0; } -static inline int bn_is_odd(const bignum256 *a) { - return (a->val[0] & 1) == 1; -} +static inline int bn_is_odd(const bignum256 *a) { return (a->val[0] & 1) == 1; } int bn_is_less(const bignum256 *a, const bignum256 *b); int bn_is_equal(const bignum256 *a, const bignum256 *b); -void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase); +void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, + const bignum256 *falsecase); void bn_lshift(bignum256 *a); @@ -141,7 +136,8 @@ void bn_addi(bignum256 *a, uint32_t b); void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime); -void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime); +void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, + const bignum256 *prime); void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res); @@ -149,14 +145,19 @@ void bn_divmod58(bignum256 *a, uint32_t *r); void bn_divmod1000(bignum256 *a, uint32_t *r); -size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen); +size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, + unsigned int decimals, int exponent, bool trailing, char *out, + size_t outlen); -static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen) -{ - bignum256 amnt; - bn_read_uint64(amount, &amnt); +static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, + const char *suffix, unsigned int decimals, + int exponent, bool trailing, char *out, + size_t outlen) { + bignum256 amnt; + bn_read_uint64(amount, &amnt); - return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, outlen); + return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, + outlen); } #if USE_BN_PRINT diff --git a/bip32.c b/bip32.c index 8d6291f51..75dbd33ee 100644 --- a/bip32.c +++ b/bip32.c @@ -22,23 +22,23 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include #include +#include -#include "aes/aes.h" #include "address.h" +#include "aes/aes.h" +#include "base58.h" #include "bignum.h" -#include "hmac.h" -#include "ecdsa.h" #include "bip32.h" -#include "sha2.h" -#include "sha3.h" -#include "base58.h" #include "curves.h" -#include "secp256k1.h" -#include "nist256p1.h" -#include "ed25519-donna/ed25519.h" +#include "ecdsa.h" #include "ed25519-donna/ed25519-sha3.h" +#include "ed25519-donna/ed25519.h" +#include "hmac.h" +#include "nist256p1.h" +#include "secp256k1.h" +#include "sha2.h" +#include "sha3.h" #if USE_KECCAK #include "ed25519-donna/ed25519-keccak.h" #endif @@ -51,412 +51,423 @@ #include "memzero.h" const curve_info ed25519_info = { - .bip32_name = "ed25519 seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "ed25519 seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; const curve_info ed25519_cardano_info = { - .bip32_name = "ed25519 cardano seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "ed25519 cardano seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; const curve_info ed25519_sha3_info = { - .bip32_name = "ed25519-sha3 seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "ed25519-sha3 seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; #if USE_KECCAK const curve_info ed25519_keccak_info = { - .bip32_name = "ed25519-keccak seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "ed25519-keccak seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; #endif const curve_info curve25519_info = { - .bip32_name = "curve25519 seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "curve25519 seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; -int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char* curve, HDNode *out) -{ - const curve_info *info = get_curve_by_name(curve); - if (info == 0) { - return 0; - } - if (public_key[0] != 0x02 && public_key[0] != 0x03) { // invalid pubkey - return 0; - } - out->curve = info; - out->depth = depth; - out->child_num = child_num; - memcpy(out->chain_code, chain_code, 32); - memzero(out->private_key, 32); - memzero(out->private_key_extension,32); - memcpy(out->public_key, public_key, 33); - return 1; +int hdnode_from_xpub(uint32_t depth, uint32_t child_num, + const uint8_t *chain_code, const uint8_t *public_key, + const char *curve, HDNode *out) { + const curve_info *info = get_curve_by_name(curve); + if (info == 0) { + return 0; + } + if (public_key[0] != 0x02 && public_key[0] != 0x03) { // invalid pubkey + return 0; + } + out->curve = info; + out->depth = depth; + out->child_num = child_num; + memcpy(out->chain_code, chain_code, 32); + memzero(out->private_key, 32); + memzero(out->private_key_extension, 32); + memcpy(out->public_key, public_key, 33); + return 1; } -int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char* curve, HDNode *out) -{ - bool failed = false; - const curve_info *info = get_curve_by_name(curve); - if (info == 0) { - failed = true; - } else if (info->params) { - bignum256 a; - bn_read_be(private_key, &a); - if (bn_is_zero(&a)) { // == 0 - failed = true; - } else { - if (!bn_is_less(&a, &info->params->order)) { // >= order - failed = true; - } - } - memzero(&a, sizeof(a)); - } - - if (failed) { - return 0; - } - - out->curve = info; - out->depth = depth; - out->child_num = child_num; - memcpy(out->chain_code, chain_code, 32); - memcpy(out->private_key, private_key, 32); - memzero(out->public_key, sizeof(out->public_key)); - memzero(out->private_key_extension, sizeof(out->private_key_extension)); - return 1; +int hdnode_from_xprv(uint32_t depth, uint32_t child_num, + const uint8_t *chain_code, const uint8_t *private_key, + const char *curve, HDNode *out) { + bool failed = false; + const curve_info *info = get_curve_by_name(curve); + if (info == 0) { + failed = true; + } else if (info->params) { + bignum256 a; + bn_read_be(private_key, &a); + if (bn_is_zero(&a)) { // == 0 + failed = true; + } else { + if (!bn_is_less(&a, &info->params->order)) { // >= order + failed = true; + } + } + memzero(&a, sizeof(a)); + } + + if (failed) { + return 0; + } + + out->curve = info; + out->depth = depth; + out->child_num = child_num; + memcpy(out->chain_code, chain_code, 32); + memcpy(out->private_key, private_key, 32); + memzero(out->public_key, sizeof(out->public_key)); + memzero(out->private_key_extension, sizeof(out->private_key_extension)); + return 1; } -int hdnode_from_seed(const uint8_t *seed, int seed_len, const char* curve, HDNode *out) -{ - static CONFIDENTIAL uint8_t I[32 + 32]; - memzero(out, sizeof(HDNode)); - out->depth = 0; - out->child_num = 0; - out->curve = get_curve_by_name(curve); - if (out->curve == 0) { - return 0; - } - static CONFIDENTIAL HMAC_SHA512_CTX ctx; - hmac_sha512_Init(&ctx, (const uint8_t*) out->curve->bip32_name, strlen(out->curve->bip32_name)); - hmac_sha512_Update(&ctx, seed, seed_len); - hmac_sha512_Final(&ctx, I); - - if (out->curve->params) { - bignum256 a; - while (true) { - bn_read_be(I, &a); - if (!bn_is_zero(&a) // != 0 - && bn_is_less(&a, &out->curve->params->order)) { // < order - break; - } - hmac_sha512_Init(&ctx, (const uint8_t*) out->curve->bip32_name, strlen(out->curve->bip32_name)); - hmac_sha512_Update(&ctx, I, sizeof(I)); - hmac_sha512_Final(&ctx, I); - } - memzero(&a, sizeof(a)); - } - memcpy(out->private_key, I, 32); - memcpy(out->chain_code, I + 32, 32); - memzero(out->public_key, sizeof(out->public_key)); - memzero(I, sizeof(I)); - return 1; +int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, + HDNode *out) { + static CONFIDENTIAL uint8_t I[32 + 32]; + memzero(out, sizeof(HDNode)); + out->depth = 0; + out->child_num = 0; + out->curve = get_curve_by_name(curve); + if (out->curve == 0) { + return 0; + } + static CONFIDENTIAL HMAC_SHA512_CTX ctx; + hmac_sha512_Init(&ctx, (const uint8_t *)out->curve->bip32_name, + strlen(out->curve->bip32_name)); + hmac_sha512_Update(&ctx, seed, seed_len); + hmac_sha512_Final(&ctx, I); + + if (out->curve->params) { + bignum256 a; + while (true) { + bn_read_be(I, &a); + if (!bn_is_zero(&a) // != 0 + && bn_is_less(&a, &out->curve->params->order)) { // < order + break; + } + hmac_sha512_Init(&ctx, (const uint8_t *)out->curve->bip32_name, + strlen(out->curve->bip32_name)); + hmac_sha512_Update(&ctx, I, sizeof(I)); + hmac_sha512_Final(&ctx, I); + } + memzero(&a, sizeof(a)); + } + memcpy(out->private_key, I, 32); + memcpy(out->chain_code, I + 32, 32); + memzero(out->public_key, sizeof(out->public_key)); + memzero(I, sizeof(I)); + return 1; } -uint32_t hdnode_fingerprint(HDNode *node) -{ - uint8_t digest[32]; - uint32_t fingerprint; +uint32_t hdnode_fingerprint(HDNode *node) { + uint8_t digest[32]; + uint32_t fingerprint; - hdnode_fill_public_key(node); - hasher_Raw(node->curve->hasher_pubkey, node->public_key, 33, digest); - fingerprint = ((uint32_t) digest[0] << 24) + (digest[1] << 16) + (digest[2] << 8) + digest[3]; - memzero(digest, sizeof(digest)); - return fingerprint; + hdnode_fill_public_key(node); + hasher_Raw(node->curve->hasher_pubkey, node->public_key, 33, digest); + fingerprint = ((uint32_t)digest[0] << 24) + (digest[1] << 16) + + (digest[2] << 8) + digest[3]; + memzero(digest, sizeof(digest)); + return fingerprint; } -int hdnode_private_ckd(HDNode *inout, uint32_t i) -{ - static CONFIDENTIAL uint8_t data[1 + 32 + 4]; - static CONFIDENTIAL uint8_t I[32 + 32]; - static CONFIDENTIAL bignum256 a, b; - - if (i & 0x80000000) { // private derivation - data[0] = 0; - memcpy(data + 1, inout->private_key, 32); - } else { // public derivation - if (!inout->curve->params) { - return 0; - } - hdnode_fill_public_key(inout); - memcpy(data, inout->public_key, 33); - } - write_be(data + 33, i); - - bn_read_be(inout->private_key, &a); - - static CONFIDENTIAL HMAC_SHA512_CTX ctx; - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, sizeof(data)); - hmac_sha512_Final(&ctx, I); - - if (inout->curve->params) { - while (true) { - bool failed = false; - bn_read_be(I, &b); - if (!bn_is_less(&b, &inout->curve->params->order)) { // >= order - failed = true; - } else { - bn_add(&b, &a); - bn_mod(&b, &inout->curve->params->order); - if (bn_is_zero(&b)) { - failed = true; - } - } - - if (!failed) { - bn_write_be(&b, inout->private_key); - break; - } - - data[0] = 1; - memcpy(data + 1, I + 32, 32); - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, sizeof(data)); - hmac_sha512_Final(&ctx, I); - } - } else { - memcpy(inout->private_key, I, 32); - } - - memcpy(inout->chain_code, I + 32, 32); - inout->depth++; - inout->child_num = i; - memzero(inout->public_key, sizeof(inout->public_key)); - - // making sure to wipe our memory - memzero(&a, sizeof(a)); - memzero(&b, sizeof(b)); - memzero(I, sizeof(I)); - memzero(data, sizeof(data)); - return 1; +int hdnode_private_ckd(HDNode *inout, uint32_t i) { + static CONFIDENTIAL uint8_t data[1 + 32 + 4]; + static CONFIDENTIAL uint8_t I[32 + 32]; + static CONFIDENTIAL bignum256 a, b; + + if (i & 0x80000000) { // private derivation + data[0] = 0; + memcpy(data + 1, inout->private_key, 32); + } else { // public derivation + if (!inout->curve->params) { + return 0; + } + hdnode_fill_public_key(inout); + memcpy(data, inout->public_key, 33); + } + write_be(data + 33, i); + + bn_read_be(inout->private_key, &a); + + static CONFIDENTIAL HMAC_SHA512_CTX ctx; + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, sizeof(data)); + hmac_sha512_Final(&ctx, I); + + if (inout->curve->params) { + while (true) { + bool failed = false; + bn_read_be(I, &b); + if (!bn_is_less(&b, &inout->curve->params->order)) { // >= order + failed = true; + } else { + bn_add(&b, &a); + bn_mod(&b, &inout->curve->params->order); + if (bn_is_zero(&b)) { + failed = true; + } + } + + if (!failed) { + bn_write_be(&b, inout->private_key); + break; + } + + data[0] = 1; + memcpy(data + 1, I + 32, 32); + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, sizeof(data)); + hmac_sha512_Final(&ctx, I); + } + } else { + memcpy(inout->private_key, I, 32); + } + + memcpy(inout->chain_code, I + 32, 32); + inout->depth++; + inout->child_num = i; + memzero(inout->public_key, sizeof(inout->public_key)); + + // making sure to wipe our memory + memzero(&a, sizeof(a)); + memzero(&b, sizeof(b)); + memzero(I, sizeof(I)); + memzero(data, sizeof(data)); + return 1; } #if USE_CARDANO -static void scalar_multiply8(const uint8_t *src, int bytes, uint8_t *dst) -{ - uint8_t prev_acc = 0; - for (int i = 0; i < bytes; i++) { - dst[i] = (src[i] << 3) + (prev_acc & 0x7); - prev_acc = src[i] >> 5; - } - dst[bytes] = src[bytes - 1] >> 5; +static void scalar_multiply8(const uint8_t *src, int bytes, uint8_t *dst) { + uint8_t prev_acc = 0; + for (int i = 0; i < bytes; i++) { + dst[i] = (src[i] << 3) + (prev_acc & 0x7); + prev_acc = src[i] >> 5; + } + dst[bytes] = src[bytes - 1] >> 5; } -static void scalar_add_256bits(const uint8_t *src1, const uint8_t *src2, uint8_t *dst) -{ - uint16_t r = 0; - for (int i = 0; i < 32; i++) { - r = r + (uint16_t)src1[i] + (uint16_t)src2[i]; - dst[i] = r & 0xff; - r >>= 8; - } +static void scalar_add_256bits(const uint8_t *src1, const uint8_t *src2, + uint8_t *dst) { + uint16_t r = 0; + for (int i = 0; i < 32; i++) { + r = r + (uint16_t)src1[i] + (uint16_t)src2[i]; + dst[i] = r & 0xff; + r >>= 8; + } } -int hdnode_private_ckd_cardano(HDNode *inout, uint32_t index) -{ - // 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 (index & 0x80000000) { - keysize = 64; - } - - static CONFIDENTIAL uint8_t data[1 + 64 + 4]; - static CONFIDENTIAL uint8_t z[32 + 32]; - static CONFIDENTIAL uint8_t priv_key[64]; - static CONFIDENTIAL uint8_t res_key[64]; - - write_le(data + keysize + 1, index); - - memcpy(priv_key, inout->private_key, 32); - memcpy(priv_key + 32, inout->private_key_extension, 32); - - if (keysize == 64) { // private derivation - data[0] = 0; - memcpy(data + 1, inout->private_key, 32); - memcpy(data + 1 + 32, inout->private_key_extension, 32); - } else { // public derivation - hdnode_fill_public_key(inout); - data[0] = 2; - memcpy(data + 1, inout->public_key + 1, 32); - } - - static CONFIDENTIAL HMAC_SHA512_CTX ctx; - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, 1 + keysize + 4); - hmac_sha512_Final(&ctx, z); - - static CONFIDENTIAL uint8_t zl8[32]; - memzero(zl8, 32); - - /* get 8 * Zl */ - scalar_multiply8(z, 28, zl8); - /* Kl = 8*Zl + parent(K)l */ - scalar_add_256bits(zl8, priv_key, res_key); - - /* Kr = Zr + parent(K)r */ - scalar_add_256bits(z + 32, priv_key + 32, res_key + 32); - - 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; - } - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, 1 + keysize + 4); - hmac_sha512_Final(&ctx, z); - - memcpy(inout->chain_code, z + 32, 32); - inout->depth++; - inout->child_num = index; - memzero(inout->public_key, sizeof(inout->public_key)); - - // making sure to wipe our memory - memzero(z, sizeof(z)); - memzero(data, sizeof(data)); - memzero(priv_key, sizeof(priv_key)); - memzero(res_key, sizeof(res_key)); - return 1; +int hdnode_private_ckd_cardano(HDNode *inout, uint32_t index) { + // 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 (index & 0x80000000) { + keysize = 64; + } + + static CONFIDENTIAL uint8_t data[1 + 64 + 4]; + static CONFIDENTIAL uint8_t z[32 + 32]; + static CONFIDENTIAL uint8_t priv_key[64]; + static CONFIDENTIAL uint8_t res_key[64]; + + write_le(data + keysize + 1, index); + + memcpy(priv_key, inout->private_key, 32); + memcpy(priv_key + 32, inout->private_key_extension, 32); + + if (keysize == 64) { // private derivation + data[0] = 0; + memcpy(data + 1, inout->private_key, 32); + memcpy(data + 1 + 32, inout->private_key_extension, 32); + } else { // public derivation + hdnode_fill_public_key(inout); + data[0] = 2; + memcpy(data + 1, inout->public_key + 1, 32); + } + + static CONFIDENTIAL HMAC_SHA512_CTX ctx; + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, 1 + keysize + 4); + hmac_sha512_Final(&ctx, z); + + static CONFIDENTIAL uint8_t zl8[32]; + memzero(zl8, 32); + + /* get 8 * Zl */ + scalar_multiply8(z, 28, zl8); + /* Kl = 8*Zl + parent(K)l */ + scalar_add_256bits(zl8, priv_key, res_key); + + /* Kr = Zr + parent(K)r */ + scalar_add_256bits(z + 32, priv_key + 32, res_key + 32); + + 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; + } + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, 1 + keysize + 4); + hmac_sha512_Final(&ctx, z); + + memcpy(inout->chain_code, z + 32, 32); + inout->depth++; + inout->child_num = index; + memzero(inout->public_key, sizeof(inout->public_key)); + + // making sure to wipe our memory + memzero(z, sizeof(z)); + memzero(data, sizeof(data)); + memzero(priv_key, sizeof(priv_key)); + memzero(res_key, sizeof(res_key)); + return 1; } -int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out) { - static CONFIDENTIAL uint8_t secret[96]; - pbkdf2_hmac_sha512(pass, pass_len, seed, seed_len, 4096, secret, 96); - - secret[0] &= 248; - secret[31] &= 31; - secret[31] |= 64; +int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, + const uint8_t *seed, int seed_len, HDNode *out) { + static CONFIDENTIAL uint8_t secret[96]; + pbkdf2_hmac_sha512(pass, pass_len, seed, seed_len, 4096, secret, 96); + + secret[0] &= 248; + secret[31] &= 31; + secret[31] |= 64; - memzero(out, sizeof(HDNode)); - out->depth = 0; - out->child_num = 0; - out->curve = get_curve_by_name(ED25519_CARDANO_NAME); + memzero(out, sizeof(HDNode)); + out->depth = 0; + out->child_num = 0; + out->curve = get_curve_by_name(ED25519_CARDANO_NAME); - memcpy(out->private_key, secret, 32); - memcpy(out->private_key_extension, secret + 32, 32); + memcpy(out->private_key, secret, 32); + memcpy(out->private_key_extension, secret + 32, 32); - out->public_key[0] = 0; - hdnode_fill_public_key(out); + out->public_key[0] = 0; + hdnode_fill_public_key(out); - memcpy(out->chain_code, secret + 64, 32); - memzero(secret, sizeof(secret)); + memcpy(out->chain_code, secret + 64, 32); + memzero(secret, sizeof(secret)); - return 1; + return 1; } #endif -int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code) { - uint8_t data[1 + 32 + 4]; - uint8_t I[32 + 32]; - bignum256 c; - - if (i & 0x80000000) { // private derivation - return 0; - } - - data[0] = 0x02 | (parent->y.val[0] & 0x01); - bn_write_be(&parent->x, data + 1); - write_be(data + 33, i); - - while (true) { - hmac_sha512(parent_chain_code, 32, data, sizeof(data), I); - bn_read_be(I, &c); - if (bn_is_less(&c, &curve->order)) { // < order - scalar_multiply(curve, &c, child); // b = c * G - point_add(curve, parent, child); // b = a + b - if (!point_is_infinity(child)) { - if (child_chain_code) { - memcpy(child_chain_code, I + 32, 32); - } - - // Wipe all stack data. - memzero(data, sizeof(data)); - memzero(I, sizeof(I)); - memzero(&c, sizeof(c)); - return 1; - } - } - - data[0] = 1; - memcpy(data + 1, I + 32, 32); - } +int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, + const uint8_t *parent_chain_code, uint32_t i, + curve_point *child, uint8_t *child_chain_code) { + uint8_t data[1 + 32 + 4]; + uint8_t I[32 + 32]; + bignum256 c; + + if (i & 0x80000000) { // private derivation + return 0; + } + + data[0] = 0x02 | (parent->y.val[0] & 0x01); + bn_write_be(&parent->x, data + 1); + write_be(data + 33, i); + + while (true) { + hmac_sha512(parent_chain_code, 32, data, sizeof(data), I); + bn_read_be(I, &c); + if (bn_is_less(&c, &curve->order)) { // < order + scalar_multiply(curve, &c, child); // b = c * G + point_add(curve, parent, child); // b = a + b + if (!point_is_infinity(child)) { + if (child_chain_code) { + memcpy(child_chain_code, I + 32, 32); + } + + // Wipe all stack data. + memzero(data, sizeof(data)); + memzero(I, sizeof(I)); + memzero(&c, sizeof(c)); + return 1; + } + } + + data[0] = 1; + memcpy(data + 1, I + 32, 32); + } } -int hdnode_public_ckd(HDNode *inout, uint32_t i) -{ - curve_point parent, child; - - if (!ecdsa_read_pubkey(inout->curve->params, inout->public_key, &parent)) { - return 0; - } - if (!hdnode_public_ckd_cp(inout->curve->params, &parent, inout->chain_code, i, &child, inout->chain_code)) { - return 0; - } - memzero(inout->private_key, 32); - inout->depth++; - inout->child_num = i; - inout->public_key[0] = 0x02 | (child.y.val[0] & 0x01); - bn_write_be(&child.x, inout->public_key + 1); - - // Wipe all stack data. - memzero(&parent, sizeof(parent)); - memzero(&child, sizeof(child)); - - return 1; +int hdnode_public_ckd(HDNode *inout, uint32_t i) { + curve_point parent, child; + + if (!ecdsa_read_pubkey(inout->curve->params, inout->public_key, &parent)) { + return 0; + } + if (!hdnode_public_ckd_cp(inout->curve->params, &parent, inout->chain_code, i, + &child, inout->chain_code)) { + return 0; + } + memzero(inout->private_key, 32); + inout->depth++; + inout->child_num = i; + inout->public_key[0] = 0x02 | (child.y.val[0] & 0x01); + bn_write_be(&child.x, inout->public_key + 1); + + // Wipe all stack data. + memzero(&parent, sizeof(parent)); + memzero(&child, sizeof(child)); + + return 1; } -void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat) -{ - uint8_t child_pubkey[33]; - curve_point b; - - hdnode_public_ckd_cp(&secp256k1, pub, chain_code, i, &b, NULL); - child_pubkey[0] = 0x02 | (b.y.val[0] & 0x01); - bn_write_be(&b.x, child_pubkey + 1); - - switch (addrformat) { - case 1: // Segwit-in-P2SH - ecdsa_get_address_segwit_p2sh(child_pubkey, version, hasher_pubkey, hasher_base58, addr, addrsize); - break; - default: // normal address - ecdsa_get_address(child_pubkey, version, hasher_pubkey, hasher_base58, addr, addrsize); - break; - } +void hdnode_public_ckd_address_optimized(const curve_point *pub, + const uint8_t *chain_code, uint32_t i, + uint32_t version, + HasherType hasher_pubkey, + HasherType hasher_base58, char *addr, + int addrsize, int addrformat) { + uint8_t child_pubkey[33]; + curve_point b; + + hdnode_public_ckd_cp(&secp256k1, pub, chain_code, i, &b, NULL); + child_pubkey[0] = 0x02 | (b.y.val[0] & 0x01); + bn_write_be(&b.x, child_pubkey + 1); + + switch (addrformat) { + case 1: // Segwit-in-P2SH + ecdsa_get_address_segwit_p2sh(child_pubkey, version, hasher_pubkey, + hasher_base58, addr, addrsize); + break; + default: // normal address + ecdsa_get_address(child_pubkey, version, hasher_pubkey, hasher_base58, + addr, addrsize); + break; + } } #if USE_BIP32_CACHE @@ -465,385 +476,412 @@ static CONFIDENTIAL HDNode private_ckd_cache_root; static int private_ckd_cache_index = 0; static CONFIDENTIAL struct { - bool set; - size_t depth; - uint32_t i[BIP32_CACHE_MAXDEPTH]; - HDNode node; + bool set; + size_t depth; + uint32_t i[BIP32_CACHE_MAXDEPTH]; + HDNode node; } private_ckd_cache[BIP32_CACHE_SIZE]; -int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint) -{ - if (i_count == 0) { - // no way how to compute parent fingerprint - return 1; - } - if (i_count == 1) { - if (fingerprint) { - *fingerprint = hdnode_fingerprint(inout); - } - if (hdnode_private_ckd(inout, i[0]) == 0) return 0; - return 1; - } - - bool found = false; - // if root is not set or not the same - if (!private_ckd_cache_root_set || memcmp(&private_ckd_cache_root, inout, sizeof(HDNode)) != 0) { - // clear the cache - private_ckd_cache_index = 0; - memzero(private_ckd_cache, sizeof(private_ckd_cache)); - // setup new root - memcpy(&private_ckd_cache_root, inout, sizeof(HDNode)); - private_ckd_cache_root_set = true; - } else { - // try to find parent - int j; - for (j = 0; j < BIP32_CACHE_SIZE; j++) { - if (private_ckd_cache[j].set && - private_ckd_cache[j].depth == i_count - 1 && - memcmp(private_ckd_cache[j].i, i, (i_count - 1) * sizeof(uint32_t)) == 0 && - private_ckd_cache[j].node.curve == inout->curve) { - memcpy(inout, &(private_ckd_cache[j].node), sizeof(HDNode)); - found = true; - break; - } - } - } - - // else derive parent - if (!found) { - size_t k; - for (k = 0; k < i_count - 1; k++) { - if (hdnode_private_ckd(inout, i[k]) == 0) return 0; - } - // and save it - memzero(&(private_ckd_cache[private_ckd_cache_index]), sizeof(private_ckd_cache[private_ckd_cache_index])); - private_ckd_cache[private_ckd_cache_index].set = true; - private_ckd_cache[private_ckd_cache_index].depth = i_count - 1; - memcpy(private_ckd_cache[private_ckd_cache_index].i, i, (i_count - 1) * sizeof(uint32_t)); - memcpy(&(private_ckd_cache[private_ckd_cache_index].node), inout, sizeof(HDNode)); - private_ckd_cache_index = (private_ckd_cache_index + 1) % BIP32_CACHE_SIZE; - } - - if (fingerprint) { - *fingerprint = hdnode_fingerprint(inout); - } - if (hdnode_private_ckd(inout, i[i_count - 1]) == 0) return 0; - - return 1; +int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, + uint32_t *fingerprint) { + if (i_count == 0) { + // no way how to compute parent fingerprint + return 1; + } + if (i_count == 1) { + if (fingerprint) { + *fingerprint = hdnode_fingerprint(inout); + } + if (hdnode_private_ckd(inout, i[0]) == 0) return 0; + return 1; + } + + bool found = false; + // if root is not set or not the same + if (!private_ckd_cache_root_set || + memcmp(&private_ckd_cache_root, inout, sizeof(HDNode)) != 0) { + // clear the cache + private_ckd_cache_index = 0; + memzero(private_ckd_cache, sizeof(private_ckd_cache)); + // setup new root + memcpy(&private_ckd_cache_root, inout, sizeof(HDNode)); + private_ckd_cache_root_set = true; + } else { + // try to find parent + int j; + for (j = 0; j < BIP32_CACHE_SIZE; j++) { + if (private_ckd_cache[j].set && + private_ckd_cache[j].depth == i_count - 1 && + memcmp(private_ckd_cache[j].i, i, (i_count - 1) * sizeof(uint32_t)) == + 0 && + private_ckd_cache[j].node.curve == inout->curve) { + memcpy(inout, &(private_ckd_cache[j].node), sizeof(HDNode)); + found = true; + break; + } + } + } + + // else derive parent + if (!found) { + size_t k; + for (k = 0; k < i_count - 1; k++) { + if (hdnode_private_ckd(inout, i[k]) == 0) return 0; + } + // and save it + memzero(&(private_ckd_cache[private_ckd_cache_index]), + sizeof(private_ckd_cache[private_ckd_cache_index])); + private_ckd_cache[private_ckd_cache_index].set = true; + private_ckd_cache[private_ckd_cache_index].depth = i_count - 1; + memcpy(private_ckd_cache[private_ckd_cache_index].i, i, + (i_count - 1) * sizeof(uint32_t)); + memcpy(&(private_ckd_cache[private_ckd_cache_index].node), inout, + sizeof(HDNode)); + private_ckd_cache_index = (private_ckd_cache_index + 1) % BIP32_CACHE_SIZE; + } + + if (fingerprint) { + *fingerprint = hdnode_fingerprint(inout); + } + if (hdnode_private_ckd(inout, i[i_count - 1]) == 0) return 0; + + return 1; } #endif -void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw) -{ - hdnode_fill_public_key(node); - ecdsa_get_address_raw(node->public_key, version, node->curve->hasher_pubkey, addr_raw); +void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw) { + hdnode_fill_public_key(node); + ecdsa_get_address_raw(node->public_key, version, node->curve->hasher_pubkey, + addr_raw); } -void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize) -{ - hdnode_fill_public_key(node); - ecdsa_get_address(node->public_key, version, node->curve->hasher_pubkey, node->curve->hasher_base58, addr, addrsize); +void hdnode_get_address(HDNode *node, uint32_t version, char *addr, + int addrsize) { + hdnode_fill_public_key(node); + ecdsa_get_address(node->public_key, version, node->curve->hasher_pubkey, + node->curve->hasher_base58, addr, addrsize); } -void hdnode_fill_public_key(HDNode *node) -{ - if (node->public_key[0] != 0) - return; +void hdnode_fill_public_key(HDNode *node) { + if (node->public_key[0] != 0) return; #if USE_BIP32_25519_CURVES - if (node->curve->params) { - ecdsa_get_public_key33(node->curve->params, node->private_key, node->public_key); - } else { - node->public_key[0] = 1; - if (node->curve == &ed25519_info) { - ed25519_publickey(node->private_key, node->public_key + 1); - } else if (node->curve == &ed25519_sha3_info) { - ed25519_publickey_sha3(node->private_key, node->public_key + 1); + if (node->curve->params) { + ecdsa_get_public_key33(node->curve->params, node->private_key, + node->public_key); + } else { + node->public_key[0] = 1; + if (node->curve == &ed25519_info) { + ed25519_publickey(node->private_key, node->public_key + 1); + } else if (node->curve == &ed25519_sha3_info) { + ed25519_publickey_sha3(node->private_key, node->public_key + 1); #if USE_KECCAK - } else if (node->curve == &ed25519_keccak_info) { - ed25519_publickey_keccak(node->private_key, node->public_key + 1); + } else if (node->curve == &ed25519_keccak_info) { + ed25519_publickey_keccak(node->private_key, node->public_key + 1); #endif - } else if (node->curve == &curve25519_info) { - curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key); + } else if (node->curve == &curve25519_info) { + curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key); #if USE_CARDANO - } else if (node->curve == &ed25519_cardano_info) { - ed25519_publickey_ext(node->private_key, node->private_key_extension, node->public_key + 1); + } else if (node->curve == &ed25519_cardano_info) { + ed25519_publickey_ext(node->private_key, node->private_key_extension, + node->public_key + 1); #endif - } - } + } + } #else - ecdsa_get_public_key33(node->curve->params, node->private_key, node->public_key); + ecdsa_get_public_key33(node->curve->params, node->private_key, + node->public_key); #endif } #if USE_ETHEREUM -int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash) -{ - uint8_t buf[65]; - SHA3_CTX ctx; +int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash) { + uint8_t buf[65]; + SHA3_CTX ctx; - /* get uncompressed public key */ - ecdsa_get_public_key65(node->curve->params, node->private_key, buf); + /* get uncompressed public key */ + ecdsa_get_public_key65(node->curve->params, node->private_key, buf); - /* compute sha3 of x and y coordinate without 04 prefix */ - sha3_256_Init(&ctx); - sha3_Update(&ctx, buf + 1, 64); - keccak_Final(&ctx, buf); + /* compute sha3 of x and y coordinate without 04 prefix */ + sha3_256_Init(&ctx); + sha3_Update(&ctx, buf + 1, 64); + keccak_Final(&ctx, buf); - /* result are the least significant 160 bits */ - memcpy(pubkeyhash, buf + 12, 20); + /* result are the least significant 160 bits */ + memcpy(pubkeyhash, buf + 12, 20); - return 1; + return 1; } #endif #if USE_NEM int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address) { - if (node->curve != &ed25519_keccak_info) { - return 0; - } + if (node->curve != &ed25519_keccak_info) { + return 0; + } - hdnode_fill_public_key(node); - return nem_get_address(&node->public_key[1], version, address); + hdnode_fill_public_key(node); + return nem_get_address(&node->public_key[1], version, address); } -int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key) { - if (node->curve != &ed25519_keccak_info) { - return 0; - } +int hdnode_get_nem_shared_key(const HDNode *node, + const ed25519_public_key peer_public_key, + const uint8_t *salt, ed25519_public_key mul, + uint8_t *shared_key) { + if (node->curve != &ed25519_keccak_info) { + return 0; + } - // sizeof(ed25519_public_key) == SHA3_256_DIGEST_LENGTH - if (mul == NULL) mul = shared_key; + // sizeof(ed25519_public_key) == SHA3_256_DIGEST_LENGTH + if (mul == NULL) mul = shared_key; - if (ed25519_scalarmult_keccak(mul, node->private_key, peer_public_key)) { - return 0; - } + if (ed25519_scalarmult_keccak(mul, node->private_key, peer_public_key)) { + return 0; + } - for (size_t i = 0; i < 32; i++) { - shared_key[i] = mul[i] ^ salt[i]; - } + for (size_t i = 0; i < 32; i++) { + shared_key[i] = mul[i] ^ salt[i]; + } - keccak_256(shared_key, 32, shared_key); - return 1; + keccak_256(shared_key, 32, shared_key); + return 1; } -int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv_immut, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer) { - uint8_t last_block[AES_BLOCK_SIZE]; - uint8_t remainder = size % AES_BLOCK_SIZE; +int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, + const uint8_t *iv_immut, const uint8_t *salt, + const uint8_t *payload, size_t size, uint8_t *buffer) { + uint8_t last_block[AES_BLOCK_SIZE]; + uint8_t remainder = size % AES_BLOCK_SIZE; - // Round down to last whole block - size -= remainder; - // Copy old last block - memcpy(last_block, &payload[size], remainder); - // Pad new last block with number of missing bytes - memset(&last_block[remainder], AES_BLOCK_SIZE - remainder, AES_BLOCK_SIZE - remainder); + // Round down to last whole block + size -= remainder; + // Copy old last block + memcpy(last_block, &payload[size], remainder); + // Pad new last block with number of missing bytes + memset(&last_block[remainder], AES_BLOCK_SIZE - remainder, + AES_BLOCK_SIZE - remainder); - // the IV gets mutated, so we make a copy not to touch the original - uint8_t iv[AES_BLOCK_SIZE]; - memcpy(iv, iv_immut, AES_BLOCK_SIZE); + // the IV gets mutated, so we make a copy not to touch the original + uint8_t iv[AES_BLOCK_SIZE]; + memcpy(iv, iv_immut, AES_BLOCK_SIZE); - uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; - if (!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) { - return 0; - } + uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; + if (!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) { + return 0; + } - aes_encrypt_ctx ctx; + aes_encrypt_ctx ctx; - int ret = aes_encrypt_key256(shared_key, &ctx); - memzero(shared_key, sizeof(shared_key)); + int ret = aes_encrypt_key256(shared_key, &ctx); + memzero(shared_key, sizeof(shared_key)); - if (ret != EXIT_SUCCESS) { - return 0; - } + if (ret != EXIT_SUCCESS) { + return 0; + } - if (aes_cbc_encrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) { - return 0; - } + if (aes_cbc_encrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) { + return 0; + } - if (aes_cbc_encrypt(last_block, &buffer[size], sizeof(last_block), iv, &ctx) != EXIT_SUCCESS) { - return 0; - } + if (aes_cbc_encrypt(last_block, &buffer[size], sizeof(last_block), iv, + &ctx) != EXIT_SUCCESS) { + return 0; + } - return 1; + return 1; } -int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer) { - uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; +int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, + uint8_t *iv, const uint8_t *salt, const uint8_t *payload, + size_t size, uint8_t *buffer) { + uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; - if (!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) { - return 0; - } + if (!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) { + return 0; + } - aes_decrypt_ctx ctx; + aes_decrypt_ctx ctx; - int ret = aes_decrypt_key256(shared_key, &ctx); - memzero(shared_key, sizeof(shared_key)); + int ret = aes_decrypt_key256(shared_key, &ctx); + memzero(shared_key, sizeof(shared_key)); - if (ret != EXIT_SUCCESS) { - return 0; - } + if (ret != EXIT_SUCCESS) { + return 0; + } - if (aes_cbc_decrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) { - return 0; - } + if (aes_cbc_decrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) { + return 0; + } - return 1; + return 1; } #endif // msg is a data to be signed // msg_len is the message length -int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) -{ - if (node->curve->params) { - return ecdsa_sign(node->curve->params, hasher_sign, node->private_key, msg, msg_len, sig, pby, is_canonical); - } else if (node->curve == &curve25519_info) { - return 1; // signatures are not supported - } else { - hdnode_fill_public_key(node); - if (node->curve == &ed25519_info) { - ed25519_sign(msg, msg_len, node->private_key, node->public_key + 1, sig); - } else if (node->curve == &ed25519_sha3_info) { - ed25519_sign_sha3(msg, msg_len, node->private_key, node->public_key + 1, sig); +int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, + HasherType hasher_sign, uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])) { + if (node->curve->params) { + return ecdsa_sign(node->curve->params, hasher_sign, node->private_key, msg, + msg_len, sig, pby, is_canonical); + } else if (node->curve == &curve25519_info) { + return 1; // signatures are not supported + } else { + hdnode_fill_public_key(node); + if (node->curve == &ed25519_info) { + ed25519_sign(msg, msg_len, node->private_key, node->public_key + 1, sig); + } else if (node->curve == &ed25519_sha3_info) { + ed25519_sign_sha3(msg, msg_len, node->private_key, node->public_key + 1, + sig); #if USE_KECCAK - } else if (node->curve == &ed25519_keccak_info) { - ed25519_sign_keccak(msg, msg_len, node->private_key, node->public_key + 1, sig); + } else if (node->curve == &ed25519_keccak_info) { + ed25519_sign_keccak(msg, msg_len, node->private_key, node->public_key + 1, + sig); #endif - } - return 0; - } + } + return 0; + } } -int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) -{ - if (node->curve->params) { - return ecdsa_sign_digest(node->curve->params, node->private_key, digest, sig, pby, is_canonical); - } else if (node->curve == &curve25519_info) { - return 1; // signatures are not supported - } else { - return hdnode_sign(node, digest, 32, 0, sig, pby, is_canonical); - } +int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, + uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])) { + if (node->curve->params) { + return ecdsa_sign_digest(node->curve->params, node->private_key, digest, + sig, pby, is_canonical); + } else if (node->curve == &curve25519_info) { + return 1; // signatures are not supported + } else { + return hdnode_sign(node, digest, 32, 0, sig, pby, is_canonical); + } } -int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size) -{ - // Use elliptic curve Diffie-Helman to compute shared session key - if (node->curve->params) { - if (ecdh_multiply(node->curve->params, node->private_key, peer_public_key, session_key) != 0) { - return 1; - } - *result_size = 65; - return 0; - } else if (node->curve == &curve25519_info) { - session_key[0] = 0x04; - if (peer_public_key[0] != 0x40) { - return 1; // Curve25519 public key should start with 0x40 byte. - } - curve25519_scalarmult(session_key + 1, node->private_key, peer_public_key + 1); - *result_size = 33; - return 0; - } else { - *result_size = 0; - return 1; // ECDH is not supported - } +int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, + uint8_t *session_key, int *result_size) { + // Use elliptic curve Diffie-Helman to compute shared session key + if (node->curve->params) { + if (ecdh_multiply(node->curve->params, node->private_key, peer_public_key, + session_key) != 0) { + return 1; + } + *result_size = 65; + return 0; + } else if (node->curve == &curve25519_info) { + session_key[0] = 0x04; + if (peer_public_key[0] != 0x40) { + return 1; // Curve25519 public key should start with 0x40 byte. + } + curve25519_scalarmult(session_key + 1, node->private_key, + peer_public_key + 1); + *result_size = 33; + return 0; + } else { + *result_size = 0; + return 1; // ECDH is not supported + } } -static int hdnode_serialize(const HDNode *node, uint32_t fingerprint, uint32_t version, char use_public, char *str, int strsize) -{ - uint8_t node_data[78]; - write_be(node_data, version); - node_data[4] = node->depth; - write_be(node_data + 5, fingerprint); - write_be(node_data + 9, node->child_num); - memcpy(node_data + 13, node->chain_code, 32); - if (use_public) { - memcpy(node_data + 45, node->public_key, 33); - } else { - node_data[45] = 0; - memcpy(node_data + 46, node->private_key, 32); - } - int ret = base58_encode_check(node_data, sizeof(node_data), node->curve->hasher_base58, str, strsize); - memzero(node_data, sizeof(node_data)); - return ret; +static int hdnode_serialize(const HDNode *node, uint32_t fingerprint, + uint32_t version, char use_public, char *str, + int strsize) { + uint8_t node_data[78]; + write_be(node_data, version); + node_data[4] = node->depth; + write_be(node_data + 5, fingerprint); + write_be(node_data + 9, node->child_num); + memcpy(node_data + 13, node->chain_code, 32); + if (use_public) { + memcpy(node_data + 45, node->public_key, 33); + } else { + node_data[45] = 0; + memcpy(node_data + 46, node->private_key, 32); + } + int ret = base58_encode_check(node_data, sizeof(node_data), + node->curve->hasher_base58, str, strsize); + memzero(node_data, sizeof(node_data)); + return ret; } -int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize) -{ - return hdnode_serialize(node, fingerprint, version, 1, str, strsize); +int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, + uint32_t version, char *str, int strsize) { + return hdnode_serialize(node, fingerprint, version, 1, str, strsize); } -int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize) -{ - return hdnode_serialize(node, fingerprint, version, 0, str, strsize); +int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, + uint32_t version, char *str, int strsize) { + return hdnode_serialize(node, fingerprint, version, 0, str, strsize); } // check for validity of curve point in case of public data not performed -int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint) -{ - uint8_t node_data[78]; - memzero(node, sizeof(HDNode)); - node->curve = get_curve_by_name(curve); - if (base58_decode_check(str, node->curve->hasher_base58, node_data, sizeof(node_data)) != sizeof(node_data)) { - return -1; - } - uint32_t version = read_be(node_data); - if (version == version_public) { - memzero(node->private_key, sizeof(node->private_key)); - memcpy(node->public_key, node_data + 45, 33); - } else if (version == version_private) { // private node - if (node_data[45]) { // invalid data - return -2; - } - memcpy(node->private_key, node_data + 46, 32); - memzero(node->public_key, sizeof(node->public_key)); - } else { - return -3; // invalid version - } - node->depth = node_data[4]; - if (fingerprint) { - *fingerprint = read_be(node_data + 5); - } - node->child_num = read_be(node_data + 9); - memcpy(node->chain_code, node_data + 13, 32); - return 0; +int hdnode_deserialize(const char *str, uint32_t version_public, + uint32_t version_private, const char *curve, + HDNode *node, uint32_t *fingerprint) { + uint8_t node_data[78]; + memzero(node, sizeof(HDNode)); + node->curve = get_curve_by_name(curve); + if (base58_decode_check(str, node->curve->hasher_base58, node_data, + sizeof(node_data)) != sizeof(node_data)) { + return -1; + } + uint32_t version = read_be(node_data); + if (version == version_public) { + memzero(node->private_key, sizeof(node->private_key)); + memcpy(node->public_key, node_data + 45, 33); + } else if (version == version_private) { // private node + if (node_data[45]) { // invalid data + return -2; + } + memcpy(node->private_key, node_data + 46, 32); + memzero(node->public_key, sizeof(node->public_key)); + } else { + return -3; // invalid version + } + node->depth = node_data[4]; + if (fingerprint) { + *fingerprint = read_be(node_data + 5); + } + node->child_num = read_be(node_data + 9); + memcpy(node->chain_code, node_data + 13, 32); + return 0; } const curve_info *get_curve_by_name(const char *curve_name) { - if (curve_name == 0) { - return 0; - } - if (strcmp(curve_name, SECP256K1_NAME) == 0) { - return &secp256k1_info; - } - if (strcmp(curve_name, SECP256K1_DECRED_NAME) == 0) { - return &secp256k1_decred_info; - } - if (strcmp(curve_name, SECP256K1_GROESTL_NAME) == 0) { - return &secp256k1_groestl_info; - } - if (strcmp(curve_name, SECP256K1_SMART_NAME) == 0) { - return &secp256k1_smart_info; - } - if (strcmp(curve_name, NIST256P1_NAME) == 0) { - return &nist256p1_info; - } - if (strcmp(curve_name, ED25519_NAME) == 0) { - return &ed25519_info; - } - if (strcmp(curve_name, ED25519_CARDANO_NAME) == 0) { - return &ed25519_cardano_info; - } - if (strcmp(curve_name, ED25519_SHA3_NAME) == 0) { - return &ed25519_sha3_info; - } + if (curve_name == 0) { + return 0; + } + if (strcmp(curve_name, SECP256K1_NAME) == 0) { + return &secp256k1_info; + } + if (strcmp(curve_name, SECP256K1_DECRED_NAME) == 0) { + return &secp256k1_decred_info; + } + if (strcmp(curve_name, SECP256K1_GROESTL_NAME) == 0) { + return &secp256k1_groestl_info; + } + if (strcmp(curve_name, SECP256K1_SMART_NAME) == 0) { + return &secp256k1_smart_info; + } + if (strcmp(curve_name, NIST256P1_NAME) == 0) { + return &nist256p1_info; + } + if (strcmp(curve_name, ED25519_NAME) == 0) { + return &ed25519_info; + } + if (strcmp(curve_name, ED25519_CARDANO_NAME) == 0) { + return &ed25519_cardano_info; + } + if (strcmp(curve_name, ED25519_SHA3_NAME) == 0) { + return &ed25519_sha3_info; + } #if USE_KECCAK - if (strcmp(curve_name, ED25519_KECCAK_NAME) == 0) { - return &ed25519_keccak_info; - } + if (strcmp(curve_name, ED25519_KECCAK_NAME) == 0) { + return &ed25519_keccak_info; + } #endif - if (strcmp(curve_name, CURVE25519_NAME) == 0) { - return &curve25519_info; - } - return 0; + if (strcmp(curve_name, CURVE25519_NAME) == 0) { + return &curve25519_info; + } + return 0; } diff --git a/bip32.h b/bip32.h index c0a04b5f8..995a7aea9 100644 --- a/bip32.h +++ b/bip32.h @@ -24,58 +24,73 @@ #ifndef __BIP32_H__ #define __BIP32_H__ +#include #include #include -#include #include "ecdsa.h" #include "ed25519-donna/ed25519.h" #include "options.h" typedef struct { - const char *bip32_name; // string for generating BIP32 xprv from seed - const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519 + const char *bip32_name; // string for generating BIP32 xprv from seed + const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519 - HasherType hasher_base58; - HasherType hasher_sign; - HasherType hasher_pubkey; - HasherType hasher_script; + HasherType hasher_base58; + HasherType hasher_sign; + HasherType hasher_pubkey; + HasherType hasher_script; } curve_info; typedef struct { - uint32_t depth; - uint32_t child_num; - uint8_t chain_code[32]; + uint32_t depth; + uint32_t child_num; + uint8_t chain_code[32]; - uint8_t private_key[32]; - uint8_t private_key_extension[32]; + uint8_t private_key[32]; + uint8_t private_key_extension[32]; - uint8_t public_key[33]; - const curve_info *curve; + uint8_t public_key[33]; + const curve_info *curve; } HDNode; -int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out); +int hdnode_from_xpub(uint32_t depth, uint32_t child_num, + const uint8_t *chain_code, const uint8_t *public_key, + const char *curve, HDNode *out); -int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out); +int hdnode_from_xprv(uint32_t depth, uint32_t child_num, + const uint8_t *chain_code, const uint8_t *private_key, + const char *curve, HDNode *out); -int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out); +int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, + HDNode *out); -#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000)) +#define hdnode_private_ckd_prime(X, I) \ + hdnode_private_ckd((X), ((I) | 0x80000000)) int hdnode_private_ckd(HDNode *inout, uint32_t i); #if USE_CARDANO int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); -int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out); +int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, + const uint8_t *seed, int seed_len, HDNode *out); #endif -int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code); +int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, + const uint8_t *parent_chain_code, uint32_t i, + curve_point *child, uint8_t *child_chain_code); int hdnode_public_ckd(HDNode *inout, uint32_t i); -void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat); +void hdnode_public_ckd_address_optimized(const curve_point *pub, + const uint8_t *chain_code, uint32_t i, + uint32_t version, + HasherType hasher_pubkey, + HasherType hasher_base58, char *addr, + int addrsize, int addrformat); #if USE_BIP32_CACHE -int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint); +int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, + uint32_t *fingerprint); #endif uint32_t hdnode_fingerprint(HDNode *node); @@ -88,24 +103,41 @@ int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash); #if USE_NEM int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address); -int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key); -int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer); -int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer); +int hdnode_get_nem_shared_key(const HDNode *node, + const ed25519_public_key peer_public_key, + const uint8_t *salt, ed25519_public_key mul, + uint8_t *shared_key); +int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, + const uint8_t *iv, const uint8_t *salt, + const uint8_t *payload, size_t size, uint8_t *buffer); +int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, + uint8_t *iv, const uint8_t *salt, const uint8_t *payload, + size_t size, uint8_t *buffer); #endif -int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); -int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, + HasherType hasher_sign, uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, + uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])); -int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size); +int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, + uint8_t *session_key, int *result_size); -int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); +int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, + uint32_t version, char *str, int strsize); -int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); +int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, + uint32_t version, char *str, int strsize); -int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint); +int hdnode_deserialize(const char *str, uint32_t version_public, + uint32_t version_private, const char *curve, + HDNode *node, uint32_t *fingerprint); void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw); -void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize); +void hdnode_get_address(HDNode *node, uint32_t version, char *addr, + int addrsize); const curve_info *get_curve_by_name(const char *curve_name); diff --git a/bip39.c b/bip39.c index 2d0a9640c..6252f7126 100644 --- a/bip39.c +++ b/bip39.c @@ -21,216 +21,211 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include #include +#include #include "bip39.h" +#include "bip39_english.h" #include "hmac.h" +#include "memzero.h" +#include "options.h" +#include "pbkdf2.h" #include "rand.h" #include "sha2.h" -#include "pbkdf2.h" -#include "bip39_english.h" -#include "options.h" -#include "memzero.h" #if USE_BIP39_CACHE static int bip39_cache_index = 0; static CONFIDENTIAL struct { - bool set; - char mnemonic[256]; - char passphrase[64]; - uint8_t seed[512 / 8]; + bool set; + char mnemonic[256]; + char passphrase[64]; + uint8_t seed[512 / 8]; } bip39_cache[BIP39_CACHE_SIZE]; #endif -const char *mnemonic_generate(int strength) -{ - if (strength % 32 || strength < 128 || strength > 256) { - return 0; - } - uint8_t data[32]; - random_buffer(data, 32); - const char *r = mnemonic_from_data(data, strength / 8); - memzero(data, sizeof(data)); - return r; +const char *mnemonic_generate(int strength) { + if (strength % 32 || strength < 128 || strength > 256) { + return 0; + } + uint8_t data[32]; + random_buffer(data, 32); + const char *r = mnemonic_from_data(data, strength / 8); + memzero(data, sizeof(data)); + return r; } static CONFIDENTIAL char mnemo[24 * 10]; -const char *mnemonic_from_data(const uint8_t *data, int len) -{ - if (len % 4 || len < 16 || len > 32) { - return 0; - } - - uint8_t bits[32 + 1]; - - sha256_Raw(data, len, bits); - // checksum - bits[len] = bits[0]; - // data - memcpy(bits, data, len); - - int mlen = len * 3 / 4; - - int i, j, idx; - char *p = mnemo; - for (i = 0; i < mlen; i++) { - idx = 0; - for (j = 0; j < 11; j++) { - idx <<= 1; - idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0; - } - strcpy(p, wordlist[idx]); - p += strlen(wordlist[idx]); - *p = (i < mlen - 1) ? ' ' : 0; - p++; - } - memzero(bits, sizeof(bits)); - - return mnemo; +const char *mnemonic_from_data(const uint8_t *data, int len) { + if (len % 4 || len < 16 || len > 32) { + return 0; + } + + uint8_t bits[32 + 1]; + + sha256_Raw(data, len, bits); + // checksum + bits[len] = bits[0]; + // data + memcpy(bits, data, len); + + int mlen = len * 3 / 4; + + int i, j, idx; + char *p = mnemo; + for (i = 0; i < mlen; i++) { + idx = 0; + for (j = 0; j < 11; j++) { + idx <<= 1; + idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0; + } + strcpy(p, wordlist[idx]); + p += strlen(wordlist[idx]); + *p = (i < mlen - 1) ? ' ' : 0; + p++; + } + memzero(bits, sizeof(bits)); + + return mnemo; } -void mnemonic_clear(void) -{ - memzero(mnemo, sizeof(mnemo)); +void mnemonic_clear(void) { memzero(mnemo, sizeof(mnemo)); } + +int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) { + if (!mnemonic) { + return 0; + } + + uint32_t 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 = 0; + uint8_t bits[32 + 1]; + + memzero(bits, sizeof(bits)); + i = 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) { + return 0; + } + memcpy(entropy, bits, sizeof(bits)); + return n * 11; } -int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) -{ - if (!mnemonic) { - return 0; - } - - uint32_t 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 = 0; - uint8_t bits[32 + 1]; - - memzero(bits, sizeof(bits)); - i = 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) { - return 0; - } - memcpy(entropy, bits, sizeof(bits)); - return n * 11; -} - -int mnemonic_check(const char *mnemonic) -{ - uint8_t bits[32 + 1]; - int seed_len = mnemonic_to_entropy(mnemonic, bits); - if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) { - return 0; - } - 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; +int mnemonic_check(const char *mnemonic) { + uint8_t bits[32 + 1]; + int seed_len = mnemonic_to_entropy(mnemonic, bits); + if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) { + return 0; + } + 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; } // passphrase must be at most 256 characters otherwise it would be truncated -void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)) -{ - int mnemoniclen = strlen(mnemonic); - int passphraselen = strnlen(passphrase, 256); +void mnemonic_to_seed(const char *mnemonic, const char *passphrase, + uint8_t seed[512 / 8], + void (*progress_callback)(uint32_t current, + uint32_t total)) { + int mnemoniclen = strlen(mnemonic); + int passphraselen = strnlen(passphrase, 256); #if USE_BIP39_CACHE - // check cache - if (mnemoniclen < 256 && passphraselen < 64) { - for (int i = 0; i < BIP39_CACHE_SIZE; i++) { - if (!bip39_cache[i].set) continue; - if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue; - if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue; - // found the correct entry - memcpy(seed, bip39_cache[i].seed, 512 / 8); - return; - } - } + // check cache + if (mnemoniclen < 256 && passphraselen < 64) { + for (int i = 0; i < BIP39_CACHE_SIZE; i++) { + if (!bip39_cache[i].set) continue; + if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue; + if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue; + // found the correct entry + memcpy(seed, bip39_cache[i].seed, 512 / 8); + return; + } + } #endif - uint8_t salt[8 + 256]; - memcpy(salt, "mnemonic", 8); - memcpy(salt + 8, passphrase, passphraselen); - static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx; - pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt, passphraselen + 8, 1); - if (progress_callback) { - progress_callback(0, BIP39_PBKDF2_ROUNDS); - } - for (int i = 0; i < 16; i++) { - pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16); - if (progress_callback) { - progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS); - } - } - pbkdf2_hmac_sha512_Final(&pctx, seed); - memzero(salt, sizeof(salt)); + uint8_t salt[8 + 256]; + memcpy(salt, "mnemonic", 8); + memcpy(salt + 8, passphrase, passphraselen); + static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx; + pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt, + passphraselen + 8, 1); + if (progress_callback) { + progress_callback(0, BIP39_PBKDF2_ROUNDS); + } + for (int i = 0; i < 16; i++) { + pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16); + if (progress_callback) { + progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, + BIP39_PBKDF2_ROUNDS); + } + } + pbkdf2_hmac_sha512_Final(&pctx, seed); + memzero(salt, sizeof(salt)); #if USE_BIP39_CACHE - // store to cache - if (mnemoniclen < 256 && passphraselen < 64) { - bip39_cache[bip39_cache_index].set = true; - strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic); - strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase); - memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8); - bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE; - } + // store to cache + if (mnemoniclen < 256 && passphraselen < 64) { + bip39_cache[bip39_cache_index].set = true; + strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic); + strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase); + memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8); + bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE; + } #endif } -const char * const *mnemonic_wordlist(void) -{ - return wordlist; -} +const char *const *mnemonic_wordlist(void) { return wordlist; } diff --git a/bip39.h b/bip39.h index ac76101d7..a2c3eb8c0 100644 --- a/bip39.h +++ b/bip39.h @@ -28,7 +28,7 @@ #define BIP39_PBKDF2_ROUNDS 2048 -const char *mnemonic_generate(int strength); // strength in bits +const char *mnemonic_generate(int strength); // strength in bits const char *mnemonic_from_data(const uint8_t *data, int len); void mnemonic_clear(void); @@ -37,8 +37,11 @@ int mnemonic_check(const char *mnemonic); int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy); // passphrase must be at most 256 characters otherwise it would be truncated -void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)); +void mnemonic_to_seed(const char *mnemonic, const char *passphrase, + uint8_t seed[512 / 8], + void (*progress_callback)(uint32_t current, + uint32_t total)); -const char * const *mnemonic_wordlist(void); +const char *const *mnemonic_wordlist(void); #endif diff --git a/bip39_english.h b/bip39_english.h index 77607ba7f..c57fca365 100644 --- a/bip39_english.h +++ b/bip39_english.h @@ -21,2054 +21,347 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -static const char * const wordlist[] = { -"abandon", -"ability", -"able", -"about", -"above", -"absent", -"absorb", -"abstract", -"absurd", -"abuse", -"access", -"accident", -"account", -"accuse", -"achieve", -"acid", -"acoustic", -"acquire", -"across", -"act", -"action", -"actor", -"actress", -"actual", -"adapt", -"add", -"addict", -"address", -"adjust", -"admit", -"adult", -"advance", -"advice", -"aerobic", -"affair", -"afford", -"afraid", -"again", -"age", -"agent", -"agree", -"ahead", -"aim", -"air", -"airport", -"aisle", -"alarm", -"album", -"alcohol", -"alert", -"alien", -"all", -"alley", -"allow", -"almost", -"alone", -"alpha", -"already", -"also", -"alter", -"always", -"amateur", -"amazing", -"among", -"amount", -"amused", -"analyst", -"anchor", -"ancient", -"anger", -"angle", -"angry", -"animal", -"ankle", -"announce", -"annual", -"another", -"answer", -"antenna", -"antique", -"anxiety", -"any", -"apart", -"apology", -"appear", -"apple", -"approve", -"april", -"arch", -"arctic", -"area", -"arena", -"argue", -"arm", -"armed", -"armor", -"army", -"around", -"arrange", -"arrest", -"arrive", -"arrow", -"art", -"artefact", -"artist", -"artwork", -"ask", -"aspect", -"assault", -"asset", -"assist", -"assume", -"asthma", -"athlete", -"atom", -"attack", -"attend", -"attitude", -"attract", -"auction", -"audit", -"august", -"aunt", -"author", -"auto", -"autumn", -"average", -"avocado", -"avoid", -"awake", -"aware", -"away", -"awesome", -"awful", -"awkward", -"axis", -"baby", -"bachelor", -"bacon", -"badge", -"bag", -"balance", -"balcony", -"ball", -"bamboo", -"banana", -"banner", -"bar", -"barely", -"bargain", -"barrel", -"base", -"basic", -"basket", -"battle", -"beach", -"bean", -"beauty", -"because", -"become", -"beef", -"before", -"begin", -"behave", -"behind", -"believe", -"below", -"belt", -"bench", -"benefit", -"best", -"betray", -"better", -"between", -"beyond", -"bicycle", -"bid", -"bike", -"bind", -"biology", -"bird", -"birth", -"bitter", -"black", -"blade", -"blame", -"blanket", -"blast", -"bleak", -"bless", -"blind", -"blood", -"blossom", -"blouse", -"blue", -"blur", -"blush", -"board", -"boat", -"body", -"boil", -"bomb", -"bone", -"bonus", -"book", -"boost", -"border", -"boring", -"borrow", -"boss", -"bottom", -"bounce", -"box", -"boy", -"bracket", -"brain", -"brand", -"brass", -"brave", -"bread", -"breeze", -"brick", -"bridge", -"brief", -"bright", -"bring", -"brisk", -"broccoli", -"broken", -"bronze", -"broom", -"brother", -"brown", -"brush", -"bubble", -"buddy", -"budget", -"buffalo", -"build", -"bulb", -"bulk", -"bullet", -"bundle", -"bunker", -"burden", -"burger", -"burst", -"bus", -"business", -"busy", -"butter", -"buyer", -"buzz", -"cabbage", -"cabin", -"cable", -"cactus", -"cage", -"cake", -"call", -"calm", -"camera", -"camp", -"can", -"canal", -"cancel", -"candy", -"cannon", -"canoe", -"canvas", -"canyon", -"capable", -"capital", -"captain", -"car", -"carbon", -"card", -"cargo", -"carpet", -"carry", -"cart", -"case", -"cash", -"casino", -"castle", -"casual", -"cat", -"catalog", -"catch", -"category", -"cattle", -"caught", -"cause", -"caution", -"cave", -"ceiling", -"celery", -"cement", -"census", -"century", -"cereal", -"certain", -"chair", -"chalk", -"champion", -"change", -"chaos", -"chapter", -"charge", -"chase", -"chat", -"cheap", -"check", -"cheese", -"chef", -"cherry", -"chest", -"chicken", -"chief", -"child", -"chimney", -"choice", -"choose", -"chronic", -"chuckle", -"chunk", -"churn", -"cigar", -"cinnamon", -"circle", -"citizen", -"city", -"civil", -"claim", -"clap", -"clarify", -"claw", -"clay", -"clean", -"clerk", -"clever", -"click", -"client", -"cliff", -"climb", -"clinic", -"clip", -"clock", -"clog", -"close", -"cloth", -"cloud", -"clown", -"club", -"clump", -"cluster", -"clutch", -"coach", -"coast", -"coconut", -"code", -"coffee", -"coil", -"coin", -"collect", -"color", -"column", -"combine", -"come", -"comfort", -"comic", -"common", -"company", -"concert", -"conduct", -"confirm", -"congress", -"connect", -"consider", -"control", -"convince", -"cook", -"cool", -"copper", -"copy", -"coral", -"core", -"corn", -"correct", -"cost", -"cotton", -"couch", -"country", -"couple", -"course", -"cousin", -"cover", -"coyote", -"crack", -"cradle", -"craft", -"cram", -"crane", -"crash", -"crater", -"crawl", -"crazy", -"cream", -"credit", -"creek", -"crew", -"cricket", -"crime", -"crisp", -"critic", -"crop", -"cross", -"crouch", -"crowd", -"crucial", -"cruel", -"cruise", -"crumble", -"crunch", -"crush", -"cry", -"crystal", -"cube", -"culture", -"cup", -"cupboard", -"curious", -"current", -"curtain", -"curve", -"cushion", -"custom", -"cute", -"cycle", -"dad", -"damage", -"damp", -"dance", -"danger", -"daring", -"dash", -"daughter", -"dawn", -"day", -"deal", -"debate", -"debris", -"decade", -"december", -"decide", -"decline", -"decorate", -"decrease", -"deer", -"defense", -"define", -"defy", -"degree", -"delay", -"deliver", -"demand", -"demise", -"denial", -"dentist", -"deny", -"depart", -"depend", -"deposit", -"depth", -"deputy", -"derive", -"describe", -"desert", -"design", -"desk", -"despair", -"destroy", -"detail", -"detect", -"develop", -"device", -"devote", -"diagram", -"dial", -"diamond", -"diary", -"dice", -"diesel", -"diet", -"differ", -"digital", -"dignity", -"dilemma", -"dinner", -"dinosaur", -"direct", -"dirt", -"disagree", -"discover", -"disease", -"dish", -"dismiss", -"disorder", -"display", -"distance", -"divert", -"divide", -"divorce", -"dizzy", -"doctor", -"document", -"dog", -"doll", -"dolphin", -"domain", -"donate", -"donkey", -"donor", -"door", -"dose", -"double", -"dove", -"draft", -"dragon", -"drama", -"drastic", -"draw", -"dream", -"dress", -"drift", -"drill", -"drink", -"drip", -"drive", -"drop", -"drum", -"dry", -"duck", -"dumb", -"dune", -"during", -"dust", -"dutch", -"duty", -"dwarf", -"dynamic", -"eager", -"eagle", -"early", -"earn", -"earth", -"easily", -"east", -"easy", -"echo", -"ecology", -"economy", -"edge", -"edit", -"educate", -"effort", -"egg", -"eight", -"either", -"elbow", -"elder", -"electric", -"elegant", -"element", -"elephant", -"elevator", -"elite", -"else", -"embark", -"embody", -"embrace", -"emerge", -"emotion", -"employ", -"empower", -"empty", -"enable", -"enact", -"end", -"endless", -"endorse", -"enemy", -"energy", -"enforce", -"engage", -"engine", -"enhance", -"enjoy", -"enlist", -"enough", -"enrich", -"enroll", -"ensure", -"enter", -"entire", -"entry", -"envelope", -"episode", -"equal", -"equip", -"era", -"erase", -"erode", -"erosion", -"error", -"erupt", -"escape", -"essay", -"essence", -"estate", -"eternal", -"ethics", -"evidence", -"evil", -"evoke", -"evolve", -"exact", -"example", -"excess", -"exchange", -"excite", -"exclude", -"excuse", -"execute", -"exercise", -"exhaust", -"exhibit", -"exile", -"exist", -"exit", -"exotic", -"expand", -"expect", -"expire", -"explain", -"expose", -"express", -"extend", -"extra", -"eye", -"eyebrow", -"fabric", -"face", -"faculty", -"fade", -"faint", -"faith", -"fall", -"false", -"fame", -"family", -"famous", -"fan", -"fancy", -"fantasy", -"farm", -"fashion", -"fat", -"fatal", -"father", -"fatigue", -"fault", -"favorite", -"feature", -"february", -"federal", -"fee", -"feed", -"feel", -"female", -"fence", -"festival", -"fetch", -"fever", -"few", -"fiber", -"fiction", -"field", -"figure", -"file", -"film", -"filter", -"final", -"find", -"fine", -"finger", -"finish", -"fire", -"firm", -"first", -"fiscal", -"fish", -"fit", -"fitness", -"fix", -"flag", -"flame", -"flash", -"flat", -"flavor", -"flee", -"flight", -"flip", -"float", -"flock", -"floor", -"flower", -"fluid", -"flush", -"fly", -"foam", -"focus", -"fog", -"foil", -"fold", -"follow", -"food", -"foot", -"force", -"forest", -"forget", -"fork", -"fortune", -"forum", -"forward", -"fossil", -"foster", -"found", -"fox", -"fragile", -"frame", -"frequent", -"fresh", -"friend", -"fringe", -"frog", -"front", -"frost", -"frown", -"frozen", -"fruit", -"fuel", -"fun", -"funny", -"furnace", -"fury", -"future", -"gadget", -"gain", -"galaxy", -"gallery", -"game", -"gap", -"garage", -"garbage", -"garden", -"garlic", -"garment", -"gas", -"gasp", -"gate", -"gather", -"gauge", -"gaze", -"general", -"genius", -"genre", -"gentle", -"genuine", -"gesture", -"ghost", -"giant", -"gift", -"giggle", -"ginger", -"giraffe", -"girl", -"give", -"glad", -"glance", -"glare", -"glass", -"glide", -"glimpse", -"globe", -"gloom", -"glory", -"glove", -"glow", -"glue", -"goat", -"goddess", -"gold", -"good", -"goose", -"gorilla", -"gospel", -"gossip", -"govern", -"gown", -"grab", -"grace", -"grain", -"grant", -"grape", -"grass", -"gravity", -"great", -"green", -"grid", -"grief", -"grit", -"grocery", -"group", -"grow", -"grunt", -"guard", -"guess", -"guide", -"guilt", -"guitar", -"gun", -"gym", -"habit", -"hair", -"half", -"hammer", -"hamster", -"hand", -"happy", -"harbor", -"hard", -"harsh", -"harvest", -"hat", -"have", -"hawk", -"hazard", -"head", -"health", -"heart", -"heavy", -"hedgehog", -"height", -"hello", -"helmet", -"help", -"hen", -"hero", -"hidden", -"high", -"hill", -"hint", -"hip", -"hire", -"history", -"hobby", -"hockey", -"hold", -"hole", -"holiday", -"hollow", -"home", -"honey", -"hood", -"hope", -"horn", -"horror", -"horse", -"hospital", -"host", -"hotel", -"hour", -"hover", -"hub", -"huge", -"human", -"humble", -"humor", -"hundred", -"hungry", -"hunt", -"hurdle", -"hurry", -"hurt", -"husband", -"hybrid", -"ice", -"icon", -"idea", -"identify", -"idle", -"ignore", -"ill", -"illegal", -"illness", -"image", -"imitate", -"immense", -"immune", -"impact", -"impose", -"improve", -"impulse", -"inch", -"include", -"income", -"increase", -"index", -"indicate", -"indoor", -"industry", -"infant", -"inflict", -"inform", -"inhale", -"inherit", -"initial", -"inject", -"injury", -"inmate", -"inner", -"innocent", -"input", -"inquiry", -"insane", -"insect", -"inside", -"inspire", -"install", -"intact", -"interest", -"into", -"invest", -"invite", -"involve", -"iron", -"island", -"isolate", -"issue", -"item", -"ivory", -"jacket", -"jaguar", -"jar", -"jazz", -"jealous", -"jeans", -"jelly", -"jewel", -"job", -"join", -"joke", -"journey", -"joy", -"judge", -"juice", -"jump", -"jungle", -"junior", -"junk", -"just", -"kangaroo", -"keen", -"keep", -"ketchup", -"key", -"kick", -"kid", -"kidney", -"kind", -"kingdom", -"kiss", -"kit", -"kitchen", -"kite", -"kitten", -"kiwi", -"knee", -"knife", -"knock", -"know", -"lab", -"label", -"labor", -"ladder", -"lady", -"lake", -"lamp", -"language", -"laptop", -"large", -"later", -"latin", -"laugh", -"laundry", -"lava", -"law", -"lawn", -"lawsuit", -"layer", -"lazy", -"leader", -"leaf", -"learn", -"leave", -"lecture", -"left", -"leg", -"legal", -"legend", -"leisure", -"lemon", -"lend", -"length", -"lens", -"leopard", -"lesson", -"letter", -"level", -"liar", -"liberty", -"library", -"license", -"life", -"lift", -"light", -"like", -"limb", -"limit", -"link", -"lion", -"liquid", -"list", -"little", -"live", -"lizard", -"load", -"loan", -"lobster", -"local", -"lock", -"logic", -"lonely", -"long", -"loop", -"lottery", -"loud", -"lounge", -"love", -"loyal", -"lucky", -"luggage", -"lumber", -"lunar", -"lunch", -"luxury", -"lyrics", -"machine", -"mad", -"magic", -"magnet", -"maid", -"mail", -"main", -"major", -"make", -"mammal", -"man", -"manage", -"mandate", -"mango", -"mansion", -"manual", -"maple", -"marble", -"march", -"margin", -"marine", -"market", -"marriage", -"mask", -"mass", -"master", -"match", -"material", -"math", -"matrix", -"matter", -"maximum", -"maze", -"meadow", -"mean", -"measure", -"meat", -"mechanic", -"medal", -"media", -"melody", -"melt", -"member", -"memory", -"mention", -"menu", -"mercy", -"merge", -"merit", -"merry", -"mesh", -"message", -"metal", -"method", -"middle", -"midnight", -"milk", -"million", -"mimic", -"mind", -"minimum", -"minor", -"minute", -"miracle", -"mirror", -"misery", -"miss", -"mistake", -"mix", -"mixed", -"mixture", -"mobile", -"model", -"modify", -"mom", -"moment", -"monitor", -"monkey", -"monster", -"month", -"moon", -"moral", -"more", -"morning", -"mosquito", -"mother", -"motion", -"motor", -"mountain", -"mouse", -"move", -"movie", -"much", -"muffin", -"mule", -"multiply", -"muscle", -"museum", -"mushroom", -"music", -"must", -"mutual", -"myself", -"mystery", -"myth", -"naive", -"name", -"napkin", -"narrow", -"nasty", -"nation", -"nature", -"near", -"neck", -"need", -"negative", -"neglect", -"neither", -"nephew", -"nerve", -"nest", -"net", -"network", -"neutral", -"never", -"news", -"next", -"nice", -"night", -"noble", -"noise", -"nominee", -"noodle", -"normal", -"north", -"nose", -"notable", -"note", -"nothing", -"notice", -"novel", -"now", -"nuclear", -"number", -"nurse", -"nut", -"oak", -"obey", -"object", -"oblige", -"obscure", -"observe", -"obtain", -"obvious", -"occur", -"ocean", -"october", -"odor", -"off", -"offer", -"office", -"often", -"oil", -"okay", -"old", -"olive", -"olympic", -"omit", -"once", -"one", -"onion", -"online", -"only", -"open", -"opera", -"opinion", -"oppose", -"option", -"orange", -"orbit", -"orchard", -"order", -"ordinary", -"organ", -"orient", -"original", -"orphan", -"ostrich", -"other", -"outdoor", -"outer", -"output", -"outside", -"oval", -"oven", -"over", -"own", -"owner", -"oxygen", -"oyster", -"ozone", -"pact", -"paddle", -"page", -"pair", -"palace", -"palm", -"panda", -"panel", -"panic", -"panther", -"paper", -"parade", -"parent", -"park", -"parrot", -"party", -"pass", -"patch", -"path", -"patient", -"patrol", -"pattern", -"pause", -"pave", -"payment", -"peace", -"peanut", -"pear", -"peasant", -"pelican", -"pen", -"penalty", -"pencil", -"people", -"pepper", -"perfect", -"permit", -"person", -"pet", -"phone", -"photo", -"phrase", -"physical", -"piano", -"picnic", -"picture", -"piece", -"pig", -"pigeon", -"pill", -"pilot", -"pink", -"pioneer", -"pipe", -"pistol", -"pitch", -"pizza", -"place", -"planet", -"plastic", -"plate", -"play", -"please", -"pledge", -"pluck", -"plug", -"plunge", -"poem", -"poet", -"point", -"polar", -"pole", -"police", -"pond", -"pony", -"pool", -"popular", -"portion", -"position", -"possible", -"post", -"potato", -"pottery", -"poverty", -"powder", -"power", -"practice", -"praise", -"predict", -"prefer", -"prepare", -"present", -"pretty", -"prevent", -"price", -"pride", -"primary", -"print", -"priority", -"prison", -"private", -"prize", -"problem", -"process", -"produce", -"profit", -"program", -"project", -"promote", -"proof", -"property", -"prosper", -"protect", -"proud", -"provide", -"public", -"pudding", -"pull", -"pulp", -"pulse", -"pumpkin", -"punch", -"pupil", -"puppy", -"purchase", -"purity", -"purpose", -"purse", -"push", -"put", -"puzzle", -"pyramid", -"quality", -"quantum", -"quarter", -"question", -"quick", -"quit", -"quiz", -"quote", -"rabbit", -"raccoon", -"race", -"rack", -"radar", -"radio", -"rail", -"rain", -"raise", -"rally", -"ramp", -"ranch", -"random", -"range", -"rapid", -"rare", -"rate", -"rather", -"raven", -"raw", -"razor", -"ready", -"real", -"reason", -"rebel", -"rebuild", -"recall", -"receive", -"recipe", -"record", -"recycle", -"reduce", -"reflect", -"reform", -"refuse", -"region", -"regret", -"regular", -"reject", -"relax", -"release", -"relief", -"rely", -"remain", -"remember", -"remind", -"remove", -"render", -"renew", -"rent", -"reopen", -"repair", -"repeat", -"replace", -"report", -"require", -"rescue", -"resemble", -"resist", -"resource", -"response", -"result", -"retire", -"retreat", -"return", -"reunion", -"reveal", -"review", -"reward", -"rhythm", -"rib", -"ribbon", -"rice", -"rich", -"ride", -"ridge", -"rifle", -"right", -"rigid", -"ring", -"riot", -"ripple", -"risk", -"ritual", -"rival", -"river", -"road", -"roast", -"robot", -"robust", -"rocket", -"romance", -"roof", -"rookie", -"room", -"rose", -"rotate", -"rough", -"round", -"route", -"royal", -"rubber", -"rude", -"rug", -"rule", -"run", -"runway", -"rural", -"sad", -"saddle", -"sadness", -"safe", -"sail", -"salad", -"salmon", -"salon", -"salt", -"salute", -"same", -"sample", -"sand", -"satisfy", -"satoshi", -"sauce", -"sausage", -"save", -"say", -"scale", -"scan", -"scare", -"scatter", -"scene", -"scheme", -"school", -"science", -"scissors", -"scorpion", -"scout", -"scrap", -"screen", -"script", -"scrub", -"sea", -"search", -"season", -"seat", -"second", -"secret", -"section", -"security", -"seed", -"seek", -"segment", -"select", -"sell", -"seminar", -"senior", -"sense", -"sentence", -"series", -"service", -"session", -"settle", -"setup", -"seven", -"shadow", -"shaft", -"shallow", -"share", -"shed", -"shell", -"sheriff", -"shield", -"shift", -"shine", -"ship", -"shiver", -"shock", -"shoe", -"shoot", -"shop", -"short", -"shoulder", -"shove", -"shrimp", -"shrug", -"shuffle", -"shy", -"sibling", -"sick", -"side", -"siege", -"sight", -"sign", -"silent", -"silk", -"silly", -"silver", -"similar", -"simple", -"since", -"sing", -"siren", -"sister", -"situate", -"six", -"size", -"skate", -"sketch", -"ski", -"skill", -"skin", -"skirt", -"skull", -"slab", -"slam", -"sleep", -"slender", -"slice", -"slide", -"slight", -"slim", -"slogan", -"slot", -"slow", -"slush", -"small", -"smart", -"smile", -"smoke", -"smooth", -"snack", -"snake", -"snap", -"sniff", -"snow", -"soap", -"soccer", -"social", -"sock", -"soda", -"soft", -"solar", -"soldier", -"solid", -"solution", -"solve", -"someone", -"song", -"soon", -"sorry", -"sort", -"soul", -"sound", -"soup", -"source", -"south", -"space", -"spare", -"spatial", -"spawn", -"speak", -"special", -"speed", -"spell", -"spend", -"sphere", -"spice", -"spider", -"spike", -"spin", -"spirit", -"split", -"spoil", -"sponsor", -"spoon", -"sport", -"spot", -"spray", -"spread", -"spring", -"spy", -"square", -"squeeze", -"squirrel", -"stable", -"stadium", -"staff", -"stage", -"stairs", -"stamp", -"stand", -"start", -"state", -"stay", -"steak", -"steel", -"stem", -"step", -"stereo", -"stick", -"still", -"sting", -"stock", -"stomach", -"stone", -"stool", -"story", -"stove", -"strategy", -"street", -"strike", -"strong", -"struggle", -"student", -"stuff", -"stumble", -"style", -"subject", -"submit", -"subway", -"success", -"such", -"sudden", -"suffer", -"sugar", -"suggest", -"suit", -"summer", -"sun", -"sunny", -"sunset", -"super", -"supply", -"supreme", -"sure", -"surface", -"surge", -"surprise", -"surround", -"survey", -"suspect", -"sustain", -"swallow", -"swamp", -"swap", -"swarm", -"swear", -"sweet", -"swift", -"swim", -"swing", -"switch", -"sword", -"symbol", -"symptom", -"syrup", -"system", -"table", -"tackle", -"tag", -"tail", -"talent", -"talk", -"tank", -"tape", -"target", -"task", -"taste", -"tattoo", -"taxi", -"teach", -"team", -"tell", -"ten", -"tenant", -"tennis", -"tent", -"term", -"test", -"text", -"thank", -"that", -"theme", -"then", -"theory", -"there", -"they", -"thing", -"this", -"thought", -"three", -"thrive", -"throw", -"thumb", -"thunder", -"ticket", -"tide", -"tiger", -"tilt", -"timber", -"time", -"tiny", -"tip", -"tired", -"tissue", -"title", -"toast", -"tobacco", -"today", -"toddler", -"toe", -"together", -"toilet", -"token", -"tomato", -"tomorrow", -"tone", -"tongue", -"tonight", -"tool", -"tooth", -"top", -"topic", -"topple", -"torch", -"tornado", -"tortoise", -"toss", -"total", -"tourist", -"toward", -"tower", -"town", -"toy", -"track", -"trade", -"traffic", -"tragic", -"train", -"transfer", -"trap", -"trash", -"travel", -"tray", -"treat", -"tree", -"trend", -"trial", -"tribe", -"trick", -"trigger", -"trim", -"trip", -"trophy", -"trouble", -"truck", -"true", -"truly", -"trumpet", -"trust", -"truth", -"try", -"tube", -"tuition", -"tumble", -"tuna", -"tunnel", -"turkey", -"turn", -"turtle", -"twelve", -"twenty", -"twice", -"twin", -"twist", -"two", -"type", -"typical", -"ugly", -"umbrella", -"unable", -"unaware", -"uncle", -"uncover", -"under", -"undo", -"unfair", -"unfold", -"unhappy", -"uniform", -"unique", -"unit", -"universe", -"unknown", -"unlock", -"until", -"unusual", -"unveil", -"update", -"upgrade", -"uphold", -"upon", -"upper", -"upset", -"urban", -"urge", -"usage", -"use", -"used", -"useful", -"useless", -"usual", -"utility", -"vacant", -"vacuum", -"vague", -"valid", -"valley", -"valve", -"van", -"vanish", -"vapor", -"various", -"vast", -"vault", -"vehicle", -"velvet", -"vendor", -"venture", -"venue", -"verb", -"verify", -"version", -"very", -"vessel", -"veteran", -"viable", -"vibrant", -"vicious", -"victory", -"video", -"view", -"village", -"vintage", -"violin", -"virtual", -"virus", -"visa", -"visit", -"visual", -"vital", -"vivid", -"vocal", -"voice", -"void", -"volcano", -"volume", -"vote", -"voyage", -"wage", -"wagon", -"wait", -"walk", -"wall", -"walnut", -"want", -"warfare", -"warm", -"warrior", -"wash", -"wasp", -"waste", -"water", -"wave", -"way", -"wealth", -"weapon", -"wear", -"weasel", -"weather", -"web", -"wedding", -"weekend", -"weird", -"welcome", -"west", -"wet", -"whale", -"what", -"wheat", -"wheel", -"when", -"where", -"whip", -"whisper", -"wide", -"width", -"wife", -"wild", -"will", -"win", -"window", -"wine", -"wing", -"wink", -"winner", -"winter", -"wire", -"wisdom", -"wise", -"wish", -"witness", -"wolf", -"woman", -"wonder", -"wood", -"wool", -"word", -"work", -"world", -"worry", -"worth", -"wrap", -"wreck", -"wrestle", -"wrist", -"write", -"wrong", -"yard", -"year", -"yellow", -"you", -"young", -"youth", -"zebra", -"zero", -"zone", -"zoo", -0, +static const char* const wordlist[] = { + "abandon", "ability", "able", "about", "above", "absent", + "absorb", "abstract", "absurd", "abuse", "access", "accident", + "account", "accuse", "achieve", "acid", "acoustic", "acquire", + "across", "act", "action", "actor", "actress", "actual", + "adapt", "add", "addict", "address", "adjust", "admit", + "adult", "advance", "advice", "aerobic", "affair", "afford", + "afraid", "again", "age", "agent", "agree", "ahead", + "aim", "air", "airport", "aisle", "alarm", "album", + "alcohol", "alert", "alien", "all", "alley", "allow", + "almost", "alone", "alpha", "already", "also", "alter", + "always", "amateur", "amazing", "among", "amount", "amused", + "analyst", "anchor", "ancient", "anger", "angle", "angry", + "animal", "ankle", "announce", "annual", "another", "answer", + "antenna", "antique", "anxiety", "any", "apart", "apology", + "appear", "apple", "approve", "april", "arch", "arctic", + "area", "arena", "argue", "arm", "armed", "armor", + "army", "around", "arrange", "arrest", "arrive", "arrow", + "art", "artefact", "artist", "artwork", "ask", "aspect", + "assault", "asset", "assist", "assume", "asthma", "athlete", + "atom", "attack", "attend", "attitude", "attract", "auction", + "audit", "august", "aunt", "author", "auto", "autumn", + "average", "avocado", "avoid", "awake", "aware", "away", + "awesome", "awful", "awkward", "axis", "baby", "bachelor", + "bacon", "badge", "bag", "balance", "balcony", "ball", + "bamboo", "banana", "banner", "bar", "barely", "bargain", + "barrel", "base", "basic", "basket", "battle", "beach", + "bean", "beauty", "because", "become", "beef", "before", + "begin", "behave", "behind", "believe", "below", "belt", + "bench", "benefit", "best", "betray", "better", "between", + "beyond", "bicycle", "bid", "bike", "bind", "biology", + "bird", "birth", "bitter", "black", "blade", "blame", + "blanket", "blast", "bleak", "bless", "blind", "blood", + "blossom", "blouse", "blue", "blur", "blush", "board", + "boat", "body", "boil", "bomb", "bone", "bonus", + "book", "boost", "border", "boring", "borrow", "boss", + "bottom", "bounce", "box", "boy", "bracket", "brain", + "brand", "brass", "brave", "bread", "breeze", "brick", + "bridge", "brief", "bright", "bring", "brisk", "broccoli", + "broken", "bronze", "broom", "brother", "brown", "brush", + "bubble", "buddy", "budget", "buffalo", "build", "bulb", + "bulk", "bullet", "bundle", "bunker", "burden", "burger", + "burst", "bus", "business", "busy", "butter", "buyer", + "buzz", "cabbage", "cabin", "cable", "cactus", "cage", + "cake", "call", "calm", "camera", "camp", "can", + "canal", "cancel", "candy", "cannon", "canoe", "canvas", + "canyon", "capable", "capital", "captain", "car", "carbon", + "card", "cargo", "carpet", "carry", "cart", "case", + "cash", "casino", "castle", "casual", "cat", "catalog", + "catch", "category", "cattle", "caught", "cause", "caution", + "cave", "ceiling", "celery", "cement", "census", "century", + "cereal", "certain", "chair", "chalk", "champion", "change", + "chaos", "chapter", "charge", "chase", "chat", "cheap", + "check", "cheese", "chef", "cherry", "chest", "chicken", + "chief", "child", "chimney", "choice", "choose", "chronic", + "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle", + "citizen", "city", "civil", "claim", "clap", "clarify", + "claw", "clay", "clean", "clerk", "clever", "click", + "client", "cliff", "climb", "clinic", "clip", "clock", + "clog", "close", "cloth", "cloud", "clown", "club", + "clump", "cluster", "clutch", "coach", "coast", "coconut", + "code", "coffee", "coil", "coin", "collect", "color", + "column", "combine", "come", "comfort", "comic", "common", + "company", "concert", "conduct", "confirm", "congress", "connect", + "consider", "control", "convince", "cook", "cool", "copper", + "copy", "coral", "core", "corn", "correct", "cost", + "cotton", "couch", "country", "couple", "course", "cousin", + "cover", "coyote", "crack", "cradle", "craft", "cram", + "crane", "crash", "crater", "crawl", "crazy", "cream", + "credit", "creek", "crew", "cricket", "crime", "crisp", + "critic", "crop", "cross", "crouch", "crowd", "crucial", + "cruel", "cruise", "crumble", "crunch", "crush", "cry", + "crystal", "cube", "culture", "cup", "cupboard", "curious", + "current", "curtain", "curve", "cushion", "custom", "cute", + "cycle", "dad", "damage", "damp", "dance", "danger", + "daring", "dash", "daughter", "dawn", "day", "deal", + "debate", "debris", "decade", "december", "decide", "decline", + "decorate", "decrease", "deer", "defense", "define", "defy", + "degree", "delay", "deliver", "demand", "demise", "denial", + "dentist", "deny", "depart", "depend", "deposit", "depth", + "deputy", "derive", "describe", "desert", "design", "desk", + "despair", "destroy", "detail", "detect", "develop", "device", + "devote", "diagram", "dial", "diamond", "diary", "dice", + "diesel", "diet", "differ", "digital", "dignity", "dilemma", + "dinner", "dinosaur", "direct", "dirt", "disagree", "discover", + "disease", "dish", "dismiss", "disorder", "display", "distance", + "divert", "divide", "divorce", "dizzy", "doctor", "document", + "dog", "doll", "dolphin", "domain", "donate", "donkey", + "donor", "door", "dose", "double", "dove", "draft", + "dragon", "drama", "drastic", "draw", "dream", "dress", + "drift", "drill", "drink", "drip", "drive", "drop", + "drum", "dry", "duck", "dumb", "dune", "during", + "dust", "dutch", "duty", "dwarf", "dynamic", "eager", + "eagle", "early", "earn", "earth", "easily", "east", + "easy", "echo", "ecology", "economy", "edge", "edit", + "educate", "effort", "egg", "eight", "either", "elbow", + "elder", "electric", "elegant", "element", "elephant", "elevator", + "elite", "else", "embark", "embody", "embrace", "emerge", + "emotion", "employ", "empower", "empty", "enable", "enact", + "end", "endless", "endorse", "enemy", "energy", "enforce", + "engage", "engine", "enhance", "enjoy", "enlist", "enough", + "enrich", "enroll", "ensure", "enter", "entire", "entry", + "envelope", "episode", "equal", "equip", "era", "erase", + "erode", "erosion", "error", "erupt", "escape", "essay", + "essence", "estate", "eternal", "ethics", "evidence", "evil", + "evoke", "evolve", "exact", "example", "excess", "exchange", + "excite", "exclude", "excuse", "execute", "exercise", "exhaust", + "exhibit", "exile", "exist", "exit", "exotic", "expand", + "expect", "expire", "explain", "expose", "express", "extend", + "extra", "eye", "eyebrow", "fabric", "face", "faculty", + "fade", "faint", "faith", "fall", "false", "fame", + "family", "famous", "fan", "fancy", "fantasy", "farm", + "fashion", "fat", "fatal", "father", "fatigue", "fault", + "favorite", "feature", "february", "federal", "fee", "feed", + "feel", "female", "fence", "festival", "fetch", "fever", + "few", "fiber", "fiction", "field", "figure", "file", + "film", "filter", "final", "find", "fine", "finger", + "finish", "fire", "firm", "first", "fiscal", "fish", + "fit", "fitness", "fix", "flag", "flame", "flash", + "flat", "flavor", "flee", "flight", "flip", "float", + "flock", "floor", "flower", "fluid", "flush", "fly", + "foam", "focus", "fog", "foil", "fold", "follow", + "food", "foot", "force", "forest", "forget", "fork", + "fortune", "forum", "forward", "fossil", "foster", "found", + "fox", "fragile", "frame", "frequent", "fresh", "friend", + "fringe", "frog", "front", "frost", "frown", "frozen", + "fruit", "fuel", "fun", "funny", "furnace", "fury", + "future", "gadget", "gain", "galaxy", "gallery", "game", + "gap", "garage", "garbage", "garden", "garlic", "garment", + "gas", "gasp", "gate", "gather", "gauge", "gaze", + "general", "genius", "genre", "gentle", "genuine", "gesture", + "ghost", "giant", "gift", "giggle", "ginger", "giraffe", + "girl", "give", "glad", "glance", "glare", "glass", + "glide", "glimpse", "globe", "gloom", "glory", "glove", + "glow", "glue", "goat", "goddess", "gold", "good", + "goose", "gorilla", "gospel", "gossip", "govern", "gown", + "grab", "grace", "grain", "grant", "grape", "grass", + "gravity", "great", "green", "grid", "grief", "grit", + "grocery", "group", "grow", "grunt", "guard", "guess", + "guide", "guilt", "guitar", "gun", "gym", "habit", + "hair", "half", "hammer", "hamster", "hand", "happy", + "harbor", "hard", "harsh", "harvest", "hat", "have", + "hawk", "hazard", "head", "health", "heart", "heavy", + "hedgehog", "height", "hello", "helmet", "help", "hen", + "hero", "hidden", "high", "hill", "hint", "hip", + "hire", "history", "hobby", "hockey", "hold", "hole", + "holiday", "hollow", "home", "honey", "hood", "hope", + "horn", "horror", "horse", "hospital", "host", "hotel", + "hour", "hover", "hub", "huge", "human", "humble", + "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", + "hurt", "husband", "hybrid", "ice", "icon", "idea", + "identify", "idle", "ignore", "ill", "illegal", "illness", + "image", "imitate", "immense", "immune", "impact", "impose", + "improve", "impulse", "inch", "include", "income", "increase", + "index", "indicate", "indoor", "industry", "infant", "inflict", + "inform", "inhale", "inherit", "initial", "inject", "injury", + "inmate", "inner", "innocent", "input", "inquiry", "insane", + "insect", "inside", "inspire", "install", "intact", "interest", + "into", "invest", "invite", "involve", "iron", "island", + "isolate", "issue", "item", "ivory", "jacket", "jaguar", + "jar", "jazz", "jealous", "jeans", "jelly", "jewel", + "job", "join", "joke", "journey", "joy", "judge", + "juice", "jump", "jungle", "junior", "junk", "just", + "kangaroo", "keen", "keep", "ketchup", "key", "kick", + "kid", "kidney", "kind", "kingdom", "kiss", "kit", + "kitchen", "kite", "kitten", "kiwi", "knee", "knife", + "knock", "know", "lab", "label", "labor", "ladder", + "lady", "lake", "lamp", "language", "laptop", "large", + "later", "latin", "laugh", "laundry", "lava", "law", + "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", + "learn", "leave", "lecture", "left", "leg", "legal", + "legend", "leisure", "lemon", "lend", "length", "lens", + "leopard", "lesson", "letter", "level", "liar", "liberty", + "library", "license", "life", "lift", "light", "like", + "limb", "limit", "link", "lion", "liquid", "list", + "little", "live", "lizard", "load", "loan", "lobster", + "local", "lock", "logic", "lonely", "long", "loop", + "lottery", "loud", "lounge", "love", "loyal", "lucky", + "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics", + "machine", "mad", "magic", "magnet", "maid", "mail", + "main", "major", "make", "mammal", "man", "manage", + "mandate", "mango", "mansion", "manual", "maple", "marble", + "march", "margin", "marine", "market", "marriage", "mask", + "mass", "master", "match", "material", "math", "matrix", + "matter", "maximum", "maze", "meadow", "mean", "measure", + "meat", "mechanic", "medal", "media", "melody", "melt", + "member", "memory", "mention", "menu", "mercy", "merge", + "merit", "merry", "mesh", "message", "metal", "method", + "middle", "midnight", "milk", "million", "mimic", "mind", + "minimum", "minor", "minute", "miracle", "mirror", "misery", + "miss", "mistake", "mix", "mixed", "mixture", "mobile", + "model", "modify", "mom", "moment", "monitor", "monkey", + "monster", "month", "moon", "moral", "more", "morning", + "mosquito", "mother", "motion", "motor", "mountain", "mouse", + "move", "movie", "much", "muffin", "mule", "multiply", + "muscle", "museum", "mushroom", "music", "must", "mutual", + "myself", "mystery", "myth", "naive", "name", "napkin", + "narrow", "nasty", "nation", "nature", "near", "neck", + "need", "negative", "neglect", "neither", "nephew", "nerve", + "nest", "net", "network", "neutral", "never", "news", + "next", "nice", "night", "noble", "noise", "nominee", + "noodle", "normal", "north", "nose", "notable", "note", + "nothing", "notice", "novel", "now", "nuclear", "number", + "nurse", "nut", "oak", "obey", "object", "oblige", + "obscure", "observe", "obtain", "obvious", "occur", "ocean", + "october", "odor", "off", "offer", "office", "often", + "oil", "okay", "old", "olive", "olympic", "omit", + "once", "one", "onion", "online", "only", "open", + "opera", "opinion", "oppose", "option", "orange", "orbit", + "orchard", "order", "ordinary", "organ", "orient", "original", + "orphan", "ostrich", "other", "outdoor", "outer", "output", + "outside", "oval", "oven", "over", "own", "owner", + "oxygen", "oyster", "ozone", "pact", "paddle", "page", + "pair", "palace", "palm", "panda", "panel", "panic", + "panther", "paper", "parade", "parent", "park", "parrot", + "party", "pass", "patch", "path", "patient", "patrol", + "pattern", "pause", "pave", "payment", "peace", "peanut", + "pear", "peasant", "pelican", "pen", "penalty", "pencil", + "people", "pepper", "perfect", "permit", "person", "pet", + "phone", "photo", "phrase", "physical", "piano", "picnic", + "picture", "piece", "pig", "pigeon", "pill", "pilot", + "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", + "place", "planet", "plastic", "plate", "play", "please", + "pledge", "pluck", "plug", "plunge", "poem", "poet", + "point", "polar", "pole", "police", "pond", "pony", + "pool", "popular", "portion", "position", "possible", "post", + "potato", "pottery", "poverty", "powder", "power", "practice", + "praise", "predict", "prefer", "prepare", "present", "pretty", + "prevent", "price", "pride", "primary", "print", "priority", + "prison", "private", "prize", "problem", "process", "produce", + "profit", "program", "project", "promote", "proof", "property", + "prosper", "protect", "proud", "provide", "public", "pudding", + "pull", "pulp", "pulse", "pumpkin", "punch", "pupil", + "puppy", "purchase", "purity", "purpose", "purse", "push", + "put", "puzzle", "pyramid", "quality", "quantum", "quarter", + "question", "quick", "quit", "quiz", "quote", "rabbit", + "raccoon", "race", "rack", "radar", "radio", "rail", + "rain", "raise", "rally", "ramp", "ranch", "random", + "range", "rapid", "rare", "rate", "rather", "raven", + "raw", "razor", "ready", "real", "reason", "rebel", + "rebuild", "recall", "receive", "recipe", "record", "recycle", + "reduce", "reflect", "reform", "refuse", "region", "regret", + "regular", "reject", "relax", "release", "relief", "rely", + "remain", "remember", "remind", "remove", "render", "renew", + "rent", "reopen", "repair", "repeat", "replace", "report", + "require", "rescue", "resemble", "resist", "resource", "response", + "result", "retire", "retreat", "return", "reunion", "reveal", + "review", "reward", "rhythm", "rib", "ribbon", "rice", + "rich", "ride", "ridge", "rifle", "right", "rigid", + "ring", "riot", "ripple", "risk", "ritual", "rival", + "river", "road", "roast", "robot", "robust", "rocket", + "romance", "roof", "rookie", "room", "rose", "rotate", + "rough", "round", "route", "royal", "rubber", "rude", + "rug", "rule", "run", "runway", "rural", "sad", + "saddle", "sadness", "safe", "sail", "salad", "salmon", + "salon", "salt", "salute", "same", "sample", "sand", + "satisfy", "satoshi", "sauce", "sausage", "save", "say", + "scale", "scan", "scare", "scatter", "scene", "scheme", + "school", "science", "scissors", "scorpion", "scout", "scrap", + "screen", "script", "scrub", "sea", "search", "season", + "seat", "second", "secret", "section", "security", "seed", + "seek", "segment", "select", "sell", "seminar", "senior", + "sense", "sentence", "series", "service", "session", "settle", + "setup", "seven", "shadow", "shaft", "shallow", "share", + "shed", "shell", "sheriff", "shield", "shift", "shine", + "ship", "shiver", "shock", "shoe", "shoot", "shop", + "short", "shoulder", "shove", "shrimp", "shrug", "shuffle", + "shy", "sibling", "sick", "side", "siege", "sight", + "sign", "silent", "silk", "silly", "silver", "similar", + "simple", "since", "sing", "siren", "sister", "situate", + "six", "size", "skate", "sketch", "ski", "skill", + "skin", "skirt", "skull", "slab", "slam", "sleep", + "slender", "slice", "slide", "slight", "slim", "slogan", + "slot", "slow", "slush", "small", "smart", "smile", + "smoke", "smooth", "snack", "snake", "snap", "sniff", + "snow", "soap", "soccer", "social", "sock", "soda", + "soft", "solar", "soldier", "solid", "solution", "solve", + "someone", "song", "soon", "sorry", "sort", "soul", + "sound", "soup", "source", "south", "space", "spare", + "spatial", "spawn", "speak", "special", "speed", "spell", + "spend", "sphere", "spice", "spider", "spike", "spin", + "spirit", "split", "spoil", "sponsor", "spoon", "sport", + "spot", "spray", "spread", "spring", "spy", "square", + "squeeze", "squirrel", "stable", "stadium", "staff", "stage", + "stairs", "stamp", "stand", "start", "state", "stay", + "steak", "steel", "stem", "step", "stereo", "stick", + "still", "sting", "stock", "stomach", "stone", "stool", + "story", "stove", "strategy", "street", "strike", "strong", + "struggle", "student", "stuff", "stumble", "style", "subject", + "submit", "subway", "success", "such", "sudden", "suffer", + "sugar", "suggest", "suit", "summer", "sun", "sunny", + "sunset", "super", "supply", "supreme", "sure", "surface", + "surge", "surprise", "surround", "survey", "suspect", "sustain", + "swallow", "swamp", "swap", "swarm", "swear", "sweet", + "swift", "swim", "swing", "switch", "sword", "symbol", + "symptom", "syrup", "system", "table", "tackle", "tag", + "tail", "talent", "talk", "tank", "tape", "target", + "task", "taste", "tattoo", "taxi", "teach", "team", + "tell", "ten", "tenant", "tennis", "tent", "term", + "test", "text", "thank", "that", "theme", "then", + "theory", "there", "they", "thing", "this", "thought", + "three", "thrive", "throw", "thumb", "thunder", "ticket", + "tide", "tiger", "tilt", "timber", "time", "tiny", + "tip", "tired", "tissue", "title", "toast", "tobacco", + "today", "toddler", "toe", "together", "toilet", "token", + "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", + "tooth", "top", "topic", "topple", "torch", "tornado", + "tortoise", "toss", "total", "tourist", "toward", "tower", + "town", "toy", "track", "trade", "traffic", "tragic", + "train", "transfer", "trap", "trash", "travel", "tray", + "treat", "tree", "trend", "trial", "tribe", "trick", + "trigger", "trim", "trip", "trophy", "trouble", "truck", + "true", "truly", "trumpet", "trust", "truth", "try", + "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", + "turn", "turtle", "twelve", "twenty", "twice", "twin", + "twist", "two", "type", "typical", "ugly", "umbrella", + "unable", "unaware", "uncle", "uncover", "under", "undo", + "unfair", "unfold", "unhappy", "uniform", "unique", "unit", + "universe", "unknown", "unlock", "until", "unusual", "unveil", + "update", "upgrade", "uphold", "upon", "upper", "upset", + "urban", "urge", "usage", "use", "used", "useful", + "useless", "usual", "utility", "vacant", "vacuum", "vague", + "valid", "valley", "valve", "van", "vanish", "vapor", + "various", "vast", "vault", "vehicle", "velvet", "vendor", + "venture", "venue", "verb", "verify", "version", "very", + "vessel", "veteran", "viable", "vibrant", "vicious", "victory", + "video", "view", "village", "vintage", "violin", "virtual", + "virus", "visa", "visit", "visual", "vital", "vivid", + "vocal", "voice", "void", "volcano", "volume", "vote", + "voyage", "wage", "wagon", "wait", "walk", "wall", + "walnut", "want", "warfare", "warm", "warrior", "wash", + "wasp", "waste", "water", "wave", "way", "wealth", + "weapon", "wear", "weasel", "weather", "web", "wedding", + "weekend", "weird", "welcome", "west", "wet", "whale", + "what", "wheat", "wheel", "when", "where", "whip", + "whisper", "wide", "width", "wife", "wild", "will", + "win", "window", "wine", "wing", "wink", "winner", + "winter", "wire", "wisdom", "wise", "wish", "witness", + "wolf", "woman", "wonder", "wood", "wool", "word", + "work", "world", "worry", "worth", "wrap", "wreck", + "wrestle", "wrist", "write", "wrong", "yard", "year", + "yellow", "you", "young", "youth", "zebra", "zero", + "zone", "zoo", 0, }; diff --git a/blake2_common.h b/blake2_common.h index 40c6da3b5..0a7a3ad91 100644 --- a/blake2_common.h +++ b/blake2_common.h @@ -1,39 +1,25 @@ -static inline uint32_t load32( const void *src ) -{ - uint32_t w; - memcpy(&w, src, sizeof w); - return w; +static inline uint32_t load32(const void *src) { + uint32_t w; + memcpy(&w, src, sizeof w); + return w; } -static inline uint64_t load64( const void *src ) -{ +static inline uint64_t load64(const void *src) { uint64_t w; memcpy(&w, src, sizeof w); return w; } -static inline void store16( void *dst, uint16_t w ) -{ - memcpy(dst, &w, sizeof w); -} +static inline void store16(void *dst, uint16_t w) { memcpy(dst, &w, sizeof w); } -static inline void store32( void *dst, uint32_t w ) -{ - memcpy(dst, &w, sizeof w); -} +static inline void store32(void *dst, uint32_t w) { memcpy(dst, &w, sizeof w); } -static inline void store64( void *dst, uint64_t w ) -{ - memcpy(dst, &w, sizeof w); -} +static inline void store64(void *dst, uint64_t w) { memcpy(dst, &w, sizeof w); } -static inline uint32_t rotr32( const uint32_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 32 - c ) ); +static inline uint32_t rotr32(const uint32_t w, const unsigned c) { + return (w >> c) | (w << (32 - c)); } -static inline uint64_t rotr64( const uint64_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 64 - c ) ); +static inline uint64_t rotr64(const uint64_t w, const unsigned c) { + return (w >> c) | (w << (64 - c)); } - diff --git a/cash_addr.c b/cash_addr.c index 0d7948a3b..4617cf7c6 100644 --- a/cash_addr.c +++ b/cash_addr.c @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include #include +#include #include #include "cash_addr.h" @@ -32,156 +32,158 @@ #define CHECKSUM_SIZE 8 uint64_t cashaddr_polymod_step(uint64_t pre) { - uint8_t b = pre >> 35; - return ((pre & 0x7FFFFFFFFULL) << 5) ^ - (-((b >> 0) & 1) & 0x98f2bc8e61ULL) ^ - (-((b >> 1) & 1) & 0x79b76d99e2ULL) ^ - (-((b >> 2) & 1) & 0xf33e5fb3c4ULL) ^ - (-((b >> 3) & 1) & 0xae2eabe2a8ULL) ^ - (-((b >> 4) & 1) & 0x1e4f43e470ULL); + uint8_t b = pre >> 35; + return ((pre & 0x7FFFFFFFFULL) << 5) ^ (-((b >> 0) & 1) & 0x98f2bc8e61ULL) ^ + (-((b >> 1) & 1) & 0x79b76d99e2ULL) ^ + (-((b >> 2) & 1) & 0xf33e5fb3c4ULL) ^ + (-((b >> 3) & 1) & 0xae2eabe2a8ULL) ^ + (-((b >> 4) & 1) & 0x1e4f43e470ULL); } static const char* charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; static const int8_t charset_rev[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 -}; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, + 5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, + 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, + -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, + 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1}; -int cash_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) { - uint64_t chk = 1; - size_t i = 0; - while (hrp[i] != 0) { - int ch = hrp[i]; - if (ch < 33 || ch > 126) { - return 0; - } - *(output++) = ch; - chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f); - ++i; - } - if (i + 1 + data_len + CHECKSUM_SIZE > MAX_CASHADDR_SIZE) { - return 0; +int cash_encode(char* output, const char* hrp, const uint8_t* data, + size_t data_len) { + uint64_t chk = 1; + size_t i = 0; + while (hrp[i] != 0) { + int ch = hrp[i]; + if (ch < 33 || ch > 126) { + return 0; } + *(output++) = ch; + chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f); + ++i; + } + if (i + 1 + data_len + CHECKSUM_SIZE > MAX_CASHADDR_SIZE) { + return 0; + } + chk = cashaddr_polymod_step(chk); + *(output++) = ':'; + for (i = 0; i < data_len; ++i) { + if (*data >> 5) return 0; + chk = cashaddr_polymod_step(chk) ^ (*data); + *(output++) = charset[*(data++)]; + } + for (i = 0; i < CHECKSUM_SIZE; ++i) { chk = cashaddr_polymod_step(chk); - *(output++) = ':'; - for (i = 0; i < data_len; ++i) { - if (*data >> 5) return 0; - chk = cashaddr_polymod_step(chk) ^ (*data); - *(output++) = charset[*(data++)]; - } - for (i = 0; i < CHECKSUM_SIZE; ++i) { - chk = cashaddr_polymod_step(chk); - } - chk ^= 1; - for (i = 0; i < CHECKSUM_SIZE; ++i) { - *(output++) = charset[(chk >> ((CHECKSUM_SIZE - 1 - i) * 5)) & 0x1f]; - } - *output = 0; - return 1; + } + chk ^= 1; + for (i = 0; i < CHECKSUM_SIZE; ++i) { + *(output++) = charset[(chk >> ((CHECKSUM_SIZE - 1 - i) * 5)) & 0x1f]; + } + *output = 0; + return 1; } -int cash_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input) { - uint64_t chk = 1; - size_t i; - size_t input_len = strlen(input); - size_t hrp_len; - int have_lower = 0, have_upper = 0; - if (input_len < CHECKSUM_SIZE || input_len > MAX_CASHADDR_SIZE) { - return 0; +int cash_decode(char* hrp, uint8_t* data, size_t* data_len, const char* input) { + uint64_t chk = 1; + size_t i; + size_t input_len = strlen(input); + size_t hrp_len; + int have_lower = 0, have_upper = 0; + if (input_len < CHECKSUM_SIZE || input_len > MAX_CASHADDR_SIZE) { + return 0; + } + *data_len = 0; + while (*data_len < input_len && input[(input_len - 1) - *data_len] != ':') { + ++(*data_len); + } + hrp_len = input_len - (1 + *data_len); + if (1 + *data_len >= input_len || hrp_len > MAX_HRP_SIZE || + *data_len < CHECKSUM_SIZE || + *data_len > CHECKSUM_SIZE + MAX_BASE32_SIZE) { + return 0; + } + // subtract checksum + *(data_len) -= CHECKSUM_SIZE; + for (i = 0; i < hrp_len; ++i) { + int ch = input[i]; + if (ch < 33 || ch > 126) { + return 0; } - *data_len = 0; - while (*data_len < input_len && input[(input_len - 1) - *data_len] != ':') { - ++(*data_len); + if (ch >= 'a' && ch <= 'z') { + have_lower = 1; + } else if (ch >= 'A' && ch <= 'Z') { + have_upper = 1; + ch = (ch - 'A') + 'a'; } - hrp_len = input_len - (1 + *data_len); - if (1 + *data_len >= input_len || hrp_len > MAX_HRP_SIZE || - *data_len < CHECKSUM_SIZE || *data_len > CHECKSUM_SIZE + MAX_BASE32_SIZE) { - return 0; + hrp[i] = ch; + chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f); + } + hrp[i] = 0; + chk = cashaddr_polymod_step(chk); + ++i; + while (i < input_len) { + int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]]; + if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; + if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; + if (v == -1) { + return 0; } - // subtract checksum - *(data_len) -= CHECKSUM_SIZE; - for (i = 0; i < hrp_len; ++i) { - int ch = input[i]; - if (ch < 33 || ch > 126) { - return 0; - } - if (ch >= 'a' && ch <= 'z') { - have_lower = 1; - } else if (ch >= 'A' && ch <= 'Z') { - have_upper = 1; - ch = (ch - 'A') + 'a'; - } - hrp[i] = ch; - chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f); + chk = cashaddr_polymod_step(chk) ^ v; + if (i + CHECKSUM_SIZE < input_len) { + data[i - (1 + hrp_len)] = v; } - hrp[i] = 0; - chk = cashaddr_polymod_step(chk); ++i; - while (i < input_len) { - int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]]; - if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; - if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; - if (v == -1) { - return 0; - } - chk = cashaddr_polymod_step(chk) ^ v; - if (i + CHECKSUM_SIZE < input_len) { - data[i - (1 + hrp_len)] = v; - } - ++i; - } - if (have_lower && have_upper) { - return 0; - } - return chk == 1; + } + if (have_lower && have_upper) { + return 0; + } + return chk == 1; } -static int convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { - uint32_t val = 0; - int bits = 0; - uint32_t maxv = (((uint32_t)1) << outbits) - 1; - while (inlen--) { - val = (val << inbits) | *(in++); - bits += inbits; - while (bits >= outbits) { - bits -= outbits; - out[(*outlen)++] = (val >> bits) & maxv; - } +static int convert_bits(uint8_t* out, size_t* outlen, int outbits, + const uint8_t* in, size_t inlen, int inbits, int pad) { + uint32_t val = 0; + int bits = 0; + uint32_t maxv = (((uint32_t)1) << outbits) - 1; + while (inlen--) { + val = (val << inbits) | *(in++); + bits += inbits; + while (bits >= outbits) { + bits -= outbits; + out[(*outlen)++] = (val >> bits) & maxv; } - if (pad) { - if (bits) { - out[(*outlen)++] = (val << (outbits - bits)) & maxv; - } - } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { - return 0; + } + if (pad) { + if (bits) { + out[(*outlen)++] = (val << (outbits - bits)) & maxv; } - return 1; + } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { + return 0; + } + return 1; } -int cash_addr_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) { - uint8_t base32[MAX_BASE32_SIZE]; - size_t base32len = 0; - if (data_len < 2 || data_len > MAX_DATA_SIZE) return 0; - convert_bits(base32, &base32len, 5, data, data_len, 8, 1); - return cash_encode(output, hrp, base32, base32len); +int cash_addr_encode(char* output, const char* hrp, const uint8_t* data, + size_t data_len) { + uint8_t base32[MAX_BASE32_SIZE]; + size_t base32len = 0; + if (data_len < 2 || data_len > MAX_DATA_SIZE) return 0; + convert_bits(base32, &base32len, 5, data, data_len, 8, 1); + return cash_encode(output, hrp, base32, base32len); } -int cash_addr_decode(uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { - uint8_t data[MAX_BASE32_SIZE]; - char hrp_actual[MAX_HRP_SIZE+1]; - size_t data_len; - if (!cash_decode(hrp_actual, data, &data_len, addr)) return 0; - if (data_len == 0 || data_len > MAX_BASE32_SIZE) return 0; - if (strncmp(hrp, hrp_actual, MAX_HRP_SIZE + 1) != 0) return 0; - *witdata_len = 0; - if (!convert_bits(witdata, witdata_len, 8, data, data_len, 5, 0)) return 0; - if (*witdata_len < 2 || *witdata_len > MAX_DATA_SIZE) return 0; - return 1; +int cash_addr_decode(uint8_t* witdata, size_t* witdata_len, const char* hrp, + const char* addr) { + uint8_t data[MAX_BASE32_SIZE]; + char hrp_actual[MAX_HRP_SIZE + 1]; + size_t data_len; + if (!cash_decode(hrp_actual, data, &data_len, addr)) return 0; + if (data_len == 0 || data_len > MAX_BASE32_SIZE) return 0; + if (strncmp(hrp, hrp_actual, MAX_HRP_SIZE + 1) != 0) return 0; + *witdata_len = 0; + if (!convert_bits(witdata, witdata_len, 8, data, data_len, 5, 0)) return 0; + if (*witdata_len < 2 || *witdata_len > MAX_DATA_SIZE) return 0; + return 1; } diff --git a/cash_addr.h b/cash_addr.h index e88e76dd9..fd7dd44f8 100644 --- a/cash_addr.h +++ b/cash_addr.h @@ -34,30 +34,20 @@ * prog_len: Number of data bytes in prog. * Returns 1 if successful. */ -int cash_addr_encode( - char *output, - const char *hrp, - const uint8_t *prog, - size_t prog_len -); +int cash_addr_encode(char *output, const char *hrp, const uint8_t *prog, + size_t prog_len); /** Decode a CashAddr address * * Out: prog: Pointer to a buffer of size 65 that will be updated to * contain the witness program bytes. - * prog_len: Pointer to a size_t that will be updated to contain the length - * of bytes in prog. - * hrp: Pointer to the null-terminated human readable part that is - * expected (chain/network specific). - * addr: Pointer to the null-terminated address. - * Returns 1 if successful. + * prog_len: Pointer to a size_t that will be updated to contain the + * length of bytes in prog. hrp: Pointer to the null-terminated human + * readable part that is expected (chain/network specific). addr: Pointer to + * the null-terminated address. Returns 1 if successful. */ -int cash_addr_decode( - uint8_t* prog, - size_t* prog_len, - const char* hrp, - const char* addr -); +int cash_addr_decode(uint8_t *prog, size_t *prog_len, const char *hrp, + const char *addr); /** Encode a Cash string * @@ -68,12 +58,8 @@ int cash_addr_decode( * data_len: Length of the data array. * Returns 1 if successful. */ -int cash_encode( - char *output, - const char *hrp, - const uint8_t *data, - size_t data_len -); +int cash_encode(char *output, const char *hrp, const uint8_t *data, + size_t data_len); /** Decode a Cash string * @@ -86,11 +72,6 @@ int cash_encode( * In: input: Pointer to a null-terminated Cash string. * Returns 1 if succesful. */ -int cash_decode( - char *hrp, - uint8_t *data, - size_t *data_len, - const char *input -); +int cash_decode(char *hrp, uint8_t *data, size_t *data_len, const char *input); #endif diff --git a/ecdsa.c b/ecdsa.c index c0717902a..f566cdd97 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -22,705 +22,698 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include -#include #include "address.h" +#include "base58.h" #include "bignum.h" -#include "rand.h" -#include "hmac.h" #include "ecdsa.h" -#include "base58.h" -#include "secp256k1.h" -#include "rfc6979.h" +#include "hmac.h" #include "memzero.h" +#include "rand.h" +#include "rfc6979.h" +#include "secp256k1.h" // Set cp2 = cp1 -void point_copy(const curve_point *cp1, curve_point *cp2) -{ - *cp2 = *cp1; -} +void point_copy(const curve_point *cp1, curve_point *cp2) { *cp2 = *cp1; } // cp2 = cp1 + cp2 -void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2) -{ - bignum256 lambda, inv, xr, yr; - - if (point_is_infinity(cp1)) { - return; - } - if (point_is_infinity(cp2)) { - point_copy(cp1, cp2); - return; - } - if (point_is_equal(cp1, cp2)) { - point_double(curve, cp2); - return; - } - if (point_is_negative_of(cp1, cp2)) { - point_set_infinity(cp2); - return; - } - - bn_subtractmod(&(cp2->x), &(cp1->x), &inv, &curve->prime); - bn_inverse(&inv, &curve->prime); - bn_subtractmod(&(cp2->y), &(cp1->y), &lambda, &curve->prime); - bn_multiply(&inv, &lambda, &curve->prime); - - // xr = lambda^2 - x1 - x2 - xr = lambda; - bn_multiply(&xr, &xr, &curve->prime); - yr = cp1->x; - bn_addmod(&yr, &(cp2->x), &curve->prime); - bn_subtractmod(&xr, &yr, &xr, &curve->prime); - bn_fast_mod(&xr, &curve->prime); - bn_mod(&xr, &curve->prime); - - // yr = lambda (x1 - xr) - y1 - bn_subtractmod(&(cp1->x), &xr, &yr, &curve->prime); - bn_multiply(&lambda, &yr, &curve->prime); - bn_subtractmod(&yr, &(cp1->y), &yr, &curve->prime); - bn_fast_mod(&yr, &curve->prime); - bn_mod(&yr, &curve->prime); - - cp2->x = xr; - cp2->y = yr; +void point_add(const ecdsa_curve *curve, const curve_point *cp1, + curve_point *cp2) { + bignum256 lambda, inv, xr, yr; + + if (point_is_infinity(cp1)) { + return; + } + if (point_is_infinity(cp2)) { + point_copy(cp1, cp2); + return; + } + if (point_is_equal(cp1, cp2)) { + point_double(curve, cp2); + return; + } + if (point_is_negative_of(cp1, cp2)) { + point_set_infinity(cp2); + return; + } + + bn_subtractmod(&(cp2->x), &(cp1->x), &inv, &curve->prime); + bn_inverse(&inv, &curve->prime); + bn_subtractmod(&(cp2->y), &(cp1->y), &lambda, &curve->prime); + bn_multiply(&inv, &lambda, &curve->prime); + + // xr = lambda^2 - x1 - x2 + xr = lambda; + bn_multiply(&xr, &xr, &curve->prime); + yr = cp1->x; + bn_addmod(&yr, &(cp2->x), &curve->prime); + bn_subtractmod(&xr, &yr, &xr, &curve->prime); + bn_fast_mod(&xr, &curve->prime); + bn_mod(&xr, &curve->prime); + + // yr = lambda (x1 - xr) - y1 + bn_subtractmod(&(cp1->x), &xr, &yr, &curve->prime); + bn_multiply(&lambda, &yr, &curve->prime); + bn_subtractmod(&yr, &(cp1->y), &yr, &curve->prime); + bn_fast_mod(&yr, &curve->prime); + bn_mod(&yr, &curve->prime); + + cp2->x = xr; + cp2->y = yr; } // cp = cp + cp -void point_double(const ecdsa_curve *curve, curve_point *cp) -{ - bignum256 lambda, xr, yr; - - if (point_is_infinity(cp)) { - return; - } - if (bn_is_zero(&(cp->y))) { - point_set_infinity(cp); - return; - } - - // lambda = (3 x^2 + a) / (2 y) - lambda = cp->y; - bn_mult_k(&lambda, 2, &curve->prime); - bn_inverse(&lambda, &curve->prime); - - xr = cp->x; - bn_multiply(&xr, &xr, &curve->prime); - bn_mult_k(&xr, 3, &curve->prime); - bn_subi(&xr, -curve->a, &curve->prime); - bn_multiply(&xr, &lambda, &curve->prime); - - // xr = lambda^2 - 2*x - xr = lambda; - bn_multiply(&xr, &xr, &curve->prime); - yr = cp->x; - bn_lshift(&yr); - bn_subtractmod(&xr, &yr, &xr, &curve->prime); - bn_fast_mod(&xr, &curve->prime); - bn_mod(&xr, &curve->prime); - - // yr = lambda (x - xr) - y - bn_subtractmod(&(cp->x), &xr, &yr, &curve->prime); - bn_multiply(&lambda, &yr, &curve->prime); - bn_subtractmod(&yr, &(cp->y), &yr, &curve->prime); - bn_fast_mod(&yr, &curve->prime); - bn_mod(&yr, &curve->prime); - - cp->x = xr; - cp->y = yr; +void point_double(const ecdsa_curve *curve, curve_point *cp) { + bignum256 lambda, xr, yr; + + if (point_is_infinity(cp)) { + return; + } + if (bn_is_zero(&(cp->y))) { + point_set_infinity(cp); + return; + } + + // lambda = (3 x^2 + a) / (2 y) + lambda = cp->y; + bn_mult_k(&lambda, 2, &curve->prime); + bn_inverse(&lambda, &curve->prime); + + xr = cp->x; + bn_multiply(&xr, &xr, &curve->prime); + bn_mult_k(&xr, 3, &curve->prime); + bn_subi(&xr, -curve->a, &curve->prime); + bn_multiply(&xr, &lambda, &curve->prime); + + // xr = lambda^2 - 2*x + xr = lambda; + bn_multiply(&xr, &xr, &curve->prime); + yr = cp->x; + bn_lshift(&yr); + bn_subtractmod(&xr, &yr, &xr, &curve->prime); + bn_fast_mod(&xr, &curve->prime); + bn_mod(&xr, &curve->prime); + + // yr = lambda (x - xr) - y + bn_subtractmod(&(cp->x), &xr, &yr, &curve->prime); + bn_multiply(&lambda, &yr, &curve->prime); + bn_subtractmod(&yr, &(cp->y), &yr, &curve->prime); + bn_fast_mod(&yr, &curve->prime); + bn_mod(&yr, &curve->prime); + + cp->x = xr; + cp->y = yr; } // set point to internal representation of point at infinity -void point_set_infinity(curve_point *p) -{ - bn_zero(&(p->x)); - bn_zero(&(p->y)); +void point_set_infinity(curve_point *p) { + bn_zero(&(p->x)); + bn_zero(&(p->y)); } // return true iff p represent point at infinity // both coords are zero in internal representation -int point_is_infinity(const curve_point *p) -{ - return bn_is_zero(&(p->x)) && bn_is_zero(&(p->y)); +int point_is_infinity(const curve_point *p) { + return bn_is_zero(&(p->x)) && bn_is_zero(&(p->y)); } // return true iff both points are equal -int point_is_equal(const curve_point *p, const curve_point *q) -{ - return bn_is_equal(&(p->x), &(q->x)) && bn_is_equal(&(p->y), &(q->y)); +int point_is_equal(const curve_point *p, const curve_point *q) { + return bn_is_equal(&(p->x), &(q->x)) && bn_is_equal(&(p->y), &(q->y)); } // returns true iff p == -q // expects p and q be valid points on curve other than point at infinity -int point_is_negative_of(const curve_point *p, const curve_point *q) -{ - // if P == (x, y), then -P would be (x, -y) on this curve - if (!bn_is_equal(&(p->x), &(q->x))) { - return 0; - } - - // we shouldn't hit this for a valid point - if (bn_is_zero(&(p->y))) { - return 0; - } - - return !bn_is_equal(&(p->y), &(q->y)); +int point_is_negative_of(const curve_point *p, const curve_point *q) { + // if P == (x, y), then -P would be (x, -y) on this curve + if (!bn_is_equal(&(p->x), &(q->x))) { + return 0; + } + + // we shouldn't hit this for a valid point + if (bn_is_zero(&(p->y))) { + return 0; + } + + return !bn_is_equal(&(p->y), &(q->y)); } // Negate a (modulo prime) if cond is 0xffffffff, keep it if cond is 0. // The timing of this function does not depend on cond. -void conditional_negate(uint32_t cond, bignum256 *a, const bignum256 *prime) -{ - int j; - uint32_t tmp = 1; - assert(a->val[8] < 0x20000); - for (j = 0; j < 8; j++) { - tmp += 0x3fffffff + 2*prime->val[j] - a->val[j]; - a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); - tmp >>= 30; - } - tmp += 0x3fffffff + 2*prime->val[j] - a->val[j]; - a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); - assert(a->val[8] < 0x20000); +void conditional_negate(uint32_t cond, bignum256 *a, const bignum256 *prime) { + int j; + uint32_t tmp = 1; + assert(a->val[8] < 0x20000); + for (j = 0; j < 8; j++) { + tmp += 0x3fffffff + 2 * prime->val[j] - a->val[j]; + a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); + tmp >>= 30; + } + tmp += 0x3fffffff + 2 * prime->val[j] - a->val[j]; + a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); + assert(a->val[8] < 0x20000); } typedef struct jacobian_curve_point { - bignum256 x, y, z; + bignum256 x, y, z; } jacobian_curve_point; // generate random K for signing/side-channel noise static void generate_k_random(bignum256 *k, const bignum256 *prime) { - do { - int i; - for (i = 0; i < 8; i++) { - k->val[i] = random32() & 0x3FFFFFFF; - } - k->val[8] = random32() & 0xFFFF; - // check that k is in range and not zero. - } while (bn_is_zero(k) || !bn_is_less(k, prime)); + do { + int i; + for (i = 0; i < 8; i++) { + k->val[i] = random32() & 0x3FFFFFFF; + } + k->val[8] = random32() & 0xFFFF; + // check that k is in range and not zero. + } while (bn_is_zero(k) || !bn_is_less(k, prime)); } -void curve_to_jacobian(const curve_point *p, jacobian_curve_point *jp, const bignum256 *prime) { - // randomize z coordinate - generate_k_random(&jp->z, prime); +void curve_to_jacobian(const curve_point *p, jacobian_curve_point *jp, + const bignum256 *prime) { + // randomize z coordinate + generate_k_random(&jp->z, prime); - jp->x = jp->z; - bn_multiply(&jp->z, &jp->x, prime); - // x = z^2 - jp->y = jp->x; - bn_multiply(&jp->z, &jp->y, prime); - // y = z^3 + jp->x = jp->z; + bn_multiply(&jp->z, &jp->x, prime); + // x = z^2 + jp->y = jp->x; + bn_multiply(&jp->z, &jp->y, prime); + // y = z^3 - bn_multiply(&p->x, &jp->x, prime); - bn_multiply(&p->y, &jp->y, prime); + bn_multiply(&p->x, &jp->x, prime); + bn_multiply(&p->y, &jp->y, prime); } -void jacobian_to_curve(const jacobian_curve_point *jp, curve_point *p, const bignum256 *prime) { - p->y = jp->z; - bn_inverse(&p->y, prime); - // p->y = z^-1 - p->x = p->y; - bn_multiply(&p->x, &p->x, prime); - // p->x = z^-2 - bn_multiply(&p->x, &p->y, prime); - // p->y = z^-3 - bn_multiply(&jp->x, &p->x, prime); - // p->x = jp->x * z^-2 - bn_multiply(&jp->y, &p->y, prime); - // p->y = jp->y * z^-3 - bn_mod(&p->x, prime); - bn_mod(&p->y, prime); +void jacobian_to_curve(const jacobian_curve_point *jp, curve_point *p, + const bignum256 *prime) { + p->y = jp->z; + bn_inverse(&p->y, prime); + // p->y = z^-1 + p->x = p->y; + bn_multiply(&p->x, &p->x, prime); + // p->x = z^-2 + bn_multiply(&p->x, &p->y, prime); + // p->y = z^-3 + bn_multiply(&jp->x, &p->x, prime); + // p->x = jp->x * z^-2 + bn_multiply(&jp->y, &p->y, prime); + // p->y = jp->y * z^-3 + bn_mod(&p->x, prime); + bn_mod(&p->y, prime); } -void point_jacobian_add(const curve_point *p1, jacobian_curve_point *p2, const ecdsa_curve *curve) { - bignum256 r, h, r2; - bignum256 hcby, hsqx; - bignum256 xz, yz, az; - int is_doubling; - const bignum256 *prime = &curve->prime; - int a = curve->a; - - assert (-3 <= a && a <= 0); - - /* First we bring p1 to the same denominator: - * x1' := x1 * z2^2 - * y1' := y1 * z2^3 - */ - /* - * lambda = ((y1' - y2)/z2^3) / ((x1' - x2)/z2^2) - * = (y1' - y2) / (x1' - x2) z2 - * x3/z3^2 = lambda^2 - (x1' + x2)/z2^2 - * y3/z3^3 = 1/2 lambda * (2x3/z3^2 - (x1' + x2)/z2^2) + (y1'+y2)/z2^3 - * - * For the special case x1=x2, y1=y2 (doubling) we have - * lambda = 3/2 ((x2/z2^2)^2 + a) / (y2/z2^3) - * = 3/2 (x2^2 + a*z2^4) / y2*z2) - * - * to get rid of fraction we write lambda as - * lambda = r / (h*z2) - * with r = is_doubling ? 3/2 x2^2 + az2^4 : (y1 - y2) - * h = is_doubling ? y1+y2 : (x1 - x2) - * - * With z3 = h*z2 (the denominator of lambda) - * we get x3 = lambda^2*z3^2 - (x1' + x2)/z2^2*z3^2 - * = r^2 - h^2 * (x1' + x2) - * and y3 = 1/2 r * (2x3 - h^2*(x1' + x2)) + h^3*(y1' + y2) - */ - - /* h = x1 - x2 - * r = y1 - y2 - * x3 = r^2 - h^3 - 2*h^2*x2 - * y3 = r*(h^2*x2 - x3) - h^3*y2 - * z3 = h*z2 - */ - - xz = p2->z; - bn_multiply(&xz, &xz, prime); // xz = z2^2 - yz = p2->z; - bn_multiply(&xz, &yz, prime); // yz = z2^3 - - if (a != 0) { - az = xz; - bn_multiply(&az, &az, prime); // az = z2^4 - bn_mult_k(&az, -a, prime); // az = -az2^4 - } - - bn_multiply(&p1->x, &xz, prime); // xz = x1' = x1*z2^2; - h = xz; - bn_subtractmod(&h, &p2->x, &h, prime); - bn_fast_mod(&h, prime); - // h = x1' - x2; - - bn_add(&xz, &p2->x); - // xz = x1' + x2 - - // check for h == 0 % prime. Note that h never normalizes to - // zero, since h = x1' + 2*prime - x2 > 0 and a positive - // multiple of prime is always normalized to prime by - // bn_fast_mod. - is_doubling = bn_is_equal(&h, prime); - - bn_multiply(&p1->y, &yz, prime); // yz = y1' = y1*z2^3; - bn_subtractmod(&yz, &p2->y, &r, prime); - // r = y1' - y2; - - bn_add(&yz, &p2->y); - // yz = y1' + y2 - - r2 = p2->x; - bn_multiply(&r2, &r2, prime); - bn_mult_k(&r2, 3, prime); - - if (a != 0) { - // subtract -a z2^4, i.e, add a z2^4 - bn_subtractmod(&r2, &az, &r2, prime); - } - bn_cmov(&r, is_doubling, &r2, &r); - bn_cmov(&h, is_doubling, &yz, &h); - - - // hsqx = h^2 - hsqx = h; - bn_multiply(&hsqx, &hsqx, prime); - - // hcby = h^3 - hcby = h; - bn_multiply(&hsqx, &hcby, prime); - - // hsqx = h^2 * (x1 + x2) - bn_multiply(&xz, &hsqx, prime); - - // hcby = h^3 * (y1 + y2) - bn_multiply(&yz, &hcby, prime); - - // z3 = h*z2 - bn_multiply(&h, &p2->z, prime); - - // x3 = r^2 - h^2 (x1 + x2) - p2->x = r; - bn_multiply(&p2->x, &p2->x, prime); - bn_subtractmod(&p2->x, &hsqx, &p2->x, prime); - bn_fast_mod(&p2->x, prime); - - // y3 = 1/2 (r*(h^2 (x1 + x2) - 2x3) - h^3 (y1 + y2)) - bn_subtractmod(&hsqx, &p2->x, &p2->y, prime); - bn_subtractmod(&p2->y, &p2->x, &p2->y, prime); - bn_multiply(&r, &p2->y, prime); - bn_subtractmod(&p2->y, &hcby, &p2->y, prime); - bn_mult_half(&p2->y, prime); - bn_fast_mod(&p2->y, prime); +void point_jacobian_add(const curve_point *p1, jacobian_curve_point *p2, + const ecdsa_curve *curve) { + bignum256 r, h, r2; + bignum256 hcby, hsqx; + bignum256 xz, yz, az; + int is_doubling; + const bignum256 *prime = &curve->prime; + int a = curve->a; + + assert(-3 <= a && a <= 0); + + /* First we bring p1 to the same denominator: + * x1' := x1 * z2^2 + * y1' := y1 * z2^3 + */ + /* + * lambda = ((y1' - y2)/z2^3) / ((x1' - x2)/z2^2) + * = (y1' - y2) / (x1' - x2) z2 + * x3/z3^2 = lambda^2 - (x1' + x2)/z2^2 + * y3/z3^3 = 1/2 lambda * (2x3/z3^2 - (x1' + x2)/z2^2) + (y1'+y2)/z2^3 + * + * For the special case x1=x2, y1=y2 (doubling) we have + * lambda = 3/2 ((x2/z2^2)^2 + a) / (y2/z2^3) + * = 3/2 (x2^2 + a*z2^4) / y2*z2) + * + * to get rid of fraction we write lambda as + * lambda = r / (h*z2) + * with r = is_doubling ? 3/2 x2^2 + az2^4 : (y1 - y2) + * h = is_doubling ? y1+y2 : (x1 - x2) + * + * With z3 = h*z2 (the denominator of lambda) + * we get x3 = lambda^2*z3^2 - (x1' + x2)/z2^2*z3^2 + * = r^2 - h^2 * (x1' + x2) + * and y3 = 1/2 r * (2x3 - h^2*(x1' + x2)) + h^3*(y1' + y2) + */ + + /* h = x1 - x2 + * r = y1 - y2 + * x3 = r^2 - h^3 - 2*h^2*x2 + * y3 = r*(h^2*x2 - x3) - h^3*y2 + * z3 = h*z2 + */ + + xz = p2->z; + bn_multiply(&xz, &xz, prime); // xz = z2^2 + yz = p2->z; + bn_multiply(&xz, &yz, prime); // yz = z2^3 + + if (a != 0) { + az = xz; + bn_multiply(&az, &az, prime); // az = z2^4 + bn_mult_k(&az, -a, prime); // az = -az2^4 + } + + bn_multiply(&p1->x, &xz, prime); // xz = x1' = x1*z2^2; + h = xz; + bn_subtractmod(&h, &p2->x, &h, prime); + bn_fast_mod(&h, prime); + // h = x1' - x2; + + bn_add(&xz, &p2->x); + // xz = x1' + x2 + + // check for h == 0 % prime. Note that h never normalizes to + // zero, since h = x1' + 2*prime - x2 > 0 and a positive + // multiple of prime is always normalized to prime by + // bn_fast_mod. + is_doubling = bn_is_equal(&h, prime); + + bn_multiply(&p1->y, &yz, prime); // yz = y1' = y1*z2^3; + bn_subtractmod(&yz, &p2->y, &r, prime); + // r = y1' - y2; + + bn_add(&yz, &p2->y); + // yz = y1' + y2 + + r2 = p2->x; + bn_multiply(&r2, &r2, prime); + bn_mult_k(&r2, 3, prime); + + if (a != 0) { + // subtract -a z2^4, i.e, add a z2^4 + bn_subtractmod(&r2, &az, &r2, prime); + } + bn_cmov(&r, is_doubling, &r2, &r); + bn_cmov(&h, is_doubling, &yz, &h); + + // hsqx = h^2 + hsqx = h; + bn_multiply(&hsqx, &hsqx, prime); + + // hcby = h^3 + hcby = h; + bn_multiply(&hsqx, &hcby, prime); + + // hsqx = h^2 * (x1 + x2) + bn_multiply(&xz, &hsqx, prime); + + // hcby = h^3 * (y1 + y2) + bn_multiply(&yz, &hcby, prime); + + // z3 = h*z2 + bn_multiply(&h, &p2->z, prime); + + // x3 = r^2 - h^2 (x1 + x2) + p2->x = r; + bn_multiply(&p2->x, &p2->x, prime); + bn_subtractmod(&p2->x, &hsqx, &p2->x, prime); + bn_fast_mod(&p2->x, prime); + + // y3 = 1/2 (r*(h^2 (x1 + x2) - 2x3) - h^3 (y1 + y2)) + bn_subtractmod(&hsqx, &p2->x, &p2->y, prime); + bn_subtractmod(&p2->y, &p2->x, &p2->y, prime); + bn_multiply(&r, &p2->y, prime); + bn_subtractmod(&p2->y, &hcby, &p2->y, prime); + bn_mult_half(&p2->y, prime); + bn_fast_mod(&p2->y, prime); } void point_jacobian_double(jacobian_curve_point *p, const ecdsa_curve *curve) { - bignum256 az4, m, msq, ysq, xysq; - const bignum256 *prime = &curve->prime; - - assert (-3 <= curve->a && curve->a <= 0); - /* usual algorithm: - * - * lambda = (3((x/z^2)^2 + a) / 2y/z^3) = (3x^2 + az^4)/2yz - * x3/z3^2 = lambda^2 - 2x/z^2 - * y3/z3^3 = lambda * (x/z^2 - x3/z3^2) - y/z^3 - * - * to get rid of fraction we set - * m = (3 x^2 + az^4) / 2 - * Hence, - * lambda = m / yz = m / z3 - * - * With z3 = yz (the denominator of lambda) - * we get x3 = lambda^2*z3^2 - 2*x/z^2*z3^2 - * = m^2 - 2*xy^2 - * and y3 = (lambda * (x/z^2 - x3/z3^2) - y/z^3) * z3^3 - * = m * (xy^2 - x3) - y^4 - */ - - /* m = (3*x^2 + a z^4) / 2 - * x3 = m^2 - 2*xy^2 - * y3 = m*(xy^2 - x3) - 8y^4 - * z3 = y*z - */ - - m = p->x; - bn_multiply(&m, &m, prime); - bn_mult_k(&m, 3, prime); - - az4 = p->z; - bn_multiply(&az4, &az4, prime); - bn_multiply(&az4, &az4, prime); - bn_mult_k(&az4, -curve->a, prime); - bn_subtractmod(&m, &az4, &m, prime); - bn_mult_half(&m, prime); - - // msq = m^2 - msq = m; - bn_multiply(&msq, &msq, prime); - // ysq = y^2 - ysq = p->y; - bn_multiply(&ysq, &ysq, prime); - // xysq = xy^2 - xysq = p->x; - bn_multiply(&ysq, &xysq, prime); - - // z3 = yz - bn_multiply(&p->y, &p->z, prime); - - // x3 = m^2 - 2*xy^2 - p->x = xysq; - bn_lshift(&p->x); - bn_fast_mod(&p->x, prime); - bn_subtractmod(&msq, &p->x, &p->x, prime); - bn_fast_mod(&p->x, prime); - - // y3 = m*(xy^2 - x3) - y^4 - bn_subtractmod(&xysq, &p->x, &p->y, prime); - bn_multiply(&m, &p->y, prime); - bn_multiply(&ysq, &ysq, prime); - bn_subtractmod(&p->y, &ysq, &p->y, prime); - bn_fast_mod(&p->y, prime); + bignum256 az4, m, msq, ysq, xysq; + const bignum256 *prime = &curve->prime; + + assert(-3 <= curve->a && curve->a <= 0); + /* usual algorithm: + * + * lambda = (3((x/z^2)^2 + a) / 2y/z^3) = (3x^2 + az^4)/2yz + * x3/z3^2 = lambda^2 - 2x/z^2 + * y3/z3^3 = lambda * (x/z^2 - x3/z3^2) - y/z^3 + * + * to get rid of fraction we set + * m = (3 x^2 + az^4) / 2 + * Hence, + * lambda = m / yz = m / z3 + * + * With z3 = yz (the denominator of lambda) + * we get x3 = lambda^2*z3^2 - 2*x/z^2*z3^2 + * = m^2 - 2*xy^2 + * and y3 = (lambda * (x/z^2 - x3/z3^2) - y/z^3) * z3^3 + * = m * (xy^2 - x3) - y^4 + */ + + /* m = (3*x^2 + a z^4) / 2 + * x3 = m^2 - 2*xy^2 + * y3 = m*(xy^2 - x3) - 8y^4 + * z3 = y*z + */ + + m = p->x; + bn_multiply(&m, &m, prime); + bn_mult_k(&m, 3, prime); + + az4 = p->z; + bn_multiply(&az4, &az4, prime); + bn_multiply(&az4, &az4, prime); + bn_mult_k(&az4, -curve->a, prime); + bn_subtractmod(&m, &az4, &m, prime); + bn_mult_half(&m, prime); + + // msq = m^2 + msq = m; + bn_multiply(&msq, &msq, prime); + // ysq = y^2 + ysq = p->y; + bn_multiply(&ysq, &ysq, prime); + // xysq = xy^2 + xysq = p->x; + bn_multiply(&ysq, &xysq, prime); + + // z3 = yz + bn_multiply(&p->y, &p->z, prime); + + // x3 = m^2 - 2*xy^2 + p->x = xysq; + bn_lshift(&p->x); + bn_fast_mod(&p->x, prime); + bn_subtractmod(&msq, &p->x, &p->x, prime); + bn_fast_mod(&p->x, prime); + + // y3 = m*(xy^2 - x3) - y^4 + bn_subtractmod(&xysq, &p->x, &p->y, prime); + bn_multiply(&m, &p->y, prime); + bn_multiply(&ysq, &ysq, prime); + bn_subtractmod(&p->y, &ysq, &p->y, prime); + bn_fast_mod(&p->y, prime); } // res = k * p -void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res) -{ - // this algorithm is loosely based on - // Katsuyuki Okeya and Tsuyoshi Takagi, The Width-w NAF Method Provides - // Small Memory and Fast Elliptic Scalar Multiplications Secure against - // Side Channel Attacks. - assert (bn_is_less(k, &curve->order)); - - int i, j; - static CONFIDENTIAL bignum256 a; - uint32_t *aptr; - uint32_t abits; - int ashift; - uint32_t is_even = (k->val[0] & 1) - 1; - uint32_t bits, sign, nsign; - static CONFIDENTIAL jacobian_curve_point jres; - curve_point pmult[8]; - const bignum256 *prime = &curve->prime; - - // is_even = 0xffffffff if k is even, 0 otherwise. - - // add 2^256. - // make number odd: subtract curve->order if even - uint32_t tmp = 1; - uint32_t is_non_zero = 0; - for (j = 0; j < 8; j++) { - is_non_zero |= k->val[j]; - tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); - a.val[j] = tmp & 0x3fffffff; - tmp >>= 30; - } - is_non_zero |= k->val[j]; - a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); - assert((a.val[0] & 1) != 0); - - // special case 0*p: just return zero. We don't care about constant time. - if (!is_non_zero) { - point_set_infinity(res); - return; - } - - // Now a = k + 2^256 (mod curve->order) and a is odd. - // - // The idea is to bring the new a into the form. - // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. - // a[0] is odd, since a is odd. If a[i] would be even, we can - // add 1 to it and subtract 16 from a[i-1]. Afterwards, - // a[64] = 1, which is the 2^256 that we added before. - // - // Since k = a - 2^256 (mod curve->order), we can compute - // k*p = sum_{i=0..63} a[i] 16^i * p - // - // We compute |a[i]| * p in advance for all possible - // values of |a[i]| * p. pmult[i] = (2*i+1) * p - // We compute p, 3*p, ..., 15*p and store it in the table pmult. - // store p^2 temporarily in pmult[7] - pmult[7] = *p; - point_double(curve, &pmult[7]); - // compute 3*p, etc by repeatedly adding p^2. - pmult[0] = *p; - for (i = 1; i < 8; i++) { - pmult[i] = pmult[7]; - point_add(curve, &pmult[i-1], &pmult[i]); - } - - // now compute res = sum_{i=0..63} a[i] * 16^i * p step by step, - // starting with i = 63. - // initialize jres = |a[63]| * p. - // Note that a[i] = a>>(4*i) & 0xf if (a&0x10) != 0 - // and - (16 - (a>>(4*i) & 0xf)) otherwise. We can compute this as - // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 - // since a is odd. - aptr = &a.val[8]; - abits = *aptr; - ashift = 12; - bits = abits >> ashift; - sign = (bits >> 4) - 1; - bits ^= sign; - bits &= 15; - curve_to_jacobian(&pmult[bits>>1], &jres, prime); - for (i = 62; i >= 0; i--) { - // sign = sign(a[i+1]) (0xffffffff for negative, 0 for positive) - // invariant jres = (-1)^sign sum_{j=i+1..63} (a[j] * 16^{j-i-1} * p) - // abits >> (ashift - 4) = lowbits(a >> (i*4)) - - point_jacobian_double(&jres, curve); - point_jacobian_double(&jres, curve); - point_jacobian_double(&jres, curve); - point_jacobian_double(&jres, curve); - - // get lowest 5 bits of a >> (i*4). - ashift -= 4; - if (ashift < 0) { - // the condition only depends on the iteration number and - // leaks no private information to a side-channel. - bits = abits << (-ashift); - abits = *(--aptr); - ashift += 30; - bits |= abits >> ashift; - } else { - bits = abits >> ashift; - } - bits &= 31; - nsign = (bits >> 4) - 1; - bits ^= nsign; - bits &= 15; - - // negate last result to make signs of this round and the - // last round equal. - conditional_negate(sign ^ nsign, &jres.z, prime); - - // add odd factor - point_jacobian_add(&pmult[bits >> 1], &jres, curve); - sign = nsign; - } - conditional_negate(sign, &jres.z, prime); - jacobian_to_curve(&jres, res, prime); - memzero(&a, sizeof(a)); - memzero(&jres, sizeof(jres)); +void point_multiply(const ecdsa_curve *curve, const bignum256 *k, + const curve_point *p, curve_point *res) { + // this algorithm is loosely based on + // Katsuyuki Okeya and Tsuyoshi Takagi, The Width-w NAF Method Provides + // Small Memory and Fast Elliptic Scalar Multiplications Secure against + // Side Channel Attacks. + assert(bn_is_less(k, &curve->order)); + + int i, j; + static CONFIDENTIAL bignum256 a; + uint32_t *aptr; + uint32_t abits; + int ashift; + uint32_t is_even = (k->val[0] & 1) - 1; + uint32_t bits, sign, nsign; + static CONFIDENTIAL jacobian_curve_point jres; + curve_point pmult[8]; + const bignum256 *prime = &curve->prime; + + // is_even = 0xffffffff if k is even, 0 otherwise. + + // add 2^256. + // make number odd: subtract curve->order if even + uint32_t tmp = 1; + uint32_t is_non_zero = 0; + for (j = 0; j < 8; j++) { + is_non_zero |= k->val[j]; + tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); + a.val[j] = tmp & 0x3fffffff; + tmp >>= 30; + } + is_non_zero |= k->val[j]; + a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); + assert((a.val[0] & 1) != 0); + + // special case 0*p: just return zero. We don't care about constant time. + if (!is_non_zero) { + point_set_infinity(res); + return; + } + + // Now a = k + 2^256 (mod curve->order) and a is odd. + // + // The idea is to bring the new a into the form. + // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. + // a[0] is odd, since a is odd. If a[i] would be even, we can + // add 1 to it and subtract 16 from a[i-1]. Afterwards, + // a[64] = 1, which is the 2^256 that we added before. + // + // Since k = a - 2^256 (mod curve->order), we can compute + // k*p = sum_{i=0..63} a[i] 16^i * p + // + // We compute |a[i]| * p in advance for all possible + // values of |a[i]| * p. pmult[i] = (2*i+1) * p + // We compute p, 3*p, ..., 15*p and store it in the table pmult. + // store p^2 temporarily in pmult[7] + pmult[7] = *p; + point_double(curve, &pmult[7]); + // compute 3*p, etc by repeatedly adding p^2. + pmult[0] = *p; + for (i = 1; i < 8; i++) { + pmult[i] = pmult[7]; + point_add(curve, &pmult[i - 1], &pmult[i]); + } + + // now compute res = sum_{i=0..63} a[i] * 16^i * p step by step, + // starting with i = 63. + // initialize jres = |a[63]| * p. + // Note that a[i] = a>>(4*i) & 0xf if (a&0x10) != 0 + // and - (16 - (a>>(4*i) & 0xf)) otherwise. We can compute this as + // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 + // since a is odd. + aptr = &a.val[8]; + abits = *aptr; + ashift = 12; + bits = abits >> ashift; + sign = (bits >> 4) - 1; + bits ^= sign; + bits &= 15; + curve_to_jacobian(&pmult[bits >> 1], &jres, prime); + for (i = 62; i >= 0; i--) { + // sign = sign(a[i+1]) (0xffffffff for negative, 0 for positive) + // invariant jres = (-1)^sign sum_{j=i+1..63} (a[j] * 16^{j-i-1} * p) + // abits >> (ashift - 4) = lowbits(a >> (i*4)) + + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + + // get lowest 5 bits of a >> (i*4). + ashift -= 4; + if (ashift < 0) { + // the condition only depends on the iteration number and + // leaks no private information to a side-channel. + bits = abits << (-ashift); + abits = *(--aptr); + ashift += 30; + bits |= abits >> ashift; + } else { + bits = abits >> ashift; + } + bits &= 31; + nsign = (bits >> 4) - 1; + bits ^= nsign; + bits &= 15; + + // negate last result to make signs of this round and the + // last round equal. + conditional_negate(sign ^ nsign, &jres.z, prime); + + // add odd factor + point_jacobian_add(&pmult[bits >> 1], &jres, curve); + sign = nsign; + } + conditional_negate(sign, &jres.z, prime); + jacobian_to_curve(&jres, res, prime); + memzero(&a, sizeof(a)); + memzero(&jres, sizeof(jres)); } #if USE_PRECOMPUTED_CP // res = k * G // k must be a normalized number with 0 <= k < curve->order -void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res) -{ - assert (bn_is_less(k, &curve->order)); - - int i, j; - static CONFIDENTIAL bignum256 a; - uint32_t is_even = (k->val[0] & 1) - 1; - uint32_t lowbits; - static CONFIDENTIAL jacobian_curve_point jres; - const bignum256 *prime = &curve->prime; - - // is_even = 0xffffffff if k is even, 0 otherwise. - - // add 2^256. - // make number odd: subtract curve->order if even - uint32_t tmp = 1; - uint32_t is_non_zero = 0; - for (j = 0; j < 8; j++) { - is_non_zero |= k->val[j]; - tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); - a.val[j] = tmp & 0x3fffffff; - tmp >>= 30; - } - is_non_zero |= k->val[j]; - a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); - assert((a.val[0] & 1) != 0); - - // special case 0*G: just return zero. We don't care about constant time. - if (!is_non_zero) { - point_set_infinity(res); - return; - } - - // Now a = k + 2^256 (mod curve->order) and a is odd. - // - // The idea is to bring the new a into the form. - // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. - // a[0] is odd, since a is odd. If a[i] would be even, we can - // add 1 to it and subtract 16 from a[i-1]. Afterwards, - // a[64] = 1, which is the 2^256 that we added before. - // - // Since k = a - 2^256 (mod curve->order), we can compute - // k*G = sum_{i=0..63} a[i] 16^i * G - // - // We have a big table curve->cp that stores all possible - // values of |a[i]| 16^i * G. - // curve->cp[i][j] = (2*j+1) * 16^i * G - - // now compute res = sum_{i=0..63} a[i] * 16^i * G step by step. - // initial res = |a[0]| * G. Note that a[0] = a & 0xf if (a&0x10) != 0 - // and - (16 - (a & 0xf)) otherwise. We can compute this as - // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 - // since a is odd. - lowbits = a.val[0] & ((1 << 5) - 1); - lowbits ^= (lowbits >> 4) - 1; - lowbits &= 15; - curve_to_jacobian(&curve->cp[0][lowbits >> 1], &jres, prime); - for (i = 1; i < 64; i ++) { - // invariant res = sign(a[i-1]) sum_{j=0..i-1} (a[j] * 16^j * G) - - // shift a by 4 places. - for (j = 0; j < 8; j++) { - a.val[j] = (a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << 26); - } - a.val[j] >>= 4; - // a = old(a)>>(4*i) - // a is even iff sign(a[i-1]) = -1 - - lowbits = a.val[0] & ((1 << 5) - 1); - lowbits ^= (lowbits >> 4) - 1; - lowbits &= 15; - // negate last result to make signs of this round and the - // last round equal. - conditional_negate((lowbits & 1) - 1, &jres.y, prime); - - // add odd factor - point_jacobian_add(&curve->cp[i][lowbits >> 1], &jres, curve); - } - conditional_negate(((a.val[0] >> 4) & 1) - 1, &jres.y, prime); - jacobian_to_curve(&jres, res, prime); - memzero(&a, sizeof(a)); - memzero(&jres, sizeof(jres)); +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, + curve_point *res) { + assert(bn_is_less(k, &curve->order)); + + int i, j; + static CONFIDENTIAL bignum256 a; + uint32_t is_even = (k->val[0] & 1) - 1; + uint32_t lowbits; + static CONFIDENTIAL jacobian_curve_point jres; + const bignum256 *prime = &curve->prime; + + // is_even = 0xffffffff if k is even, 0 otherwise. + + // add 2^256. + // make number odd: subtract curve->order if even + uint32_t tmp = 1; + uint32_t is_non_zero = 0; + for (j = 0; j < 8; j++) { + is_non_zero |= k->val[j]; + tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); + a.val[j] = tmp & 0x3fffffff; + tmp >>= 30; + } + is_non_zero |= k->val[j]; + a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); + assert((a.val[0] & 1) != 0); + + // special case 0*G: just return zero. We don't care about constant time. + if (!is_non_zero) { + point_set_infinity(res); + return; + } + + // Now a = k + 2^256 (mod curve->order) and a is odd. + // + // The idea is to bring the new a into the form. + // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. + // a[0] is odd, since a is odd. If a[i] would be even, we can + // add 1 to it and subtract 16 from a[i-1]. Afterwards, + // a[64] = 1, which is the 2^256 that we added before. + // + // Since k = a - 2^256 (mod curve->order), we can compute + // k*G = sum_{i=0..63} a[i] 16^i * G + // + // We have a big table curve->cp that stores all possible + // values of |a[i]| 16^i * G. + // curve->cp[i][j] = (2*j+1) * 16^i * G + + // now compute res = sum_{i=0..63} a[i] * 16^i * G step by step. + // initial res = |a[0]| * G. Note that a[0] = a & 0xf if (a&0x10) != 0 + // and - (16 - (a & 0xf)) otherwise. We can compute this as + // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 + // since a is odd. + lowbits = a.val[0] & ((1 << 5) - 1); + lowbits ^= (lowbits >> 4) - 1; + lowbits &= 15; + curve_to_jacobian(&curve->cp[0][lowbits >> 1], &jres, prime); + for (i = 1; i < 64; i++) { + // invariant res = sign(a[i-1]) sum_{j=0..i-1} (a[j] * 16^j * G) + + // shift a by 4 places. + for (j = 0; j < 8; j++) { + a.val[j] = (a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << 26); + } + a.val[j] >>= 4; + // a = old(a)>>(4*i) + // a is even iff sign(a[i-1]) = -1 + + lowbits = a.val[0] & ((1 << 5) - 1); + lowbits ^= (lowbits >> 4) - 1; + lowbits &= 15; + // negate last result to make signs of this round and the + // last round equal. + conditional_negate((lowbits & 1) - 1, &jres.y, prime); + + // add odd factor + point_jacobian_add(&curve->cp[i][lowbits >> 1], &jres, curve); + } + conditional_negate(((a.val[0] >> 4) & 1) - 1, &jres.y, prime); + jacobian_to_curve(&jres, res, prime); + memzero(&a, sizeof(a)); + memzero(&jres, sizeof(jres)); } #else -void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res) -{ - point_multiply(curve, k, &curve->G, res); +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, + curve_point *res) { + point_multiply(curve, k, &curve->G, res); } #endif -int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key) -{ - curve_point point; - if (!ecdsa_read_pubkey(curve, pub_key, &point)) { - return 1; - } +int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, + const uint8_t *pub_key, uint8_t *session_key) { + curve_point point; + if (!ecdsa_read_pubkey(curve, pub_key, &point)) { + return 1; + } - bignum256 k; - bn_read_be(priv_key, &k); - point_multiply(curve, &k, &point, &point); - memzero(&k, sizeof(k)); + bignum256 k; + bn_read_be(priv_key, &k); + point_multiply(curve, &k, &point, &point); + memzero(&k, sizeof(k)); - session_key[0] = 0x04; - bn_write_be(&point.x, session_key + 1); - bn_write_be(&point.y, session_key + 33); - memzero(&point, sizeof(point)); + session_key[0] = 0x04; + bn_write_be(&point.x, session_key + 1); + bn_write_be(&point.y, session_key + 33); + memzero(&point, sizeof(point)); - return 0; + return 0; } -void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { - uint8_t bx[2*32]; - uint8_t buf[32 + 1 + 2*32]; +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, + rfc6979_state *state) { + uint8_t bx[2 * 32]; + uint8_t buf[32 + 1 + 2 * 32]; - memcpy(bx, priv_key, 32); - memcpy(bx+32, hash, 32); + memcpy(bx, priv_key, 32); + memcpy(bx + 32, hash, 32); - memset(state->v, 1, sizeof(state->v)); - memset(state->k, 0, sizeof(state->k)); + memset(state->v, 1, sizeof(state->v)); + memset(state->k, 0, sizeof(state->k)); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x00; - memcpy(buf + sizeof(state->v) + 1, bx, 64); - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x01; - memcpy(buf + sizeof(state->v) + 1, bx, 64); - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x01; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memzero(bx, sizeof(bx)); - memzero(buf, sizeof(buf)); + memzero(bx, sizeof(bx)); + memzero(buf, sizeof(buf)); } // generate next number from deterministic random number generator -void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) -{ - uint8_t buf[32 + 1]; - - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x00; - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(rnd, buf, 32); - memzero(buf, sizeof(buf)); +void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) { + uint8_t buf[32 + 1]; + + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(rnd, buf, 32); + memzero(buf, sizeof(buf)); } // generate K in a deterministic way, according to RFC6979 // http://tools.ietf.org/html/rfc6979 -void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) -{ - uint8_t buf[32]; - generate_rfc6979(buf, state); - bn_read_be(buf, k); - memzero(buf, sizeof(buf)); +void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) { + uint8_t buf[32]; + generate_rfc6979(buf, state); + bn_read_be(buf, k); + memzero(buf, sizeof(buf)); } // msg is a data to be signed // msg_len is the message length -int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) -{ - uint8_t hash[32]; - hasher_Raw(hasher_sign, msg, msg_len, hash); - int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby, is_canonical); - memzero(hash, sizeof(hash)); - return res; - +int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, + const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, + uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])) { + uint8_t hash[32]; + hasher_Raw(hasher_sign, msg, msg_len, hash); + int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby, is_canonical); + memzero(hash, sizeof(hash)); + return res; } // uses secp256k1 curve @@ -729,245 +722,251 @@ int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t * // digest is 32 bytes of digest // is_canonical is an optional function that checks if the signature // conforms to additional coin-specific rules. -int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) -{ - int i; - curve_point R; - bignum256 k, z, randk; - bignum256 *s = &R.y; - uint8_t by; // signature recovery byte +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, + const uint8_t *digest, uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])) { + int i; + curve_point R; + bignum256 k, z, randk; + bignum256 *s = &R.y; + uint8_t by; // signature recovery byte #if USE_RFC6979 - rfc6979_state rng; - init_rfc6979(priv_key, digest, &rng); + rfc6979_state rng; + init_rfc6979(priv_key, digest, &rng); #endif - bn_read_be(digest, &z); - - for (i = 0; i < 10000; i++) { + bn_read_be(digest, &z); + for (i = 0; i < 10000; i++) { #if USE_RFC6979 - // generate K deterministically - generate_k_rfc6979(&k, &rng); - // if k is too big or too small, we don't like it - if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) { - continue; - } + // generate K deterministically + generate_k_rfc6979(&k, &rng); + // if k is too big or too small, we don't like it + if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) { + continue; + } #else - // generate random number k - generate_k_random(&k, &curve->order); + // generate random number k + generate_k_random(&k, &curve->order); #endif - // compute k*G - scalar_multiply(curve, &k, &R); - by = R.y.val[0] & 1; - // r = (rx mod n) - if (!bn_is_less(&R.x, &curve->order)) { - bn_subtract(&R.x, &curve->order, &R.x); - by |= 2; - } - // if r is zero, we retry - if (bn_is_zero(&R.x)) { - continue; - } - - // randomize operations to counter side-channel attacks - generate_k_random(&randk, &curve->order); - bn_multiply(&randk, &k, &curve->order); // k*rand - bn_inverse(&k, &curve->order); // (k*rand)^-1 - bn_read_be(priv_key, s); // priv - bn_multiply(&R.x, s, &curve->order); // R.x*priv - bn_add(s, &z); // R.x*priv + z - bn_multiply(&k, s, &curve->order); // (k*rand)^-1 (R.x*priv + z) - bn_multiply(&randk, s, &curve->order); // k^-1 (R.x*priv + z) - bn_mod(s, &curve->order); - // if s is zero, we retry - if (bn_is_zero(s)) { - continue; - } - - // if S > order/2 => S = -S - if (bn_is_less(&curve->order_half, s)) { - bn_subtract(&curve->order, s, s); - by ^= 1; - } - // we are done, R.x and s is the result signature - bn_write_be(&R.x, sig); - bn_write_be(s, sig + 32); - - // check if the signature is acceptable or retry - if (is_canonical && !is_canonical(by, sig)) { - continue; - } - - if (pby) { - *pby = by; - } - - memzero(&k, sizeof(k)); - memzero(&randk, sizeof(randk)); + // compute k*G + scalar_multiply(curve, &k, &R); + by = R.y.val[0] & 1; + // r = (rx mod n) + if (!bn_is_less(&R.x, &curve->order)) { + bn_subtract(&R.x, &curve->order, &R.x); + by |= 2; + } + // if r is zero, we retry + if (bn_is_zero(&R.x)) { + continue; + } + + // randomize operations to counter side-channel attacks + generate_k_random(&randk, &curve->order); + bn_multiply(&randk, &k, &curve->order); // k*rand + bn_inverse(&k, &curve->order); // (k*rand)^-1 + bn_read_be(priv_key, s); // priv + bn_multiply(&R.x, s, &curve->order); // R.x*priv + bn_add(s, &z); // R.x*priv + z + bn_multiply(&k, s, &curve->order); // (k*rand)^-1 (R.x*priv + z) + bn_multiply(&randk, s, &curve->order); // k^-1 (R.x*priv + z) + bn_mod(s, &curve->order); + // if s is zero, we retry + if (bn_is_zero(s)) { + continue; + } + + // if S > order/2 => S = -S + if (bn_is_less(&curve->order_half, s)) { + bn_subtract(&curve->order, s, s); + by ^= 1; + } + // we are done, R.x and s is the result signature + bn_write_be(&R.x, sig); + bn_write_be(s, sig + 32); + + // check if the signature is acceptable or retry + if (is_canonical && !is_canonical(by, sig)) { + continue; + } + + if (pby) { + *pby = by; + } + + memzero(&k, sizeof(k)); + memzero(&randk, sizeof(randk)); #if USE_RFC6979 - memzero(&rng, sizeof(rng)); + memzero(&rng, sizeof(rng)); #endif - return 0; - } + return 0; + } - // Too many retries without a valid signature - // -> fail with an error - memzero(&k, sizeof(k)); - memzero(&randk, sizeof(randk)); + // Too many retries without a valid signature + // -> fail with an error + memzero(&k, sizeof(k)); + memzero(&randk, sizeof(randk)); #if USE_RFC6979 - memzero(&rng, sizeof(rng)); + memzero(&rng, sizeof(rng)); #endif - return -1; + return -1; } -void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key) -{ - curve_point R; - bignum256 k; - - bn_read_be(priv_key, &k); - // compute k*G - scalar_multiply(curve, &k, &R); - pub_key[0] = 0x02 | (R.y.val[0] & 0x01); - bn_write_be(&R.x, pub_key + 1); - memzero(&R, sizeof(R)); - memzero(&k, sizeof(k)); +void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, + uint8_t *pub_key) { + curve_point R; + bignum256 k; + + bn_read_be(priv_key, &k); + // compute k*G + scalar_multiply(curve, &k, &R); + pub_key[0] = 0x02 | (R.y.val[0] & 0x01); + bn_write_be(&R.x, pub_key + 1); + memzero(&R, sizeof(R)); + memzero(&k, sizeof(k)); } -void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key) -{ - curve_point R; - bignum256 k; - - bn_read_be(priv_key, &k); - // compute k*G - scalar_multiply(curve, &k, &R); - pub_key[0] = 0x04; - bn_write_be(&R.x, pub_key + 1); - bn_write_be(&R.y, pub_key + 33); - memzero(&R, sizeof(R)); - memzero(&k, sizeof(k)); +void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, + uint8_t *pub_key) { + curve_point R; + bignum256 k; + + bn_read_be(priv_key, &k); + // compute k*G + scalar_multiply(curve, &k, &R); + pub_key[0] = 0x04; + bn_write_be(&R.x, pub_key + 1); + bn_write_be(&R.y, pub_key + 33); + memzero(&R, sizeof(R)); + memzero(&k, sizeof(k)); } -int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed) -{ - curve_point pub; +int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, + uint8_t *uncompressed) { + curve_point pub; - if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { - return 0; - } + if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { + return 0; + } - uncompressed[0] = 4; - bn_write_be(&pub.x, uncompressed + 1); - bn_write_be(&pub.y, uncompressed + 33); + uncompressed[0] = 4; + bn_write_be(&pub.x, uncompressed + 1); + bn_write_be(&pub.y, uncompressed + 33); - return 1; + return 1; } -void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash) -{ - uint8_t h[HASHER_DIGEST_LENGTH]; - if (pub_key[0] == 0x04) { // uncompressed format - hasher_Raw(hasher_pubkey, pub_key, 65, h); - } else if (pub_key[0] == 0x00) { // point at infinity - hasher_Raw(hasher_pubkey, pub_key, 1, h); - } else { // expecting compressed format - hasher_Raw(hasher_pubkey, pub_key, 33, h); - } - memcpy(pubkeyhash, h, 20); - memzero(h, sizeof(h)); +void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, + uint8_t *pubkeyhash) { + uint8_t h[HASHER_DIGEST_LENGTH]; + if (pub_key[0] == 0x04) { // uncompressed format + hasher_Raw(hasher_pubkey, pub_key, 65, h); + } else if (pub_key[0] == 0x00) { // point at infinity + hasher_Raw(hasher_pubkey, pub_key, 1, h); + } else { // expecting compressed format + hasher_Raw(hasher_pubkey, pub_key, 33, h); + } + memcpy(pubkeyhash, h, 20); + memzero(h, sizeof(h)); } -void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw) -{ - size_t prefix_len = address_prefix_bytes_len(version); - address_write_prefix_bytes(version, addr_raw); - ecdsa_get_pubkeyhash(pub_key, hasher_pubkey, addr_raw + prefix_len); +void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, uint8_t *addr_raw) { + size_t prefix_len = address_prefix_bytes_len(version); + address_write_prefix_bytes(version, addr_raw); + ecdsa_get_pubkeyhash(pub_key, hasher_pubkey, addr_raw + prefix_len); } -void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize) -{ - uint8_t raw[MAX_ADDR_RAW_SIZE]; - size_t prefix_len = address_prefix_bytes_len(version); - ecdsa_get_address_raw(pub_key, version, hasher_pubkey, raw); - base58_encode_check(raw, 20 + prefix_len, hasher_base58, addr, addrsize); - // not as important to clear this one, but we might as well - memzero(raw, sizeof(raw)); +void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, HasherType hasher_base58, + char *addr, int addrsize) { + uint8_t raw[MAX_ADDR_RAW_SIZE]; + size_t prefix_len = address_prefix_bytes_len(version); + ecdsa_get_address_raw(pub_key, version, hasher_pubkey, raw); + base58_encode_check(raw, 20 + prefix_len, hasher_base58, addr, addrsize); + // not as important to clear this one, but we might as well + memzero(raw, sizeof(raw)); } -void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw) -{ - uint8_t buf[32 + 2]; - buf[0] = 0; // version byte - buf[1] = 20; // push 20 bytes - ecdsa_get_pubkeyhash(pub_key, hasher_pubkey, buf + 2); - size_t prefix_len = address_prefix_bytes_len(version); - address_write_prefix_bytes(version, addr_raw); - hasher_Raw(hasher_pubkey, buf, 22, addr_raw + prefix_len); +void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, + uint8_t *addr_raw) { + uint8_t buf[32 + 2]; + buf[0] = 0; // version byte + buf[1] = 20; // push 20 bytes + ecdsa_get_pubkeyhash(pub_key, hasher_pubkey, buf + 2); + size_t prefix_len = address_prefix_bytes_len(version); + address_write_prefix_bytes(version, addr_raw); + hasher_Raw(hasher_pubkey, buf, 22, addr_raw + prefix_len); } -void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize) -{ - uint8_t raw[MAX_ADDR_RAW_SIZE]; - size_t prefix_len = address_prefix_bytes_len(version); - ecdsa_get_address_segwit_p2sh_raw(pub_key, version, hasher_pubkey, raw); - base58_encode_check(raw, prefix_len + 20, hasher_base58, addr, addrsize); - memzero(raw, sizeof(raw)); +void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, + HasherType hasher_base58, char *addr, + int addrsize) { + uint8_t raw[MAX_ADDR_RAW_SIZE]; + size_t prefix_len = address_prefix_bytes_len(version); + ecdsa_get_address_segwit_p2sh_raw(pub_key, version, hasher_pubkey, raw); + base58_encode_check(raw, prefix_len + 20, hasher_base58, addr, addrsize); + memzero(raw, sizeof(raw)); } -void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize) -{ - uint8_t wif_raw[MAX_WIF_RAW_SIZE]; - size_t prefix_len = address_prefix_bytes_len(version); - address_write_prefix_bytes(version, wif_raw); - memcpy(wif_raw + prefix_len, priv_key, 32); - wif_raw[prefix_len + 32] = 0x01; - base58_encode_check(wif_raw, prefix_len + 32 + 1, hasher_base58, wif, wifsize); - // private keys running around our stack can cause trouble - memzero(wif_raw, sizeof(wif_raw)); +void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, + HasherType hasher_base58, char *wif, int wifsize) { + uint8_t wif_raw[MAX_WIF_RAW_SIZE]; + size_t prefix_len = address_prefix_bytes_len(version); + address_write_prefix_bytes(version, wif_raw); + memcpy(wif_raw + prefix_len, priv_key, 32); + wif_raw[prefix_len + 32] = 0x01; + base58_encode_check(wif_raw, prefix_len + 32 + 1, hasher_base58, wif, + wifsize); + // private keys running around our stack can cause trouble + memzero(wif_raw, sizeof(wif_raw)); } -int ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out) -{ - if (!addr) return 0; - int prefix_len = address_prefix_bytes_len(version); - return base58_decode_check(addr, hasher_base58, out, 20 + prefix_len) == 20 + prefix_len - && address_check_prefix(out, version); +int ecdsa_address_decode(const char *addr, uint32_t version, + HasherType hasher_base58, uint8_t *out) { + if (!addr) return 0; + int prefix_len = address_prefix_bytes_len(version); + return base58_decode_check(addr, hasher_base58, out, 20 + prefix_len) == + 20 + prefix_len && + address_check_prefix(out, version); } -void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y) -{ - // y^2 = x^3 + a*x + b - memcpy(y, x, sizeof(bignum256)); // y is x - bn_multiply(x, y, &curve->prime); // y is x^2 - bn_subi(y, -curve->a, &curve->prime); // y is x^2 + a - bn_multiply(x, y, &curve->prime); // y is x^3 + ax - bn_add(y, &curve->b); // y is x^3 + ax + b - bn_sqrt(y, &curve->prime); // y = sqrt(y) - if ((odd & 0x01) != (y->val[0] & 1)) { - bn_subtract(&curve->prime, y, y); // y = -y - } +void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, + const bignum256 *x, bignum256 *y) { + // y^2 = x^3 + a*x + b + memcpy(y, x, sizeof(bignum256)); // y is x + bn_multiply(x, y, &curve->prime); // y is x^2 + bn_subi(y, -curve->a, &curve->prime); // y is x^2 + a + bn_multiply(x, y, &curve->prime); // y is x^3 + ax + bn_add(y, &curve->b); // y is x^3 + ax + b + bn_sqrt(y, &curve->prime); // y = sqrt(y) + if ((odd & 0x01) != (y->val[0] & 1)) { + bn_subtract(&curve->prime, y, y); // y = -y + } } -int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub) -{ - if (!curve) { - curve = &secp256k1; - } - if (pub_key[0] == 0x04) { - bn_read_be(pub_key + 1, &(pub->x)); - bn_read_be(pub_key + 33, &(pub->y)); - return ecdsa_validate_pubkey(curve, pub); - } - if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords - bn_read_be(pub_key + 1, &(pub->x)); - uncompress_coords(curve, pub_key[0], &(pub->x), &(pub->y)); - return ecdsa_validate_pubkey(curve, pub); - } - // error - return 0; +int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, + curve_point *pub) { + if (!curve) { + curve = &secp256k1; + } + if (pub_key[0] == 0x04) { + bn_read_be(pub_key + 1, &(pub->x)); + bn_read_be(pub_key + 33, &(pub->y)); + return ecdsa_validate_pubkey(curve, pub); + } + if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords + bn_read_be(pub_key + 1, &(pub->x)); + uncompress_coords(curve, pub_key[0], &(pub->x), &(pub->y)); + return ecdsa_validate_pubkey(curve, pub); + } + // error + return 0; } // Verifies that: @@ -975,37 +974,37 @@ int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_po // - pub->x and pub->y are in range [0,p-1]. // - pub is on the curve. -int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub) -{ - bignum256 y_2, x3_ax_b; +int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub) { + bignum256 y_2, x3_ax_b; - if (point_is_infinity(pub)) { - return 0; - } + if (point_is_infinity(pub)) { + return 0; + } - if (!bn_is_less(&(pub->x), &curve->prime) || !bn_is_less(&(pub->y), &curve->prime)) { - return 0; - } + if (!bn_is_less(&(pub->x), &curve->prime) || + !bn_is_less(&(pub->y), &curve->prime)) { + return 0; + } - memcpy(&y_2, &(pub->y), sizeof(bignum256)); - memcpy(&x3_ax_b, &(pub->x), sizeof(bignum256)); + memcpy(&y_2, &(pub->y), sizeof(bignum256)); + memcpy(&x3_ax_b, &(pub->x), sizeof(bignum256)); - // y^2 - bn_multiply(&(pub->y), &y_2, &curve->prime); - bn_mod(&y_2, &curve->prime); + // y^2 + bn_multiply(&(pub->y), &y_2, &curve->prime); + bn_mod(&y_2, &curve->prime); - // x^3 + ax + b - bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^2 - bn_subi(&x3_ax_b, -curve->a, &curve->prime); // x^2 + a - bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^3 + ax - bn_addmod(&x3_ax_b, &curve->b, &curve->prime); // x^3 + ax + b - bn_mod(&x3_ax_b, &curve->prime); + // x^3 + ax + b + bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^2 + bn_subi(&x3_ax_b, -curve->a, &curve->prime); // x^2 + a + bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^3 + ax + bn_addmod(&x3_ax_b, &curve->b, &curve->prime); // x^3 + ax + b + bn_mod(&x3_ax_b, &curve->prime); - if (!bn_is_equal(&x3_ax_b, &y_2)) { - return 0; - } + if (!bn_is_equal(&x3_ax_b, &y_2)) { + return 0; + } - return 1; + return 1; } // uses secp256k1 curve @@ -1014,153 +1013,178 @@ int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub) // msg is a data that was signed // msg_len is the message length -int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len) -{ - uint8_t hash[32]; - hasher_Raw(hasher_sign, msg, msg_len, hash); - int res = ecdsa_verify_digest(curve, pub_key, sig, hash); - memzero(hash, sizeof(hash)); - return res; +int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, + const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, + uint32_t msg_len) { + uint8_t hash[32]; + hasher_Raw(hasher_sign, msg, msg_len, hash); + int res = ecdsa_verify_digest(curve, pub_key, sig, hash); + memzero(hash, sizeof(hash)); + return res; } // Compute public key from signature and recovery id. // returns 0 if the key is successfully recovered -int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid) -{ - bignum256 r, s, e; - curve_point cp, cp2; - - // read r and s - bn_read_be(sig, &r); - bn_read_be(sig + 32, &s); - if (!bn_is_less(&r, &curve->order) || bn_is_zero(&r)) { - return 1; - } - if (!bn_is_less(&s, &curve->order) || bn_is_zero(&s)) { - return 1; - } - // cp = R = k * G (k is secret nonce when signing) - memcpy(&cp.x, &r, sizeof(bignum256)); - if (recid & 2) { - bn_add(&cp.x, &curve->order); - if (!bn_is_less(&cp.x, &curve->prime)) { - return 1; - } - } - // compute y from x - uncompress_coords(curve, recid & 1, &cp.x, &cp.y); - if (!ecdsa_validate_pubkey(curve, &cp)) { - return 1; - } - // e = -digest - bn_read_be(digest, &e); - bn_subtractmod(&curve->order, &e, &e, &curve->order); - bn_fast_mod(&e, &curve->order); - bn_mod(&e, &curve->order); - // r := r^-1 - bn_inverse(&r, &curve->order); - // cp := s * R = s * k *G - point_multiply(curve, &s, &cp, &cp); - // cp2 := -digest * G - scalar_multiply(curve, &e, &cp2); - // cp := (s * k - digest) * G = (r*priv) * G = r * Pub - point_add(curve, &cp2, &cp); - // cp := r^{-1} * r * Pub = Pub - point_multiply(curve, &r, &cp, &cp); - pub_key[0] = 0x04; - bn_write_be(&cp.x, pub_key + 1); - bn_write_be(&cp.y, pub_key + 33); - return 0; +int ecdsa_recover_pub_from_sig(const ecdsa_curve *curve, uint8_t *pub_key, + const uint8_t *sig, const uint8_t *digest, + int recid) { + bignum256 r, s, e; + curve_point cp, cp2; + + // read r and s + bn_read_be(sig, &r); + bn_read_be(sig + 32, &s); + if (!bn_is_less(&r, &curve->order) || bn_is_zero(&r)) { + return 1; + } + if (!bn_is_less(&s, &curve->order) || bn_is_zero(&s)) { + return 1; + } + // cp = R = k * G (k is secret nonce when signing) + memcpy(&cp.x, &r, sizeof(bignum256)); + if (recid & 2) { + bn_add(&cp.x, &curve->order); + if (!bn_is_less(&cp.x, &curve->prime)) { + return 1; + } + } + // compute y from x + uncompress_coords(curve, recid & 1, &cp.x, &cp.y); + if (!ecdsa_validate_pubkey(curve, &cp)) { + return 1; + } + // e = -digest + bn_read_be(digest, &e); + bn_subtractmod(&curve->order, &e, &e, &curve->order); + bn_fast_mod(&e, &curve->order); + bn_mod(&e, &curve->order); + // r := r^-1 + bn_inverse(&r, &curve->order); + // cp := s * R = s * k *G + point_multiply(curve, &s, &cp, &cp); + // cp2 := -digest * G + scalar_multiply(curve, &e, &cp2); + // cp := (s * k - digest) * G = (r*priv) * G = r * Pub + point_add(curve, &cp2, &cp); + // cp := r^{-1} * r * Pub = Pub + point_multiply(curve, &r, &cp, &cp); + pub_key[0] = 0x04; + bn_write_be(&cp.x, pub_key + 1); + bn_write_be(&cp.y, pub_key + 33); + return 0; } // returns 0 if verification succeeded -int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest) -{ - curve_point pub, res; - bignum256 r, s, z; - - if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { - return 1; - } - - bn_read_be(sig, &r); - bn_read_be(sig + 32, &s); - - bn_read_be(digest, &z); - - if (bn_is_zero(&r) || bn_is_zero(&s) || - (!bn_is_less(&r, &curve->order)) || - (!bn_is_less(&s, &curve->order))) return 2; - - bn_inverse(&s, &curve->order); // s^-1 - bn_multiply(&s, &z, &curve->order); // z*s^-1 - bn_mod(&z, &curve->order); - bn_multiply(&r, &s, &curve->order); // r*s^-1 - bn_mod(&s, &curve->order); - - int result = 0; - if (bn_is_zero(&z)) { - // our message hashes to zero - // I don't expect this to happen any time soon - result = 3; - } else { - scalar_multiply(curve, &z, &res); - } - - if (result == 0) { - // both pub and res can be infinity, can have y = 0 OR can be equal -> false negative - point_multiply(curve, &s, &pub, &pub); - point_add(curve, &pub, &res); - bn_mod(&(res.x), &curve->order); - // signature does not match - if (!bn_is_equal(&res.x, &r)) { - result = 5; - } - } - - memzero(&pub, sizeof(pub)); - memzero(&res, sizeof(res)); - memzero(&r, sizeof(r)); - memzero(&s, sizeof(s)); - memzero(&z, sizeof(z)); - - // all OK - return result; +int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, + const uint8_t *sig, const uint8_t *digest) { + curve_point pub, res; + bignum256 r, s, z; + + if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { + return 1; + } + + bn_read_be(sig, &r); + bn_read_be(sig + 32, &s); + + bn_read_be(digest, &z); + + if (bn_is_zero(&r) || bn_is_zero(&s) || (!bn_is_less(&r, &curve->order)) || + (!bn_is_less(&s, &curve->order))) + return 2; + + bn_inverse(&s, &curve->order); // s^-1 + bn_multiply(&s, &z, &curve->order); // z*s^-1 + bn_mod(&z, &curve->order); + bn_multiply(&r, &s, &curve->order); // r*s^-1 + bn_mod(&s, &curve->order); + + int result = 0; + if (bn_is_zero(&z)) { + // our message hashes to zero + // I don't expect this to happen any time soon + result = 3; + } else { + scalar_multiply(curve, &z, &res); + } + + if (result == 0) { + // both pub and res can be infinity, can have y = 0 OR can be equal -> false + // negative + point_multiply(curve, &s, &pub, &pub); + point_add(curve, &pub, &res); + bn_mod(&(res.x), &curve->order); + // signature does not match + if (!bn_is_equal(&res.x, &r)) { + result = 5; + } + } + + memzero(&pub, sizeof(pub)); + memzero(&res, sizeof(res)); + memzero(&r, sizeof(r)); + memzero(&s, sizeof(s)); + memzero(&z, sizeof(z)); + + // all OK + return result; } -int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der) -{ - int i; - uint8_t *p = der, *len, *len1, *len2; - *p = 0x30; p++; // sequence - *p = 0x00; len = p; p++; // len(sequence) - - *p = 0x02; p++; // integer - *p = 0x00; len1 = p; p++; // len(integer) - - // process R - i = 0; - while (sig[i] == 0 && i < 32) { i++; } // skip leading zeroes - if (sig[i] >= 0x80) { // put zero in output if MSB set - *p = 0x00; p++; *len1 = *len1 + 1; - } - while (i < 32) { // copy bytes to output - *p = sig[i]; p++; *len1 = *len1 + 1; i++; - } - - *p = 0x02; p++; // integer - *p = 0x00; len2 = p; p++; // len(integer) - - // process S - i = 32; - while (sig[i] == 0 && i < 64) { i++; } // skip leading zeroes - if (sig[i] >= 0x80) { // put zero in output if MSB set - *p = 0x00; p++; *len2 = *len2 + 1; - } - while (i < 64) { // copy bytes to output - *p = sig[i]; p++; *len2 = *len2 + 1; i++; - } - - *len = *len1 + *len2 + 4; - return *len + 2; +int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der) { + int i; + uint8_t *p = der, *len, *len1, *len2; + *p = 0x30; + p++; // sequence + *p = 0x00; + len = p; + p++; // len(sequence) + + *p = 0x02; + p++; // integer + *p = 0x00; + len1 = p; + p++; // len(integer) + + // process R + i = 0; + while (sig[i] == 0 && i < 32) { + i++; + } // skip leading zeroes + if (sig[i] >= 0x80) { // put zero in output if MSB set + *p = 0x00; + p++; + *len1 = *len1 + 1; + } + while (i < 32) { // copy bytes to output + *p = sig[i]; + p++; + *len1 = *len1 + 1; + i++; + } + + *p = 0x02; + p++; // integer + *p = 0x00; + len2 = p; + p++; // len(integer) + + // process S + i = 32; + while (sig[i] == 0 && i < 64) { + i++; + } // skip leading zeroes + if (sig[i] >= 0x80) { // put zero in output if MSB set + *p = 0x00; + p++; + *len2 = *len2 + 1; + } + while (i < 64) { // copy bytes to output + *p = sig[i]; + p++; + *len2 = *len2 + 1; + i++; + } + + *len = *len1 + *len2 + 4; + return *len + 2; } diff --git a/ecdsa.h b/ecdsa.h index 6afb542f2..8f8d06457 100644 --- a/ecdsa.h +++ b/ecdsa.h @@ -25,26 +25,25 @@ #define __ECDSA_H__ #include -#include "options.h" #include "bignum.h" #include "hasher.h" +#include "options.h" // curve point x and y typedef struct { - bignum256 x, y; + bignum256 x, y; } curve_point; typedef struct { - - bignum256 prime; // prime order of the finite field - curve_point G; // initial curve point - bignum256 order; // order of G - bignum256 order_half; // order of G divided by 2 - int a; // coefficient 'a' of the elliptic curve - bignum256 b; // coefficient 'b' of the elliptic curve + bignum256 prime; // prime order of the finite field + curve_point G; // initial curve point + bignum256 order; // order of G + bignum256 order_half; // order of G divided by 2 + int a; // coefficient 'a' of the elliptic curve + bignum256 b; // coefficient 'b' of the elliptic curve #if USE_PRECOMPUTED_CP - const curve_point cp[64][8]; + const curve_point cp[64][8]; #endif } ecdsa_curve; @@ -63,35 +62,65 @@ typedef struct { #define MAX_WIF_SIZE (57) void point_copy(const curve_point *cp1, curve_point *cp2); -void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2); +void point_add(const ecdsa_curve *curve, const curve_point *cp1, + curve_point *cp2); void point_double(const ecdsa_curve *curve, curve_point *cp); -void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res); +void point_multiply(const ecdsa_curve *curve, const bignum256 *k, + const curve_point *p, curve_point *res); void point_set_infinity(curve_point *p); int point_is_infinity(const curve_point *p); int point_is_equal(const curve_point *p, const curve_point *q); int point_is_negative_of(const curve_point *p, const curve_point *q); -void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res); -int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key); -void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y); -int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed); +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, + curve_point *res); +int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, + const uint8_t *pub_key, uint8_t *session_key); +void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, + const bignum256 *x, bignum256 *y); +int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, + uint8_t *uncompressed); -int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); -int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); -void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); -void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); -void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash); -void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw); -void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize); -void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw); -void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize); -void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize); +int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, + const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, + uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, + const uint8_t *digest, uint8_t *sig, uint8_t *pby, + int (*is_canonical)(uint8_t by, uint8_t sig[64])); +void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, + uint8_t *pub_key); +void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, + uint8_t *pub_key); +void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, + uint8_t *pubkeyhash); +void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, uint8_t *addr_raw); +void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, HasherType hasher_base58, + char *addr, int addrsize); +void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, + uint8_t *addr_raw); +void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, + HasherType hasher_pubkey, + HasherType hasher_base58, char *addr, + int addrsize); +void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, + HasherType hasher_base58, char *wif, int wifsize); -int ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out); -int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub); +int ecdsa_address_decode(const char *addr, uint32_t version, + HasherType hasher_base58, uint8_t *out); +int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, + curve_point *pub); int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub); -int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len); -int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest); -int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid); +int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, + const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, + uint32_t msg_len); +int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, + const uint8_t *sig, const uint8_t *digest); +int ecdsa_recover_pub_from_sig(const ecdsa_curve *curve, uint8_t *pub_key, + const uint8_t *sig, const uint8_t *digest, + int recid); int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der); #endif diff --git a/hasher.c b/hasher.c index dac3e9bf5..240cba778 100644 --- a/hasher.c +++ b/hasher.c @@ -23,122 +23,125 @@ #include "hasher.h" #include "ripemd160.h" -void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size) { - hasher->type = type; - hasher->param = param; - hasher->param_size = param_size; +void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, + uint32_t param_size) { + hasher->type = type; + hasher->param = param; + hasher->param_size = param_size; - switch (hasher->type) { - case HASHER_SHA2: - case HASHER_SHA2D: - case HASHER_SHA2_RIPEMD: - sha256_Init(&hasher->ctx.sha2); - break; - case HASHER_SHA3: + switch (hasher->type) { + case HASHER_SHA2: + case HASHER_SHA2D: + case HASHER_SHA2_RIPEMD: + sha256_Init(&hasher->ctx.sha2); + break; + case HASHER_SHA3: #if USE_KECCAK - case HASHER_SHA3K: + case HASHER_SHA3K: #endif - sha3_256_Init(&hasher->ctx.sha3); - break; - case HASHER_BLAKE: - case HASHER_BLAKED: - case HASHER_BLAKE_RIPEMD: - blake256_Init(&hasher->ctx.blake); - break; - case HASHER_GROESTLD_TRUNC: - groestl512_Init(&hasher->ctx.groestl); - break; - case HASHER_BLAKE2B: - blake2b_Init(&hasher->ctx.blake2b, 32); - break; - case HASHER_BLAKE2B_PERSONAL: - blake2b_InitPersonal(&hasher->ctx.blake2b, 32, hasher->param, hasher->param_size); - break; - } + sha3_256_Init(&hasher->ctx.sha3); + break; + case HASHER_BLAKE: + case HASHER_BLAKED: + case HASHER_BLAKE_RIPEMD: + blake256_Init(&hasher->ctx.blake); + break; + case HASHER_GROESTLD_TRUNC: + groestl512_Init(&hasher->ctx.groestl); + break; + case HASHER_BLAKE2B: + blake2b_Init(&hasher->ctx.blake2b, 32); + break; + case HASHER_BLAKE2B_PERSONAL: + blake2b_InitPersonal(&hasher->ctx.blake2b, 32, hasher->param, + hasher->param_size); + break; + } } void hasher_Init(Hasher *hasher, HasherType type) { - hasher_InitParam(hasher, type, NULL, 0); + hasher_InitParam(hasher, type, NULL, 0); } void hasher_Reset(Hasher *hasher) { - hasher_InitParam(hasher, hasher->type, hasher->param, hasher->param_size); + hasher_InitParam(hasher, hasher->type, hasher->param, hasher->param_size); } void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length) { - switch (hasher->type) { - case HASHER_SHA2: - case HASHER_SHA2D: - case HASHER_SHA2_RIPEMD: - sha256_Update(&hasher->ctx.sha2, data, length); - break; - case HASHER_SHA3: + switch (hasher->type) { + case HASHER_SHA2: + case HASHER_SHA2D: + case HASHER_SHA2_RIPEMD: + sha256_Update(&hasher->ctx.sha2, data, length); + break; + case HASHER_SHA3: #if USE_KECCAK - case HASHER_SHA3K: + case HASHER_SHA3K: #endif - sha3_Update(&hasher->ctx.sha3, data, length); - break; - case HASHER_BLAKE: - case HASHER_BLAKED: - case HASHER_BLAKE_RIPEMD: - blake256_Update(&hasher->ctx.blake, data, length); - break; - case HASHER_GROESTLD_TRUNC: - groestl512_Update(&hasher->ctx.groestl, data, length); - break; - case HASHER_BLAKE2B: - case HASHER_BLAKE2B_PERSONAL: - blake2b_Update(&hasher->ctx.blake2b, data, length); - break; - } + sha3_Update(&hasher->ctx.sha3, data, length); + break; + case HASHER_BLAKE: + case HASHER_BLAKED: + case HASHER_BLAKE_RIPEMD: + blake256_Update(&hasher->ctx.blake, data, length); + break; + case HASHER_GROESTLD_TRUNC: + groestl512_Update(&hasher->ctx.groestl, data, length); + break; + case HASHER_BLAKE2B: + case HASHER_BLAKE2B_PERSONAL: + blake2b_Update(&hasher->ctx.blake2b, data, length); + break; + } } void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]) { - switch (hasher->type) { - case HASHER_SHA2: - sha256_Final(&hasher->ctx.sha2, hash); - break; - case HASHER_SHA2D: - sha256_Final(&hasher->ctx.sha2, hash); - hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash); - break; - case HASHER_SHA2_RIPEMD: - sha256_Final(&hasher->ctx.sha2, hash); - ripemd160(hash, HASHER_DIGEST_LENGTH, hash); - break; - case HASHER_SHA3: - sha3_Final(&hasher->ctx.sha3, hash); - break; + switch (hasher->type) { + case HASHER_SHA2: + sha256_Final(&hasher->ctx.sha2, hash); + break; + case HASHER_SHA2D: + sha256_Final(&hasher->ctx.sha2, hash); + hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash); + break; + case HASHER_SHA2_RIPEMD: + sha256_Final(&hasher->ctx.sha2, hash); + ripemd160(hash, HASHER_DIGEST_LENGTH, hash); + break; + case HASHER_SHA3: + sha3_Final(&hasher->ctx.sha3, hash); + break; #if USE_KECCAK - case HASHER_SHA3K: - keccak_Final(&hasher->ctx.sha3, hash); - break; + case HASHER_SHA3K: + keccak_Final(&hasher->ctx.sha3, hash); + break; #endif - case HASHER_BLAKE: - blake256_Final(&hasher->ctx.blake, hash); - break; - case HASHER_BLAKED: - blake256_Final(&hasher->ctx.blake, hash); - hasher_Raw(HASHER_BLAKE, hash, HASHER_DIGEST_LENGTH, hash); - break; - case HASHER_BLAKE_RIPEMD: - blake256_Final(&hasher->ctx.blake, hash); - ripemd160(hash, HASHER_DIGEST_LENGTH, hash); - break; - case HASHER_GROESTLD_TRUNC: - groestl512_DoubleTrunc(&hasher->ctx.groestl, hash); - break; - case HASHER_BLAKE2B: - case HASHER_BLAKE2B_PERSONAL: - blake2b_Final(&hasher->ctx.blake2b, hash, 32); - break; - } + case HASHER_BLAKE: + blake256_Final(&hasher->ctx.blake, hash); + break; + case HASHER_BLAKED: + blake256_Final(&hasher->ctx.blake, hash); + hasher_Raw(HASHER_BLAKE, hash, HASHER_DIGEST_LENGTH, hash); + break; + case HASHER_BLAKE_RIPEMD: + blake256_Final(&hasher->ctx.blake, hash); + ripemd160(hash, HASHER_DIGEST_LENGTH, hash); + break; + case HASHER_GROESTLD_TRUNC: + groestl512_DoubleTrunc(&hasher->ctx.groestl, hash); + break; + case HASHER_BLAKE2B: + case HASHER_BLAKE2B_PERSONAL: + blake2b_Final(&hasher->ctx.blake2b, hash, 32); + break; + } } -void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]) { - Hasher hasher; +void hasher_Raw(HasherType type, const uint8_t *data, size_t length, + uint8_t hash[HASHER_DIGEST_LENGTH]) { + Hasher hasher; - hasher_Init(&hasher, type); - hasher_Update(&hasher, data, length); - hasher_Final(&hasher, hash); + hasher_Init(&hasher, type); + hasher_Update(&hasher, data, length); + hasher_Final(&hasher, hash); } diff --git a/hasher.h b/hasher.h index 0cde1df8b..8d9c20364 100644 --- a/hasher.h +++ b/hasher.h @@ -26,55 +26,57 @@ #include #include -#include "sha2.h" -#include "sha3.h" #include "blake256.h" -#include "groestl.h" #include "blake2b.h" +#include "groestl.h" +#include "sha2.h" +#include "sha3.h" #define HASHER_DIGEST_LENGTH 32 typedef enum { - HASHER_SHA2, - HASHER_SHA2D, - HASHER_SHA2_RIPEMD, + HASHER_SHA2, + HASHER_SHA2D, + HASHER_SHA2_RIPEMD, - HASHER_SHA3, + HASHER_SHA3, #if USE_KECCAK - HASHER_SHA3K, + HASHER_SHA3K, #endif - HASHER_BLAKE, - HASHER_BLAKED, - HASHER_BLAKE_RIPEMD, + HASHER_BLAKE, + HASHER_BLAKED, + HASHER_BLAKE_RIPEMD, - HASHER_GROESTLD_TRUNC, /* Double Groestl512 hasher truncated to 256 bits */ + HASHER_GROESTLD_TRUNC, /* Double Groestl512 hasher truncated to 256 bits */ - HASHER_BLAKE2B, - HASHER_BLAKE2B_PERSONAL, + HASHER_BLAKE2B, + HASHER_BLAKE2B_PERSONAL, } HasherType; typedef struct { - HasherType type; + HasherType type; - union { - SHA256_CTX sha2; // for HASHER_SHA2{,D} - SHA3_CTX sha3; // for HASHER_SHA3{,K} - BLAKE256_CTX blake; // for HASHER_BLAKE{,D} - GROESTL512_CTX groestl; // for HASHER_GROESTLD_TRUNC - BLAKE2B_CTX blake2b; // for HASHER_BLAKE2B{,_PERSONAL} - } ctx; + union { + SHA256_CTX sha2; // for HASHER_SHA2{,D} + SHA3_CTX sha3; // for HASHER_SHA3{,K} + BLAKE256_CTX blake; // for HASHER_BLAKE{,D} + GROESTL512_CTX groestl; // for HASHER_GROESTLD_TRUNC + BLAKE2B_CTX blake2b; // for HASHER_BLAKE2B{,_PERSONAL} + } ctx; - const void *param; - uint32_t param_size; + const void *param; + uint32_t param_size; } Hasher; -void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size); +void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, + uint32_t param_size); void hasher_Init(Hasher *hasher, HasherType type); void hasher_Reset(Hasher *hasher); void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length); void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]); -void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]); +void hasher_Raw(HasherType type, const uint8_t *data, size_t length, + uint8_t hash[HASHER_DIGEST_LENGTH]); #endif diff --git a/hmac.c b/hmac.c index 0a0946012..fa2b68947 100644 --- a/hmac.c +++ b/hmac.c @@ -24,155 +24,153 @@ #include #include "hmac.h" -#include "options.h" #include "memzero.h" +#include "options.h" -void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen) -{ - static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH]; - memzero(i_key_pad, SHA256_BLOCK_LENGTH); - if (keylen > SHA256_BLOCK_LENGTH) { - sha256_Raw(key, keylen, i_key_pad); - } else { - memcpy(i_key_pad, key, keylen); - } - for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) { - hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; - i_key_pad[i] ^= 0x36; - } - sha256_Init(&(hctx->ctx)); - sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH); - memzero(i_key_pad, sizeof(i_key_pad)); +void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, + const uint32_t keylen) { + static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH]; + memzero(i_key_pad, SHA256_BLOCK_LENGTH); + if (keylen > SHA256_BLOCK_LENGTH) { + sha256_Raw(key, keylen, i_key_pad); + } else { + memcpy(i_key_pad, key, keylen); + } + for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) { + hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; + i_key_pad[i] ^= 0x36; + } + sha256_Init(&(hctx->ctx)); + sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH); + memzero(i_key_pad, sizeof(i_key_pad)); } -void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen) -{ - sha256_Update(&(hctx->ctx), msg, msglen); +void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, + const uint32_t msglen) { + sha256_Update(&(hctx->ctx), msg, msglen); } -void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) -{ - sha256_Final(&(hctx->ctx), hmac); - sha256_Init(&(hctx->ctx)); - sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH); - sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH); - sha256_Final(&(hctx->ctx), hmac); - memzero(hctx, sizeof(HMAC_SHA256_CTX)); +void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) { + sha256_Final(&(hctx->ctx), hmac); + sha256_Init(&(hctx->ctx)); + sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH); + sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH); + sha256_Final(&(hctx->ctx), hmac); + memzero(hctx, sizeof(HMAC_SHA256_CTX)); } -void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) -{ - static CONFIDENTIAL HMAC_SHA256_CTX hctx; - hmac_sha256_Init(&hctx, key, keylen); - hmac_sha256_Update(&hctx, msg, msglen); - hmac_sha256_Final(&hctx, hmac); +void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, + const uint32_t msglen, uint8_t *hmac) { + static CONFIDENTIAL HMAC_SHA256_CTX hctx; + hmac_sha256_Init(&hctx, key, keylen); + hmac_sha256_Update(&hctx, msg, msglen); + hmac_sha256_Final(&hctx, hmac); } -void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest) -{ - static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH/sizeof(uint32_t)]; - - memzero(key_pad, sizeof(key_pad)); - if (keylen > SHA256_BLOCK_LENGTH) { - static CONFIDENTIAL SHA256_CTX context; - sha256_Init(&context); - sha256_Update(&context, key, keylen); - sha256_Final(&context, (uint8_t*)key_pad); - } else { - memcpy(key_pad, key, keylen); - } - - /* compute o_key_pad and its digest */ - for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { - uint32_t data; +void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, + uint32_t *opad_digest, uint32_t *ipad_digest) { + static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; + + memzero(key_pad, sizeof(key_pad)); + if (keylen > SHA256_BLOCK_LENGTH) { + static CONFIDENTIAL SHA256_CTX context; + sha256_Init(&context); + sha256_Update(&context, key, keylen); + sha256_Final(&context, (uint8_t *)key_pad); + } else { + memcpy(key_pad, key, keylen); + } + + /* compute o_key_pad and its digest */ + for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) { + uint32_t data; #if BYTE_ORDER == LITTLE_ENDIAN - REVERSE32(key_pad[i], data); + REVERSE32(key_pad[i], data); #else - data = key_pad[i]; + data = key_pad[i]; #endif - key_pad[i] = data ^ 0x5c5c5c5c; - } - sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest); - - /* convert o_key_pad to i_key_pad and compute its digest */ - for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { - key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636; - } - sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest); - memzero(key_pad, sizeof(key_pad)); + key_pad[i] = data ^ 0x5c5c5c5c; + } + sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest); + + /* convert o_key_pad to i_key_pad and compute its digest */ + for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) { + key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636; + } + sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest); + memzero(key_pad, sizeof(key_pad)); } -void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen) -{ - static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH]; - memzero(i_key_pad, SHA512_BLOCK_LENGTH); - if (keylen > SHA512_BLOCK_LENGTH) { - sha512_Raw(key, keylen, i_key_pad); - } else { - memcpy(i_key_pad, key, keylen); - } - for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) { - hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; - i_key_pad[i] ^= 0x36; - } - sha512_Init(&(hctx->ctx)); - sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH); - memzero(i_key_pad, sizeof(i_key_pad)); +void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, + const uint32_t keylen) { + static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH]; + memzero(i_key_pad, SHA512_BLOCK_LENGTH); + if (keylen > SHA512_BLOCK_LENGTH) { + sha512_Raw(key, keylen, i_key_pad); + } else { + memcpy(i_key_pad, key, keylen); + } + for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) { + hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; + i_key_pad[i] ^= 0x36; + } + sha512_Init(&(hctx->ctx)); + sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH); + memzero(i_key_pad, sizeof(i_key_pad)); } -void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen) -{ - sha512_Update(&(hctx->ctx), msg, msglen); +void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, + const uint32_t msglen) { + sha512_Update(&(hctx->ctx), msg, msglen); } -void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) -{ - sha512_Final(&(hctx->ctx), hmac); - sha512_Init(&(hctx->ctx)); - sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH); - sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH); - sha512_Final(&(hctx->ctx), hmac); - memzero(hctx, sizeof(HMAC_SHA512_CTX)); +void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) { + sha512_Final(&(hctx->ctx), hmac); + sha512_Init(&(hctx->ctx)); + sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH); + sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH); + sha512_Final(&(hctx->ctx), hmac); + memzero(hctx, sizeof(HMAC_SHA512_CTX)); } -void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) -{ - HMAC_SHA512_CTX hctx; - hmac_sha512_Init(&hctx, key, keylen); - hmac_sha512_Update(&hctx, msg, msglen); - hmac_sha512_Final(&hctx, hmac); +void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, + const uint32_t msglen, uint8_t *hmac) { + HMAC_SHA512_CTX hctx; + hmac_sha512_Init(&hctx, key, keylen); + hmac_sha512_Update(&hctx, msg, msglen); + hmac_sha512_Final(&hctx, hmac); } -void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest) -{ - static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; - - memzero(key_pad, sizeof(key_pad)); - if (keylen > SHA512_BLOCK_LENGTH) { - static CONFIDENTIAL SHA512_CTX context; - sha512_Init(&context); - sha512_Update(&context, key, keylen); - sha512_Final(&context, (uint8_t*)key_pad); - } else { - memcpy(key_pad, key, keylen); - } - - /* compute o_key_pad and its digest */ - for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { - uint64_t data; +void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, + uint64_t *opad_digest, uint64_t *ipad_digest) { + static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; + + memzero(key_pad, sizeof(key_pad)); + if (keylen > SHA512_BLOCK_LENGTH) { + static CONFIDENTIAL SHA512_CTX context; + sha512_Init(&context); + sha512_Update(&context, key, keylen); + sha512_Final(&context, (uint8_t *)key_pad); + } else { + memcpy(key_pad, key, keylen); + } + + /* compute o_key_pad and its digest */ + for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) { + uint64_t data; #if BYTE_ORDER == LITTLE_ENDIAN - REVERSE64(key_pad[i], data); + REVERSE64(key_pad[i], data); #else - data = key_pad[i]; + data = key_pad[i]; #endif - key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c; - } - sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest); - - /* convert o_key_pad to i_key_pad and compute its digest */ - for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { - key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636; - } - sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest); - memzero(key_pad, sizeof(key_pad)); + key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c; + } + sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest); + + /* convert o_key_pad to i_key_pad and compute its digest */ + for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) { + key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636; + } + sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest); + memzero(key_pad, sizeof(key_pad)); } diff --git a/hmac.h b/hmac.h index 3cfc0cd0f..3921a171e 100644 --- a/hmac.h +++ b/hmac.h @@ -28,25 +28,33 @@ #include "sha2.h" typedef struct _HMAC_SHA256_CTX { - uint8_t o_key_pad[SHA256_BLOCK_LENGTH]; - SHA256_CTX ctx; + uint8_t o_key_pad[SHA256_BLOCK_LENGTH]; + SHA256_CTX ctx; } HMAC_SHA256_CTX; typedef struct _HMAC_SHA512_CTX { - uint8_t o_key_pad[SHA512_BLOCK_LENGTH]; - SHA512_CTX ctx; + uint8_t o_key_pad[SHA512_BLOCK_LENGTH]; + SHA512_CTX ctx; } HMAC_SHA512_CTX; -void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen); -void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen); +void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, + const uint32_t keylen); +void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, + const uint32_t msglen); void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac); -void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); -void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest); +void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, + const uint32_t msglen, uint8_t *hmac); +void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, + uint32_t *opad_digest, uint32_t *ipad_digest); -void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen); -void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen); +void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, + const uint32_t keylen); +void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, + const uint32_t msglen); void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac); -void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); -void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest); +void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, + const uint32_t msglen, uint8_t *hmac); +void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, + uint64_t *opad_digest, uint64_t *ipad_digest); #endif diff --git a/memzero.c b/memzero.c index 3c3a7383d..6a517ff38 100644 --- a/memzero.c +++ b/memzero.c @@ -1,5 +1,5 @@ #ifndef __STDC_WANT_LIB_EXT1__ -#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface. +#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface. #endif #include @@ -18,12 +18,13 @@ #endif // GNU C Library version 2.25 or later. -#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#if defined(__GLIBC__) && \ + (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) #define HAVE_EXPLICIT_BZERO 1 #endif // Newlib -#if defined( __NEWLIB__) +#if defined(__NEWLIB__) #define HAVE_EXPLICIT_BZERO 1 #endif @@ -42,25 +43,24 @@ #define HAVE_EXPLICIT_MEMSET 1 #endif -// Adapted from https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130 +// Adapted from +// https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130 -void memzero(void *const pnt, const size_t len) -{ +void memzero(void *const pnt, const size_t len) { #ifdef _WIN32 - SecureZeroMemory(pnt, len); + SecureZeroMemory(pnt, len); #elif defined(HAVE_MEMSET_S) - memset_s(pnt, (rsize_t) len, 0, (rsize_t) len); + memset_s(pnt, (rsize_t)len, 0, (rsize_t)len); #elif defined(HAVE_EXPLICIT_BZERO) - explicit_bzero(pnt, len); + explicit_bzero(pnt, len); #elif defined(HAVE_EXPLICIT_MEMSET) - explicit_memset(pnt, 0, len); + explicit_memset(pnt, 0, len); #else - volatile unsigned char *volatile pnt_ = - (volatile unsigned char *volatile) pnt; - size_t i = (size_t) 0U; + volatile unsigned char *volatile pnt_ = (volatile unsigned char *volatile)pnt; + size_t i = (size_t)0U; - while (i < len) { - pnt_[i++] = 0U; - } + while (i < len) { + pnt_[i++] = 0U; + } #endif } diff --git a/memzero.h b/memzero.h index a7797d2b3..0a959fbc2 100644 --- a/memzero.h +++ b/memzero.h @@ -3,6 +3,6 @@ #include -void memzero(void * const pnt, const size_t len); +void memzero(void* const pnt, const size_t len); #endif diff --git a/monero/monero.h b/monero/monero.h index d281f333b..ba436c3a3 100644 --- a/monero/monero.h +++ b/monero/monero.h @@ -14,8 +14,8 @@ #endif #include "base58.h" +#include "range_proof.h" #include "serialize.h" #include "xmr.h" -#include "range_proof.h" -#endif //TREZOR_CRYPTO_MONERO_H +#endif // TREZOR_CRYPTO_MONERO_H diff --git a/monero/range_proof.c b/monero/range_proof.c index aaad23dec..832f6f918 100644 --- a/monero/range_proof.c +++ b/monero/range_proof.c @@ -4,112 +4,112 @@ #include "range_proof.h" - -static void xmr_hash_ge25519_to_scalar(bignum256modm r, const ge25519 *p){ - unsigned char buff[32]; - ge25519_pack(buff, p); - xmr_hash_to_scalar(r, buff, sizeof(buff)); +static void xmr_hash_ge25519_to_scalar(bignum256modm r, const ge25519 *p) { + unsigned char buff[32]; + ge25519_pack(buff, p); + xmr_hash_to_scalar(r, buff, sizeof(buff)); } -void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask){ - bignum256modm ai[64]; - bignum256modm alpha[64]; - xmr_gen_range_sig_ex(sig, C, mask, amount, last_mask, ai, alpha); +void xmr_gen_range_sig(xmr_range_sig_t *sig, ge25519 *C, bignum256modm mask, + xmr_amount amount, bignum256modm *last_mask) { + bignum256modm ai[64]; + bignum256modm alpha[64]; + xmr_gen_range_sig_ex(sig, C, mask, amount, last_mask, ai, alpha); } -void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask, - bignum256modm ai[64], bignum256modm alpha[64]) -{ - const unsigned n = XMR_ATOMS; - bignum256modm a={0}; - bignum256modm si={0}; - bignum256modm c={0}; - bignum256modm ee={0}; - unsigned char buff[32]; +void xmr_gen_range_sig_ex(xmr_range_sig_t *sig, ge25519 *C, bignum256modm mask, + xmr_amount amount, bignum256modm *last_mask, + bignum256modm ai[64], bignum256modm alpha[64]) { + const unsigned n = XMR_ATOMS; + bignum256modm a = {0}; + bignum256modm si = {0}; + bignum256modm c = {0}; + bignum256modm ee = {0}; + unsigned char buff[32]; - Hasher kck; - xmr_hasher_init(&kck); + Hasher kck; + xmr_hasher_init(&kck); - ge25519 C_acc; - ge25519 C_h; - ge25519 C_tmp; - ge25519 L; - ge25519 Zero; + ge25519 C_acc; + ge25519 C_h; + ge25519 C_tmp; + ge25519 L; + ge25519 Zero; - ge25519_set_neutral(&Zero); - ge25519_set_neutral(&C_acc); - ge25519_set_xmr_h(&C_h); - set256_modm(a, 0); + ge25519_set_neutral(&Zero); + ge25519_set_neutral(&C_acc); + ge25519_set_xmr_h(&C_h); + set256_modm(a, 0); -#define BB(i) ((amount>>(i)) & 1) +#define BB(i) ((amount >> (i)) & 1) - // First pass, generates: ai, alpha, Ci, ee, s1 - for(unsigned ii=0; iiCi[ii], &C_tmp); + // Set Ci[ii] to sigs + ge25519_pack(sig->Ci[ii], &C_tmp); - if (BB(ii) == 0) { - xmr_random_scalar(si); - xmr_hash_ge25519_to_scalar(c, &L); + if (BB(ii) == 0) { + xmr_random_scalar(si); + xmr_hash_ge25519_to_scalar(c, &L); - ge25519_add(&C_tmp, &C_tmp, &C_h, 1); // Ci[ii] -= c_h - xmr_add_keys2_vartime(&L, si, c, &C_tmp); + ge25519_add(&C_tmp, &C_tmp, &C_h, 1); // Ci[ii] -= c_h + xmr_add_keys2_vartime(&L, si, c, &C_tmp); - // Set s1[ii] to sigs - contract256_modm(sig->asig.s1[ii], si); - } + // Set s1[ii] to sigs + contract256_modm(sig->asig.s1[ii], si); + } - ge25519_pack(buff, &L); - xmr_hasher_update(&kck, buff, sizeof(buff)); + ge25519_pack(buff, &L); + xmr_hasher_update(&kck, buff, sizeof(buff)); - ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2) - } + ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2) + } - // Compute ee - xmr_hasher_final(&kck, buff); - expand256_modm(ee, buff, sizeof(buff)); + // Compute ee + xmr_hasher_final(&kck, buff); + expand256_modm(ee, buff, sizeof(buff)); - ge25519_set_xmr_h(&C_h); + ge25519_set_xmr_h(&C_h); - // Second pass, s0, s1 - for(unsigned ii=0; iiasig.s0[ii], si); + // Second pass, s0, s1 + for (unsigned ii = 0; ii < n; ++ii) { + if (BB(ii) == 0) { + mulsub256_modm(si, ai[ii], ee, alpha[ii]); + contract256_modm(sig->asig.s0[ii], si); - } else { - xmr_random_scalar(si); - contract256_modm(sig->asig.s0[ii], si); + } else { + xmr_random_scalar(si); + contract256_modm(sig->asig.s0[ii], si); - ge25519_unpack_vartime(&C_tmp, sig->Ci[ii]); - xmr_add_keys2_vartime(&L, si, ee, &C_tmp); - xmr_hash_ge25519_to_scalar(c, &L); + ge25519_unpack_vartime(&C_tmp, sig->Ci[ii]); + xmr_add_keys2_vartime(&L, si, ee, &C_tmp); + xmr_hash_ge25519_to_scalar(c, &L); - mulsub256_modm(si, ai[ii], c, alpha[ii]); - contract256_modm(sig->asig.s1[ii], si); - } + mulsub256_modm(si, ai[ii], c, alpha[ii]); + contract256_modm(sig->asig.s1[ii], si); + } - ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2) - } + ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2) + } - ge25519_copy(C, &C_acc); - copy256_modm(mask, a); - contract256_modm(sig->asig.ee, ee); + ge25519_copy(C, &C_acc); + copy256_modm(mask, a); + contract256_modm(sig->asig.ee, ee); #undef BB } - diff --git a/monero/range_proof.h b/monero/range_proof.h index cd846a095..f614ab04e 100644 --- a/monero/range_proof.h +++ b/monero/range_proof.h @@ -12,19 +12,20 @@ typedef uint64_t xmr_amount; typedef xmr_key_t xmr_key64_t[64]; typedef struct xmr_boro_sig { - xmr_key64_t s0; - xmr_key64_t s1; - xmr_key_t ee; + xmr_key64_t s0; + xmr_key64_t s1; + xmr_key_t ee; } xmr_boro_sig_t; typedef struct range_sig { - xmr_boro_sig_t asig; - xmr_key64_t Ci; + xmr_boro_sig_t asig; + xmr_key64_t Ci; } xmr_range_sig_t; - -void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask); -void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask, +void xmr_gen_range_sig(xmr_range_sig_t* sig, ge25519* C, bignum256modm mask, + xmr_amount amount, bignum256modm* last_mask); +void xmr_gen_range_sig_ex(xmr_range_sig_t* sig, ge25519* C, bignum256modm mask, + xmr_amount amount, bignum256modm* last_mask, bignum256modm ai[64], bignum256modm alpha[64]); -#endif //TREZOR_CRYPTO_RANGE_PROOF_H +#endif // TREZOR_CRYPTO_RANGE_PROOF_H diff --git a/monero/serialize.c b/monero/serialize.c index ee6aab420..ebd323b93 100644 --- a/monero/serialize.c +++ b/monero/serialize.c @@ -4,51 +4,50 @@ #include "serialize.h" -int xmr_size_varint(uint64_t num){ - int ctr = 1; - while (num >= 0x80) { - ++ctr; - num >>= 7; - } - return ctr; +int xmr_size_varint(uint64_t num) { + int ctr = 1; + while (num >= 0x80) { + ++ctr; + num >>= 7; + } + return ctr; } -int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num){ - unsigned ctr = 0; - while (num >= 0x80 && ctr < buff_size) { - *buff = (uint8_t) (((num) & 0x7f) | 0x80); - ++buff; - ++ctr; - num >>= 7; - } - - /* writes the last one to dest */ - if (ctr < buff_size) { - *buff = (uint8_t) num; - ++ctr; - } - return ctr <= buff_size ? (int)ctr : -1; +int xmr_write_varint(uint8_t *buff, size_t buff_size, uint64_t num) { + unsigned ctr = 0; + while (num >= 0x80 && ctr < buff_size) { + *buff = (uint8_t)(((num)&0x7f) | 0x80); + ++buff; + ++ctr; + num >>= 7; + } + + /* writes the last one to dest */ + if (ctr < buff_size) { + *buff = (uint8_t)num; + ++ctr; + } + return ctr <= buff_size ? (int)ctr : -1; } -int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val) { - unsigned read = 0; - int finished_ok = 0; - *val = 0; - - for (int shift = 0; read < buff_size; shift += 7, ++read) { - uint8_t byte = buff[read]; - if (byte == 0 && shift != 0) { - return -1; - } - - *val |= (uint64_t)(byte & 0x7f) << shift; - - /* If there is no next */ - if ((byte & 0x80) == 0) { - finished_ok = 1; - break; - } - } - return finished_ok ? (int)read + 1 : -2; +int xmr_read_varint(uint8_t *buff, size_t buff_size, uint64_t *val) { + unsigned read = 0; + int finished_ok = 0; + *val = 0; + + for (int shift = 0; read < buff_size; shift += 7, ++read) { + uint8_t byte = buff[read]; + if (byte == 0 && shift != 0) { + return -1; + } + + *val |= (uint64_t)(byte & 0x7f) << shift; + + /* If there is no next */ + if ((byte & 0x80) == 0) { + finished_ok = 1; + break; + } + } + return finished_ok ? (int)read + 1 : -2; } - diff --git a/monero/serialize.h b/monero/serialize.h index f2b0fb903..8d3499007 100644 --- a/monero/serialize.h +++ b/monero/serialize.h @@ -9,7 +9,7 @@ #include int xmr_size_varint(uint64_t num); -int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num); -int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val); +int xmr_write_varint(uint8_t *buff, size_t buff_size, uint64_t num); +int xmr_read_varint(uint8_t *buff, size_t buff_size, uint64_t *val); -#endif //TREZOR_XMR_SERIALIZE_H +#endif // TREZOR_XMR_SERIALIZE_H diff --git a/monero/xmr.c b/monero/xmr.c index 7a3576348..25199b1b1 100644 --- a/monero/xmr.c +++ b/monero/xmr.c @@ -4,133 +4,140 @@ #include "xmr.h" #include "int-util.h" -#include "serialize.h" #include "rand.h" - +#include "serialize.h" const ge25519 ALIGN(16) xmr_h = { - {0x1861ec7, 0x1ceac77, 0x2f11626, 0x1f261d3, 0x346107c, 0x06d8c4a, 0x254201d, 0x1675c09, 0x1301c3f, 0x0211d73}, - {0x326feb4, 0x12e30cc, 0x0cf54b4, 0x1117305, 0x318f5d5, 0x06cf754, 0x2e578a1, 0x1daf058, 0x34430a1, 0x04410e9}, - {0x0fde4d2, 0x0774049, 0x22ca951, 0x05aec2b, 0x07a36a5, 0x1394f13, 0x3c5385c, 0x1adb924, 0x2b6c581, 0x0a55fa4}, - {0x24517f7, 0x05ee936, 0x3acf5d9, 0x14b08aa, 0x3363738, 0x1051745, 0x360601e, 0x0f3f2c9, 0x1ead2cd, 0x1d3e3df} -}; + {0x1861ec7, 0x1ceac77, 0x2f11626, 0x1f261d3, 0x346107c, 0x06d8c4a, + 0x254201d, 0x1675c09, 0x1301c3f, 0x0211d73}, + {0x326feb4, 0x12e30cc, 0x0cf54b4, 0x1117305, 0x318f5d5, 0x06cf754, + 0x2e578a1, 0x1daf058, 0x34430a1, 0x04410e9}, + {0x0fde4d2, 0x0774049, 0x22ca951, 0x05aec2b, 0x07a36a5, 0x1394f13, + 0x3c5385c, 0x1adb924, 0x2b6c581, 0x0a55fa4}, + {0x24517f7, 0x05ee936, 0x3acf5d9, 0x14b08aa, 0x3363738, 0x1051745, + 0x360601e, 0x0f3f2c9, 0x1ead2cd, 0x1d3e3df}}; +void ge25519_set_xmr_h(ge25519 *r) { ge25519_copy(r, &xmr_h); } -void ge25519_set_xmr_h(ge25519 *r){ - ge25519_copy(r, &xmr_h); +void xmr_random_scalar(bignum256modm m) { + unsigned char buff[32] = {0}; + random_buffer(buff, sizeof(buff)); + expand256_modm(m, buff, sizeof(buff)); } -void xmr_random_scalar(bignum256modm m){ - unsigned char buff[32]={0}; - random_buffer(buff, sizeof(buff)); - expand256_modm(m, buff, sizeof(buff)); +void xmr_fast_hash(uint8_t *hash, const void *data, size_t length) { + hasher_Raw(HASHER_SHA3K, data, length, hash); } -void xmr_fast_hash(uint8_t * hash, const void *data, size_t length){ - hasher_Raw(HASHER_SHA3K, data, length, hash); -} - -void xmr_hasher_init(Hasher * hasher){ - hasher_Init(hasher, HASHER_SHA3K); -} +void xmr_hasher_init(Hasher *hasher) { hasher_Init(hasher, HASHER_SHA3K); } -void xmr_hasher_update(Hasher * hasher, const void *data, size_t length){ - hasher_Update(hasher, data, length); +void xmr_hasher_update(Hasher *hasher, const void *data, size_t length) { + hasher_Update(hasher, data, length); } -void xmr_hasher_final(Hasher * hasher, uint8_t * hash){ - hasher_Final(hasher, hash); +void xmr_hasher_final(Hasher *hasher, uint8_t *hash) { + hasher_Final(hasher, hash); } -void xmr_hasher_copy(Hasher * dst, const Hasher * src){ - memcpy(dst, src, sizeof(Hasher)); +void xmr_hasher_copy(Hasher *dst, const Hasher *src) { + memcpy(dst, src, sizeof(Hasher)); } -void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length){ - uint8_t hash[HASHER_DIGEST_LENGTH]; - hasher_Raw(HASHER_SHA3K, data, length, hash); - expand256_modm(r, hash, HASHER_DIGEST_LENGTH); +void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length) { + uint8_t hash[HASHER_DIGEST_LENGTH]; + hasher_Raw(HASHER_SHA3K, data, length, hash); + expand256_modm(r, hash, HASHER_DIGEST_LENGTH); } -void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length){ - ge25519 point2; - uint8_t hash[HASHER_DIGEST_LENGTH]; - hasher_Raw(HASHER_SHA3K, data, length, hash); +void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length) { + ge25519 point2; + uint8_t hash[HASHER_DIGEST_LENGTH]; + hasher_Raw(HASHER_SHA3K, data, length, hash); - ge25519_fromfe_frombytes_vartime(&point2, hash); - ge25519_mul8(P, &point2); + ge25519_fromfe_frombytes_vartime(&point2, hash); + ge25519_mul8(P, &point2); } -void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index){ - uint8_t buff[32 + 8]; - ge25519_pack(buff, p); - int written = xmr_write_varint(buff + 32, 8, output_index); - xmr_hash_to_scalar(s, buff, 32u + written); +void xmr_derivation_to_scalar(bignum256modm s, const ge25519 *p, + uint32_t output_index) { + uint8_t buff[32 + 8]; + ge25519_pack(buff, p); + int written = xmr_write_varint(buff + 32, 8, output_index); + xmr_hash_to_scalar(s, buff, 32u + written); } -void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b){ - ge25519 bA; - ge25519_scalarmult(&bA, A, b); - ge25519_mul8(r, &bA); +void xmr_generate_key_derivation(ge25519 *r, const ge25519 *A, + const bignum256modm b) { + ge25519 bA; + ge25519_scalarmult(&bA, A, b); + ge25519_mul8(r, &bA); } -void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base){ - xmr_derivation_to_scalar(s, deriv, idx); - add256_modm(s, s, base); +void xmr_derive_private_key(bignum256modm s, const ge25519 *deriv, uint32_t idx, + const bignum256modm base) { + xmr_derivation_to_scalar(s, deriv, idx); + add256_modm(s, s, base); } -void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base){ - bignum256modm s={0}; - ge25519 p2; +void xmr_derive_public_key(ge25519 *r, const ge25519 *deriv, uint32_t idx, + const ge25519 *base) { + bignum256modm s = {0}; + ge25519 p2; - xmr_derivation_to_scalar(s, deriv, idx); - ge25519_scalarmult_base_niels(&p2, ge25519_niels_base_multiples, s); - ge25519_add(r, base, &p2, 0); + xmr_derivation_to_scalar(s, deriv, idx); + ge25519_scalarmult_base_niels(&p2, ge25519_niels_base_multiples, s); + ge25519_add(r, base, &p2, 0); } -void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){ - // aG + bB, G is basepoint - ge25519 aG, bB; - ge25519_scalarmult_base_niels(&aG, ge25519_niels_base_multiples, a); - ge25519_scalarmult(&bB, B, b); - ge25519_add(r, &aG, &bB, 0); +void xmr_add_keys2(ge25519 *r, const bignum256modm a, const bignum256modm b, + const ge25519 *B) { + // aG + bB, G is basepoint + ge25519 aG, bB; + ge25519_scalarmult_base_niels(&aG, ge25519_niels_base_multiples, a); + ge25519_scalarmult(&bB, B, b); + ge25519_add(r, &aG, &bB, 0); } -void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){ - // aG + bB, G is basepoint - ge25519_double_scalarmult_vartime(r, B, b, a); +void xmr_add_keys2_vartime(ge25519 *r, const bignum256modm a, + const bignum256modm b, const ge25519 *B) { + // aG + bB, G is basepoint + ge25519_double_scalarmult_vartime(r, B, b, a); } -void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){ - // aA + bB - ge25519 aA, bB; - ge25519_scalarmult(&aA, A, a); - ge25519_scalarmult(&bB, B, b); - ge25519_add(r, &aA, &bB, 0); +void xmr_add_keys3(ge25519 *r, const bignum256modm a, const ge25519 *A, + const bignum256modm b, const ge25519 *B) { + // aA + bB + ge25519 aA, bB; + ge25519_scalarmult(&aA, A, a); + ge25519_scalarmult(&bB, B, b); + ge25519_add(r, &aA, &bB, 0); } -void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){ - // aA + bB - ge25519_double_scalarmult_vartime2(r, A, a, B, b); +void xmr_add_keys3_vartime(ge25519 *r, const bignum256modm a, const ge25519 *A, + const bignum256modm b, const ge25519 *B) { + // aA + bB + ge25519_double_scalarmult_vartime2(r, A, a, B, b); } -void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m){ - const char prefix[] = "SubAddr"; - unsigned char buff[32]; - contract256_modm(buff, m); +void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, + uint32_t minor, const bignum256modm m) { + const char prefix[] = "SubAddr"; + unsigned char buff[32]; + contract256_modm(buff, m); - char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)]; - memcpy(data, prefix, sizeof(prefix)); - memcpy(data + sizeof(prefix), buff, sizeof(buff)); - memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t)); - memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor, sizeof(uint32_t)); + char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)]; + memcpy(data, prefix, sizeof(prefix)); + memcpy(data + sizeof(prefix), buff, sizeof(buff)); + memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t)); + memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor, + sizeof(uint32_t)); - xmr_hash_to_scalar(r, data, sizeof(data)); + xmr_hash_to_scalar(r, data, sizeof(data)); } -void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount){ - // C = aG + bH - bignum256modm b={0}; - set256_modm(b, amount); - xmr_add_keys2(r, a, b, &xmr_h); +void xmr_gen_c(ge25519 *r, const bignum256modm a, uint64_t amount) { + // C = aG + bH + bignum256modm b = {0}; + set256_modm(b, amount); + xmr_add_keys2(r, a, b, &xmr_h); } diff --git a/monero/xmr.h b/monero/xmr.h index 83cdf83b4..4ef83a06b 100644 --- a/monero/xmr.h +++ b/monero/xmr.h @@ -24,13 +24,13 @@ void ge25519_set_xmr_h(ge25519 *r); void xmr_random_scalar(bignum256modm m); /* cn_fast_hash */ -void xmr_fast_hash(uint8_t * hash, const void *data, size_t length); +void xmr_fast_hash(uint8_t *hash, const void *data, size_t length); /* incremental hashing wrappers */ -void xmr_hasher_init(Hasher * hasher); -void xmr_hasher_update(Hasher * hasher, const void *data, size_t length); -void xmr_hasher_final(Hasher * hasher, uint8_t * hash); -void xmr_hasher_copy(Hasher * dst, const Hasher * src); +void xmr_hasher_init(Hasher *hasher); +void xmr_hasher_update(Hasher *hasher, const void *data, size_t length); +void xmr_hasher_final(Hasher *hasher, uint8_t *hash); +void xmr_hasher_copy(Hasher *dst, const Hasher *src); /* H_s(buffer) */ void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length); @@ -39,29 +39,38 @@ void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length); void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length); /* derivation to scalar value */ -void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index); +void xmr_derivation_to_scalar(bignum256modm s, const ge25519 *p, + uint32_t output_index); /* derivation */ -void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b); +void xmr_generate_key_derivation(ge25519 *r, const ge25519 *A, + const bignum256modm b); /* H_s(derivation || varint(output_index)) + base */ -void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base); +void xmr_derive_private_key(bignum256modm s, const ge25519 *deriv, uint32_t idx, + const bignum256modm base); /* H_s(derivation || varint(output_index))G + base */ -void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base); +void xmr_derive_public_key(ge25519 *r, const ge25519 *deriv, uint32_t idx, + const ge25519 *base); /* aG + bB, G is basepoint */ -void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B); -void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B); +void xmr_add_keys2(ge25519 *r, const bignum256modm a, const bignum256modm b, + const ge25519 *B); +void xmr_add_keys2_vartime(ge25519 *r, const bignum256modm a, + const bignum256modm b, const ge25519 *B); /* aA + bB */ -void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B); -void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B); +void xmr_add_keys3(ge25519 *r, const bignum256modm a, const ge25519 *A, + const bignum256modm b, const ge25519 *B); +void xmr_add_keys3_vartime(ge25519 *r, const bignum256modm a, const ge25519 *A, + const bignum256modm b, const ge25519 *B); /* subaddress secret */ -void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m); +void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, + uint32_t minor, const bignum256modm m); /* Generates Pedersen commitment C = aG + bH */ -void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount); +void xmr_gen_c(ge25519 *r, const bignum256modm a, uint64_t amount); -#endif //TREZOR_CRYPTO_XMR_H +#endif // TREZOR_CRYPTO_XMR_H diff --git a/nem.c b/nem.c index 39c9ac586..5fd55e5d3 100644 --- a/nem.c +++ b/nem.c @@ -26,544 +26,483 @@ #include "base32.h" #include "ed25519-donna/ed25519-keccak.h" +#include "memzero.h" #include "ripemd160.h" #include "sha3.h" -#include "memzero.h" #define CAN_WRITE(NEEDED) ((ctx->offset + (NEEDED)) <= ctx->size) -#define SERIALIZE_U32(DATA) \ - do { if (!nem_write_u32(ctx, (DATA))) return false; } while (0) -#define SERIALIZE_U64(DATA) \ - do { if (!nem_write_u64(ctx, (DATA))) return false; } while (0) -#define SERIALIZE_TAGGED(DATA, LENGTH) \ - do { if (!nem_write_tagged(ctx, (DATA), (LENGTH))) return false; } while (0) - +#define SERIALIZE_U32(DATA) \ + do { \ + if (!nem_write_u32(ctx, (DATA))) return false; \ + } while (0) +#define SERIALIZE_U64(DATA) \ + do { \ + if (!nem_write_u64(ctx, (DATA))) return false; \ + } while (0) +#define SERIALIZE_TAGGED(DATA, LENGTH) \ + do { \ + if (!nem_write_tagged(ctx, (DATA), (LENGTH))) return false; \ + } while (0) const char *nem_network_name(uint8_t network) { - switch (network) { - case NEM_NETWORK_MAINNET: - return "NEM Mainnet"; - case NEM_NETWORK_TESTNET: - return "NEM Testnet"; - case NEM_NETWORK_MIJIN: - return "Mijin"; - default: - return NULL; - } + switch (network) { + case NEM_NETWORK_MAINNET: + return "NEM Mainnet"; + case NEM_NETWORK_TESTNET: + return "NEM Testnet"; + case NEM_NETWORK_MIJIN: + return "Mijin"; + default: + return NULL; + } } -static inline bool nem_write_checked(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) { - if (!CAN_WRITE(length)) { - return false; - } +static inline bool nem_write_checked(nem_transaction_ctx *ctx, + const uint8_t *data, uint32_t length) { + if (!CAN_WRITE(length)) { + return false; + } - memcpy(&ctx->buffer[ctx->offset], data, length); - ctx->offset += length; - return true; + memcpy(&ctx->buffer[ctx->offset], data, length); + ctx->offset += length; + return true; } static inline bool nem_write_u32(nem_transaction_ctx *ctx, uint32_t data) { - if (!CAN_WRITE(4)) { - return false; - } + if (!CAN_WRITE(4)) { + return false; + } - ctx->buffer[ctx->offset++] = (data >> 0) & 0xff; - ctx->buffer[ctx->offset++] = (data >> 8) & 0xff; - ctx->buffer[ctx->offset++] = (data >> 16) & 0xff; - ctx->buffer[ctx->offset++] = (data >> 24) & 0xff; + ctx->buffer[ctx->offset++] = (data >> 0) & 0xff; + ctx->buffer[ctx->offset++] = (data >> 8) & 0xff; + ctx->buffer[ctx->offset++] = (data >> 16) & 0xff; + ctx->buffer[ctx->offset++] = (data >> 24) & 0xff; - return true; + return true; } static inline bool nem_write_u64(nem_transaction_ctx *ctx, uint64_t data) { - SERIALIZE_U32((data >> 0) & 0xffffffff); - SERIALIZE_U32((data >> 32) & 0xffffffff); + SERIALIZE_U32((data >> 0) & 0xffffffff); + SERIALIZE_U32((data >> 32) & 0xffffffff); - return true; + return true; } -static inline bool nem_write_tagged(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) { - SERIALIZE_U32(length); +static inline bool nem_write_tagged(nem_transaction_ctx *ctx, + const uint8_t *data, uint32_t length) { + SERIALIZE_U32(length); - return nem_write_checked(ctx, data, length); + return nem_write_checked(ctx, data, length); } -static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx, const char *name, const char *value) { - uint32_t name_length = strlen(name); - uint32_t value_length = strlen(value); +static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx, + const char *name, const char *value) { + uint32_t name_length = strlen(name); + uint32_t value_length = strlen(value); - SERIALIZE_U32(sizeof(uint32_t) + name_length + sizeof(uint32_t) + value_length); - SERIALIZE_TAGGED((const uint8_t *) name, name_length); - SERIALIZE_TAGGED((const uint8_t *) value, value_length); + SERIALIZE_U32(sizeof(uint32_t) + name_length + sizeof(uint32_t) + + value_length); + SERIALIZE_TAGGED((const uint8_t *)name, name_length); + SERIALIZE_TAGGED((const uint8_t *)value, value_length); - return true; + return true; } -static inline bool nem_write_mosaic_bool(nem_transaction_ctx *ctx, const char *name, bool value) { - return nem_write_mosaic_str(ctx, name, value ? "true" : "false"); +static inline bool nem_write_mosaic_bool(nem_transaction_ctx *ctx, + const char *name, bool value) { + return nem_write_mosaic_str(ctx, name, value ? "true" : "false"); } -static inline bool nem_write_mosaic_u64(nem_transaction_ctx *ctx, const char *name, uint64_t value) { - char buffer[21]; +static inline bool nem_write_mosaic_u64(nem_transaction_ctx *ctx, + const char *name, uint64_t value) { + char buffer[21]; - if (bn_format_uint64(value, NULL, NULL, 0, 0, false, buffer, sizeof(buffer)) == 0) { - return false; - } + if (bn_format_uint64(value, NULL, NULL, 0, 0, false, buffer, + sizeof(buffer)) == 0) { + return false; + } - return nem_write_mosaic_str(ctx, name, buffer); + return nem_write_mosaic_str(ctx, name, buffer); } -void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, uint8_t *address) { - uint8_t hash[SHA3_256_DIGEST_LENGTH]; +void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, + uint8_t *address) { + uint8_t hash[SHA3_256_DIGEST_LENGTH]; - /* 1. Perform 256-bit Sha3 on the public key */ - keccak_256(public_key, sizeof(ed25519_public_key), hash); + /* 1. Perform 256-bit Sha3 on the public key */ + keccak_256(public_key, sizeof(ed25519_public_key), hash); - /* 2. Perform 160-bit Ripemd of hash resulting from step 1. */ - ripemd160(hash, SHA3_256_DIGEST_LENGTH, &address[1]); + /* 2. Perform 160-bit Ripemd of hash resulting from step 1. */ + ripemd160(hash, SHA3_256_DIGEST_LENGTH, &address[1]); - /* 3. Prepend version byte to Ripemd hash (either 0x68 or 0x98) */ - address[0] = version; + /* 3. Prepend version byte to Ripemd hash (either 0x68 or 0x98) */ + address[0] = version; - /* 4. Perform 256-bit Sha3 on the result, take the first four bytes as a checksum */ - keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash); + /* 4. Perform 256-bit Sha3 on the result, take the first four bytes as a + * checksum */ + keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash); - /* 5. Concatenate output of step 3 and the checksum from step 4 */ - memcpy(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4); + /* 5. Concatenate output of step 3 and the checksum from step 4 */ + memcpy(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4); - memzero(hash, sizeof(hash)); + memzero(hash, sizeof(hash)); } -bool nem_get_address(const ed25519_public_key public_key, uint8_t version, char *address) { - uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW]; +bool nem_get_address(const ed25519_public_key public_key, uint8_t version, + char *address) { + uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW]; - nem_get_address_raw(public_key, version, pubkeyhash); + nem_get_address_raw(public_key, version, pubkeyhash); - char *ret = base32_encode(pubkeyhash, sizeof(pubkeyhash), address, NEM_ADDRESS_SIZE + 1, BASE32_ALPHABET_RFC4648); + char *ret = base32_encode(pubkeyhash, sizeof(pubkeyhash), address, + NEM_ADDRESS_SIZE + 1, BASE32_ALPHABET_RFC4648); - memzero(pubkeyhash, sizeof(pubkeyhash)); - return (ret != NULL); + memzero(pubkeyhash, sizeof(pubkeyhash)); + return (ret != NULL); } bool nem_validate_address_raw(const uint8_t *address, uint8_t network) { - if (!nem_network_name(network) || address[0] != network) { - return false; - } + if (!nem_network_name(network) || address[0] != network) { + return false; + } - uint8_t hash[SHA3_256_DIGEST_LENGTH]; + uint8_t hash[SHA3_256_DIGEST_LENGTH]; - keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash); - bool valid = (memcmp(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4) == 0); + keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash); + bool valid = (memcmp(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4) == 0); - memzero(hash, sizeof(hash)); - return valid; + memzero(hash, sizeof(hash)); + return valid; } bool nem_validate_address(const char *address, uint8_t network) { - uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW]; + uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW]; - if (strlen(address) != NEM_ADDRESS_SIZE) { - return false; - } + if (strlen(address) != NEM_ADDRESS_SIZE) { + return false; + } - uint8_t *ret = base32_decode(address, NEM_ADDRESS_SIZE, pubkeyhash, sizeof(pubkeyhash), BASE32_ALPHABET_RFC4648); - bool valid = (ret != NULL) && nem_validate_address_raw(pubkeyhash, network); + uint8_t *ret = base32_decode(address, NEM_ADDRESS_SIZE, pubkeyhash, + sizeof(pubkeyhash), BASE32_ALPHABET_RFC4648); + bool valid = (ret != NULL) && nem_validate_address_raw(pubkeyhash, network); - memzero(pubkeyhash, sizeof(pubkeyhash)); - return valid; + memzero(pubkeyhash, sizeof(pubkeyhash)); + return valid; } -void nem_transaction_start(nem_transaction_ctx *ctx, const ed25519_public_key public_key, uint8_t *buffer, size_t size) { - memcpy(ctx->public_key, public_key, sizeof(ctx->public_key)); +void nem_transaction_start(nem_transaction_ctx *ctx, + const ed25519_public_key public_key, uint8_t *buffer, + size_t size) { + memcpy(ctx->public_key, public_key, sizeof(ctx->public_key)); - ctx->buffer = buffer; - ctx->offset = 0; - ctx->size = size; + ctx->buffer = buffer; + ctx->offset = 0; + ctx->size = size; } -size_t nem_transaction_end(nem_transaction_ctx *ctx, const ed25519_secret_key private_key, ed25519_signature signature) { - if (private_key != NULL && signature != NULL) { - ed25519_sign_keccak(ctx->buffer, ctx->offset, private_key, ctx->public_key, signature); - } +size_t nem_transaction_end(nem_transaction_ctx *ctx, + const ed25519_secret_key private_key, + ed25519_signature signature) { + if (private_key != NULL && signature != NULL) { + ed25519_sign_keccak(ctx->buffer, ctx->offset, private_key, ctx->public_key, + signature); + } - return ctx->offset; + return ctx->offset; } -bool nem_transaction_write_common(nem_transaction_ctx *ctx, - uint32_t type, - uint32_t version, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline) { - - SERIALIZE_U32(type); - SERIALIZE_U32(version); - SERIALIZE_U32(timestamp); - SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key)); - SERIALIZE_U64(fee); - SERIALIZE_U32(deadline); - - return true; +bool nem_transaction_write_common(nem_transaction_ctx *ctx, uint32_t type, + uint32_t version, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, + uint32_t deadline) { + SERIALIZE_U32(type); + SERIALIZE_U32(version); + SERIALIZE_U32(timestamp); + SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key)); + SERIALIZE_U64(fee); + SERIALIZE_U32(deadline); + + return true; } -bool nem_transaction_create_transfer(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *recipient, - uint64_t amount, - const uint8_t *payload, - uint32_t length, - bool encrypted, - uint32_t mosaics) { - - if (!signer) { - signer = ctx->public_key; - } - - if (!payload) { - length = 0; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_TRANSFER, - (uint32_t) network << 24 | (mosaics ? 2 : 1), - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - SERIALIZE_TAGGED((const uint8_t *) recipient, NEM_ADDRESS_SIZE); - SERIALIZE_U64(amount); - - if (length) { - SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + length); - SERIALIZE_U32(encrypted ? 0x02 : 0x01); - SERIALIZE_TAGGED(payload, length); - } else { - SERIALIZE_U32(0); - } - - if (mosaics) { - - SERIALIZE_U32(mosaics); - - } - - return true; +bool nem_transaction_create_transfer(nem_transaction_ctx *ctx, uint8_t network, + uint32_t timestamp, + const ed25519_public_key signer, + uint64_t fee, uint32_t deadline, + const char *recipient, uint64_t amount, + const uint8_t *payload, uint32_t length, + bool encrypted, uint32_t mosaics) { + if (!signer) { + signer = ctx->public_key; + } + + if (!payload) { + length = 0; + } + + bool ret = + nem_transaction_write_common(ctx, NEM_TRANSACTION_TYPE_TRANSFER, + (uint32_t)network << 24 | (mosaics ? 2 : 1), + timestamp, signer, fee, deadline); + if (!ret) return false; + + SERIALIZE_TAGGED((const uint8_t *)recipient, NEM_ADDRESS_SIZE); + SERIALIZE_U64(amount); + + if (length) { + SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + length); + SERIALIZE_U32(encrypted ? 0x02 : 0x01); + SERIALIZE_TAGGED(payload, length); + } else { + SERIALIZE_U32(0); + } + + if (mosaics) { + SERIALIZE_U32(mosaics); + } + + return true; } bool nem_transaction_write_mosaic(nem_transaction_ctx *ctx, - const char *namespace, - const char *mosaic, - uint64_t quantity) { + const char *namespace, const char *mosaic, + uint64_t quantity) { + size_t namespace_length = strlen(namespace); + size_t mosaic_length = strlen(mosaic); + size_t identifier_length = + sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; + + SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length); + SERIALIZE_U32(identifier_length); + SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length); + SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length); + SERIALIZE_U64(quantity); + + return true; +} - size_t namespace_length = strlen(namespace); - size_t mosaic_length = strlen(mosaic); - size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; +bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, uint8_t network, + uint32_t timestamp, + const ed25519_public_key signer, + uint64_t fee, uint32_t deadline, + const nem_transaction_ctx *inner) { + if (!signer) { + signer = ctx->public_key; + } - SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length); - SERIALIZE_U32(identifier_length); - SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length); - SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length); - SERIALIZE_U64(quantity); + bool ret = nem_transaction_write_common(ctx, NEM_TRANSACTION_TYPE_MULTISIG, + (uint32_t)network << 24 | 1, + timestamp, signer, fee, deadline); + if (!ret) return false; - return true; -} + SERIALIZE_TAGGED(inner->buffer, inner->offset); -bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const nem_transaction_ctx *inner) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_MULTISIG, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - SERIALIZE_TAGGED(inner->buffer, inner->offset); - - return true; + return true; } -bool nem_transaction_create_multisig_signature(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const nem_transaction_ctx *inner) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - char address[NEM_ADDRESS_SIZE + 1]; - nem_get_address(inner->public_key, network, address); - - uint8_t hash[SHA3_256_DIGEST_LENGTH]; - keccak_256(inner->buffer, inner->offset, hash); - - SERIALIZE_U32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH); - SERIALIZE_TAGGED(hash, SHA3_256_DIGEST_LENGTH); - SERIALIZE_TAGGED((const uint8_t *) address, NEM_ADDRESS_SIZE); - - return true; -} +bool nem_transaction_create_multisig_signature( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const nem_transaction_ctx *inner) { + if (!signer) { + signer = ctx->public_key; + } -bool nem_transaction_create_provision_namespace(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *parent, - const char *rental_sink, - uint64_t rental_fee) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - if (parent) { - SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE); - SERIALIZE_U64(rental_fee); - SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace)); - SERIALIZE_TAGGED((const uint8_t *) parent, strlen(parent)); - } else { - SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE); - SERIALIZE_U64(rental_fee); - SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace)); - SERIALIZE_U32(0xffffffff); - } - - return true; -} + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE, (uint32_t)network << 24 | 1, + timestamp, signer, fee, deadline); + if (!ret) return false; + + char address[NEM_ADDRESS_SIZE + 1]; + nem_get_address(inner->public_key, network, address); -bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *mosaic, - const char *description, - uint32_t divisibility, - uint64_t supply, - bool mutable_supply, - bool transferable, - uint32_t levy_type, - uint64_t levy_fee, - const char *levy_address, - const char *levy_namespace, - const char *levy_mosaic, - const char *creation_sink, - uint64_t creation_fee) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_MOSAIC_CREATION, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - size_t namespace_length = strlen(namespace); - size_t mosaic_length = strlen(mosaic); - size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; - - // This length will be rewritten later on - nem_transaction_ctx state; - memcpy(&state, ctx, sizeof(state)); - - SERIALIZE_U32(0); - SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key)); - SERIALIZE_U32(identifier_length); - SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length); - SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length); - SERIALIZE_TAGGED((const uint8_t *) description, strlen(description)); - SERIALIZE_U32(4); // Number of properties - - if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false; - if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false; - if (!nem_write_mosaic_bool(ctx, "supplyMutable", mutable_supply)) return false; - if (!nem_write_mosaic_bool(ctx, "transferable", transferable)) return false; - - if (levy_type) { - size_t levy_namespace_length = strlen(levy_namespace); - size_t levy_mosaic_length = strlen(levy_mosaic); - size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length + sizeof(uint32_t) + levy_mosaic_length; - - SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE + sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t)); - SERIALIZE_U32(levy_type); - SERIALIZE_TAGGED((const uint8_t *) levy_address, NEM_ADDRESS_SIZE); - SERIALIZE_U32(levy_identifier_length); - SERIALIZE_TAGGED((const uint8_t *) levy_namespace, levy_namespace_length); - SERIALIZE_TAGGED((const uint8_t *) levy_mosaic, levy_mosaic_length); - SERIALIZE_U64(levy_fee); - } else { - SERIALIZE_U32(0); - } - - // Rewrite length - nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t)); - - SERIALIZE_TAGGED((const uint8_t *) creation_sink, NEM_ADDRESS_SIZE); - SERIALIZE_U64(creation_fee); - - return true; + uint8_t hash[SHA3_256_DIGEST_LENGTH]; + keccak_256(inner->buffer, inner->offset, hash); + SERIALIZE_U32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH); + SERIALIZE_TAGGED(hash, SHA3_256_DIGEST_LENGTH); + SERIALIZE_TAGGED((const uint8_t *)address, NEM_ADDRESS_SIZE); + + return true; } -bool nem_transaction_create_mosaic_supply_change(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *mosaic, - uint32_t type, - uint64_t delta) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - size_t namespace_length = strlen(namespace); - size_t mosaic_length = strlen(mosaic); - size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; - - SERIALIZE_U32(identifier_length); - SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length); - SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length); - SERIALIZE_U32(type); - SERIALIZE_U64(delta); - - return true; +bool nem_transaction_create_provision_namespace( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *parent, const char *rental_sink, + uint64_t rental_fee) { + if (!signer) { + signer = ctx->public_key; + } + + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE, + (uint32_t)network << 24 | 1, timestamp, signer, fee, deadline); + if (!ret) return false; + + if (parent) { + SERIALIZE_TAGGED((const uint8_t *)rental_sink, NEM_ADDRESS_SIZE); + SERIALIZE_U64(rental_fee); + SERIALIZE_TAGGED((const uint8_t *)namespace, strlen(namespace)); + SERIALIZE_TAGGED((const uint8_t *)parent, strlen(parent)); + } else { + SERIALIZE_TAGGED((const uint8_t *)rental_sink, NEM_ADDRESS_SIZE); + SERIALIZE_U64(rental_fee); + SERIALIZE_TAGGED((const uint8_t *)namespace, strlen(namespace)); + SERIALIZE_U32(0xffffffff); + } + + return true; } -bool nem_transaction_create_aggregate_modification(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - uint32_t modifications, - bool relative_change) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION, - (uint32_t) network << 24 | (relative_change ? 2 : 1), - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - SERIALIZE_U32(modifications); - - return true; +bool nem_transaction_create_mosaic_creation( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *mosaic, const char *description, + uint32_t divisibility, uint64_t supply, bool mutable_supply, + bool transferable, uint32_t levy_type, uint64_t levy_fee, + const char *levy_address, const char *levy_namespace, + const char *levy_mosaic, const char *creation_sink, uint64_t creation_fee) { + if (!signer) { + signer = ctx->public_key; + } + + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_MOSAIC_CREATION, (uint32_t)network << 24 | 1, + timestamp, signer, fee, deadline); + if (!ret) return false; + + size_t namespace_length = strlen(namespace); + size_t mosaic_length = strlen(mosaic); + size_t identifier_length = + sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; + + // This length will be rewritten later on + nem_transaction_ctx state; + memcpy(&state, ctx, sizeof(state)); + + SERIALIZE_U32(0); + SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key)); + SERIALIZE_U32(identifier_length); + SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length); + SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length); + SERIALIZE_TAGGED((const uint8_t *)description, strlen(description)); + SERIALIZE_U32(4); // Number of properties + + if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false; + if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false; + if (!nem_write_mosaic_bool(ctx, "supplyMutable", mutable_supply)) + return false; + if (!nem_write_mosaic_bool(ctx, "transferable", transferable)) return false; + + if (levy_type) { + size_t levy_namespace_length = strlen(levy_namespace); + size_t levy_mosaic_length = strlen(levy_mosaic); + size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length + + sizeof(uint32_t) + levy_mosaic_length; + + SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE + + sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t)); + SERIALIZE_U32(levy_type); + SERIALIZE_TAGGED((const uint8_t *)levy_address, NEM_ADDRESS_SIZE); + SERIALIZE_U32(levy_identifier_length); + SERIALIZE_TAGGED((const uint8_t *)levy_namespace, levy_namespace_length); + SERIALIZE_TAGGED((const uint8_t *)levy_mosaic, levy_mosaic_length); + SERIALIZE_U64(levy_fee); + } else { + SERIALIZE_U32(0); + } + + // Rewrite length + nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t)); + + SERIALIZE_TAGGED((const uint8_t *)creation_sink, NEM_ADDRESS_SIZE); + SERIALIZE_U64(creation_fee); + + return true; } -bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx, - uint32_t type, - const ed25519_public_key cosignatory) { +bool nem_transaction_create_mosaic_supply_change( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *mosaic, uint32_t type, uint64_t delta) { + if (!signer) { + signer = ctx->public_key; + } + + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE, + (uint32_t)network << 24 | 1, timestamp, signer, fee, deadline); + if (!ret) return false; + + size_t namespace_length = strlen(namespace); + size_t mosaic_length = strlen(mosaic); + size_t identifier_length = + sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length; + + SERIALIZE_U32(identifier_length); + SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length); + SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length); + SERIALIZE_U32(type); + SERIALIZE_U64(delta); + + return true; +} - SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(ed25519_public_key)); - SERIALIZE_U32(type); - SERIALIZE_TAGGED(cosignatory, sizeof(ed25519_public_key)); +bool nem_transaction_create_aggregate_modification( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + uint32_t modifications, bool relative_change) { + if (!signer) { + signer = ctx->public_key; + } - return true; + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION, + (uint32_t)network << 24 | (relative_change ? 2 : 1), timestamp, signer, + fee, deadline); + if (!ret) return false; + + SERIALIZE_U32(modifications); + + return true; } -bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx, - int32_t relative_change) { +bool nem_transaction_write_cosignatory_modification( + nem_transaction_ctx *ctx, uint32_t type, + const ed25519_public_key cosignatory) { + SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + + sizeof(ed25519_public_key)); + SERIALIZE_U32(type); + SERIALIZE_TAGGED(cosignatory, sizeof(ed25519_public_key)); - SERIALIZE_U32(sizeof(uint32_t)); - SERIALIZE_U32((uint32_t) relative_change); + return true; +} - return true; +bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx, + int32_t relative_change) { + SERIALIZE_U32(sizeof(uint32_t)); + SERIALIZE_U32((uint32_t)relative_change); + + return true; } -bool nem_transaction_create_importance_transfer(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - uint32_t mode, - const ed25519_public_key remote) { - - if (!signer) { - signer = ctx->public_key; - } - - bool ret = nem_transaction_write_common(ctx, - NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER, - (uint32_t) network << 24 | 1, - timestamp, - signer, - fee, - deadline); - if (!ret) return false; - - SERIALIZE_U32(mode); - SERIALIZE_TAGGED(remote, sizeof(ed25519_public_key)); - - return true; +bool nem_transaction_create_importance_transfer( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + uint32_t mode, const ed25519_public_key remote) { + if (!signer) { + signer = ctx->public_key; + } + + bool ret = nem_transaction_write_common( + ctx, NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER, + (uint32_t)network << 24 | 1, timestamp, signer, fee, deadline); + if (!ret) return false; + + SERIALIZE_U32(mode); + SERIALIZE_TAGGED(remote, sizeof(ed25519_public_key)); + + return true; } diff --git a/nem.h b/nem.h index fe7f7b68f..fe68316fb 100644 --- a/nem.h +++ b/nem.h @@ -31,161 +31,126 @@ #include "ed25519-donna/ed25519.h" #define NEM_LEVY_PERCENTILE_DIVISOR 4 -#define NEM_MAX_DIVISIBILITY 6 -#define NEM_MAX_SUPPLY 9000000000 +#define NEM_MAX_DIVISIBILITY 6 +#define NEM_MAX_SUPPLY 9000000000 #define NEM_NETWORK_MAINNET 0x68 #define NEM_NETWORK_TESTNET 0x98 -#define NEM_NETWORK_MIJIN 0x60 +#define NEM_NETWORK_MIJIN 0x60 #define NEM_ADDRESS_SIZE 40 #define NEM_ADDRESS_SIZE_RAW 25 -#define NEM_TRANSACTION_TYPE_TRANSFER 0x0101 -#define NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER 0x0801 -#define NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION 0x1001 -#define NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE 0x1002 -#define NEM_TRANSACTION_TYPE_MULTISIG 0x1004 -#define NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE 0x2001 -#define NEM_TRANSACTION_TYPE_MOSAIC_CREATION 0x4001 -#define NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE 0x4002 +#define NEM_TRANSACTION_TYPE_TRANSFER 0x0101 +#define NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER 0x0801 +#define NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION 0x1001 +#define NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE 0x1002 +#define NEM_TRANSACTION_TYPE_MULTISIG 0x1004 +#define NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE 0x2001 +#define NEM_TRANSACTION_TYPE_MOSAIC_CREATION 0x4001 +#define NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE 0x4002 #define NEM_SALT_SIZE sizeof(ed25519_public_key) -#define NEM_ENCRYPTED_SIZE(size) (((size) + AES_BLOCK_SIZE) / AES_BLOCK_SIZE * AES_BLOCK_SIZE) -#define NEM_ENCRYPTED_PAYLOAD_SIZE(size) (AES_BLOCK_SIZE + NEM_SALT_SIZE + NEM_ENCRYPTED_SIZE(size)) +#define NEM_ENCRYPTED_SIZE(size) \ + (((size) + AES_BLOCK_SIZE) / AES_BLOCK_SIZE * AES_BLOCK_SIZE) +#define NEM_ENCRYPTED_PAYLOAD_SIZE(size) \ + (AES_BLOCK_SIZE + NEM_SALT_SIZE + NEM_ENCRYPTED_SIZE(size)) -#define _NEM_PADDING_SIZE(buffer, size) ((buffer)[(size) - 1]) -#define NEM_PADDING_SIZE(buffer, size) (_NEM_PADDING_SIZE(buffer, size) > (size) ? (size) : _NEM_PADDING_SIZE(buffer, size)) +#define _NEM_PADDING_SIZE(buffer, size) ((buffer)[(size)-1]) +#define NEM_PADDING_SIZE(buffer, size) \ + (_NEM_PADDING_SIZE(buffer, size) > (size) ? (size) \ + : _NEM_PADDING_SIZE(buffer, size)) -#define NEM_DECRYPTED_SIZE(buffer, size) ((size) - NEM_PADDING_SIZE(buffer, size)) +#define NEM_DECRYPTED_SIZE(buffer, size) ((size)-NEM_PADDING_SIZE(buffer, size)) typedef struct { - ed25519_public_key public_key; - uint8_t *buffer; - size_t offset; - size_t size; + ed25519_public_key public_key; + uint8_t *buffer; + size_t offset; + size_t size; } nem_transaction_ctx; const char *nem_network_name(uint8_t network); -void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, uint8_t *address); -bool nem_get_address(const ed25519_public_key public_key, uint8_t version, char *address); +void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, + uint8_t *address); +bool nem_get_address(const ed25519_public_key public_key, uint8_t version, + char *address); bool nem_validate_address_raw(const uint8_t *address, uint8_t network); bool nem_validate_address(const char *address, uint8_t network); -void nem_transaction_start(nem_transaction_ctx *ctx, const ed25519_public_key public_key, uint8_t *buffer, size_t size); -size_t nem_transaction_end(nem_transaction_ctx *ctx, const ed25519_secret_key private_key, ed25519_signature signature); +void nem_transaction_start(nem_transaction_ctx *ctx, + const ed25519_public_key public_key, uint8_t *buffer, + size_t size); +size_t nem_transaction_end(nem_transaction_ctx *ctx, + const ed25519_secret_key private_key, + ed25519_signature signature); -bool nem_transaction_write_common(nem_transaction_ctx *context, - uint32_t type, - uint32_t version, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline); +bool nem_transaction_write_common(nem_transaction_ctx *context, uint32_t type, + uint32_t version, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, + uint32_t deadline); bool nem_transaction_create_transfer(nem_transaction_ctx *context, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *recipient, - uint64_t amount, - const uint8_t *payload, - uint32_t length, - bool encrypted, - uint32_t mosaics); + uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, + uint64_t fee, uint32_t deadline, + const char *recipient, uint64_t amount, + const uint8_t *payload, uint32_t length, + bool encrypted, uint32_t mosaics); bool nem_transaction_write_mosaic(nem_transaction_ctx *ctx, - const char *namespace, - const char *mosaic, - uint64_t quantity); - -bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const nem_transaction_ctx *inner); - -bool nem_transaction_create_multisig_signature(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const nem_transaction_ctx *inner); - -bool nem_transaction_create_provision_namespace(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *parent, - const char *rental_sink, - uint64_t rental_fee); - -bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *mosaic, - const char *description, - uint32_t divisibility, - uint64_t supply, - bool mutable_supply, - bool transferable, - uint32_t levy_type, - uint64_t levy_fee, - const char *levy_address, - const char *levy_namespace, - const char *levy_mosaic, - const char *creation_sink, - uint64_t creation_fee); - -bool nem_transaction_create_mosaic_supply_change(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - const char *namespace, - const char *mosaic, - uint32_t type, - uint64_t delta); - -bool nem_transaction_create_aggregate_modification(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - uint32_t modifications, - bool relative_change); - -bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx, - uint32_t type, - const ed25519_public_key cosignatory); + const char *namespace, const char *mosaic, + uint64_t quantity); + +bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, uint8_t network, + uint32_t timestamp, + const ed25519_public_key signer, + uint64_t fee, uint32_t deadline, + const nem_transaction_ctx *inner); + +bool nem_transaction_create_multisig_signature( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const nem_transaction_ctx *inner); + +bool nem_transaction_create_provision_namespace( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *parent, const char *rental_sink, + uint64_t rental_fee); + +bool nem_transaction_create_mosaic_creation( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *mosaic, const char *description, + uint32_t divisibility, uint64_t supply, bool mutable_supply, + bool transferable, uint32_t levy_type, uint64_t levy_fee, + const char *levy_address, const char *levy_namespace, + const char *levy_mosaic, const char *creation_sink, uint64_t creation_fee); + +bool nem_transaction_create_mosaic_supply_change( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + const char *namespace, const char *mosaic, uint32_t type, uint64_t delta); + +bool nem_transaction_create_aggregate_modification( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + uint32_t modifications, bool relative_change); + +bool nem_transaction_write_cosignatory_modification( + nem_transaction_ctx *ctx, uint32_t type, + const ed25519_public_key cosignatory); bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx, - int32_t relative_change); - -bool nem_transaction_create_importance_transfer(nem_transaction_ctx *ctx, - uint8_t network, - uint32_t timestamp, - const ed25519_public_key signer, - uint64_t fee, - uint32_t deadline, - uint32_t mode, - const ed25519_public_key remote); + int32_t relative_change); + +bool nem_transaction_create_importance_transfer( + nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp, + const ed25519_public_key signer, uint64_t fee, uint32_t deadline, + uint32_t mode, const ed25519_public_key remote); #endif diff --git a/nist256p1.c b/nist256p1.c index 7cffa5c39..e7e9f3a69 100644 --- a/nist256p1.c +++ b/nist256p1.c @@ -24,42 +24,45 @@ #include "nist256p1.h" const ecdsa_curve nist256p1 = { - /* .prime */ { - /*.val =*/ {0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0, 0x1000, 0x3fffc000, 0xffff} - }, + /* .prime */ {/*.val =*/{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0, + 0x1000, 0x3fffc000, 0xffff}}, - /* G */ { - /*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b, 0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b, 0x6b17}}, - /*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da, 0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86, 0x4fe3}} - }, + /* G */ + {/*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b, + 0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b, + 0x6b17}}, + /*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da, + 0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86, + 0x4fe3}}}, - /* order */ { - /*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc, 0x3fffffff, 0xfff, 0x3fffc000, 0xffff} - }, + /* order */ + {/*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc, + 0x3fffffff, 0xfff, 0x3fffc000, 0xffff}}, - /* order_half */ { - /*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde, 0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff} - }, + /* order_half */ + {/*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde, + 0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff}}, - /* a */ -3, + /* a */ -3, - /* b */ { - /*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65, 0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6} - } + /* b */ + {/*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65, + 0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6}} #if USE_PRECOMPUTED_CP - , - /* cp */ { + , + /* cp */ + { #include "nist256p1.table" - } + } #endif }; const curve_info nist256p1_info = { - .bip32_name = "Nist256p1 seed", - .params = &nist256p1, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "Nist256p1 seed", + .params = &nist256p1, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; diff --git a/nist256p1.h b/nist256p1.h index a1a767efd..02d04025a 100644 --- a/nist256p1.h +++ b/nist256p1.h @@ -26,8 +26,8 @@ #include -#include "ecdsa.h" #include "bip32.h" +#include "ecdsa.h" extern const ecdsa_curve nist256p1; extern const curve_info nist256p1_info; diff --git a/options.h b/options.h index e57654e6c..d3a9c2edf 100644 --- a/options.h +++ b/options.h @@ -52,7 +52,7 @@ // support constructing BIP32 nodes from ed25519 and curve25519 curves. #ifndef USE_BIP32_25519_CURVES -#define USE_BIP32_25519_CURVES 1 +#define USE_BIP32_25519_CURVES 1 #endif // implement BIP39 caching diff --git a/pbkdf2.c b/pbkdf2.c index 719fc89e2..9380b667a 100644 --- a/pbkdf2.c +++ b/pbkdf2.c @@ -21,157 +21,159 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include #include "pbkdf2.h" +#include #include "hmac.h" -#include "sha2.h" #include "memzero.h" +#include "sha2.h" -void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr) -{ - SHA256_CTX ctx; +void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, + int passlen, const uint8_t *salt, int saltlen, + uint32_t blocknr) { + SHA256_CTX ctx; #if BYTE_ORDER == LITTLE_ENDIAN - REVERSE32(blocknr, blocknr); + REVERSE32(blocknr, blocknr); #endif - hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig); - memzero(pctx->g, sizeof(pctx->g)); - pctx->g[8] = 0x80000000; - pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8; + hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig); + memzero(pctx->g, sizeof(pctx->g)); + pctx->g[8] = 0x80000000; + pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8; - memcpy (ctx.state, pctx->idig, sizeof(pctx->idig)); - ctx.bitcount = SHA256_BLOCK_LENGTH * 8; - sha256_Update(&ctx, salt, saltlen); - sha256_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr)); - sha256_Final(&ctx, (uint8_t*)pctx->g); + memcpy(ctx.state, pctx->idig, sizeof(pctx->idig)); + ctx.bitcount = SHA256_BLOCK_LENGTH * 8; + sha256_Update(&ctx, salt, saltlen); + sha256_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr)); + sha256_Final(&ctx, (uint8_t *)pctx->g); #if BYTE_ORDER == LITTLE_ENDIAN - for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) { - REVERSE32(pctx->g[k], pctx->g[k]); - } + for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) { + REVERSE32(pctx->g[k], pctx->g[k]); + } #endif - sha256_Transform(pctx->odig, pctx->g, pctx->g); - memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH); - pctx->first = 1; + sha256_Transform(pctx->odig, pctx->g, pctx->g); + memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH); + pctx->first = 1; } -void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations) -{ - for (uint32_t i = pctx->first; i < iterations; i++) { - sha256_Transform(pctx->idig, pctx->g, pctx->g); - sha256_Transform(pctx->odig, pctx->g, pctx->g); - for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH/sizeof(uint32_t); j++) { - pctx->f[j] ^= pctx->g[j]; - } - } - pctx->first = 0; +void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, + uint32_t iterations) { + for (uint32_t i = pctx->first; i < iterations; i++) { + sha256_Transform(pctx->idig, pctx->g, pctx->g); + sha256_Transform(pctx->odig, pctx->g, pctx->g); + for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH / sizeof(uint32_t); j++) { + pctx->f[j] ^= pctx->g[j]; + } + } + pctx->first = 0; } -void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) -{ +void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) { #if BYTE_ORDER == LITTLE_ENDIAN - for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH/sizeof(uint32_t); k++) { - REVERSE32(pctx->f[k], pctx->f[k]); - } + for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) { + REVERSE32(pctx->f[k], pctx->f[k]); + } #endif - memcpy(key, pctx->f, SHA256_DIGEST_LENGTH); - memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX)); + memcpy(key, pctx->f, SHA256_DIGEST_LENGTH); + memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX)); } -void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen) -{ - uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH; - uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH; - if (last_block_size) { - blocks_count++; - } else { - last_block_size = SHA256_DIGEST_LENGTH; - } - for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { - PBKDF2_HMAC_SHA256_CTX pctx; - pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr); - pbkdf2_hmac_sha256_Update(&pctx, iterations); - uint8_t digest[SHA256_DIGEST_LENGTH]; - pbkdf2_hmac_sha256_Final(&pctx, digest); - uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH; - if (blocknr < blocks_count) { - memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH); - } else { - memcpy(key + key_offset, digest, last_block_size); - } - } +void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, + int saltlen, uint32_t iterations, uint8_t *key, + int keylen) { + uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH; + uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH; + if (last_block_size) { + blocks_count++; + } else { + last_block_size = SHA256_DIGEST_LENGTH; + } + for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { + PBKDF2_HMAC_SHA256_CTX pctx; + pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr); + pbkdf2_hmac_sha256_Update(&pctx, iterations); + uint8_t digest[SHA256_DIGEST_LENGTH]; + pbkdf2_hmac_sha256_Final(&pctx, digest); + uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH; + if (blocknr < blocks_count) { + memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH); + } else { + memcpy(key + key_offset, digest, last_block_size); + } + } } -void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr) -{ - SHA512_CTX ctx; +void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, + int passlen, const uint8_t *salt, int saltlen, + uint32_t blocknr) { + SHA512_CTX ctx; #if BYTE_ORDER == LITTLE_ENDIAN - REVERSE32(blocknr, blocknr); + REVERSE32(blocknr, blocknr); #endif - hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig); - memzero(pctx->g, sizeof(pctx->g)); - pctx->g[8] = 0x8000000000000000; - pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8; + hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig); + memzero(pctx->g, sizeof(pctx->g)); + pctx->g[8] = 0x8000000000000000; + pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8; - memcpy (ctx.state, pctx->idig, sizeof(pctx->idig)); - ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8; - ctx.bitcount[1] = 0; - sha512_Update(&ctx, salt, saltlen); - sha512_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr)); - sha512_Final(&ctx, (uint8_t*)pctx->g); + memcpy(ctx.state, pctx->idig, sizeof(pctx->idig)); + ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8; + ctx.bitcount[1] = 0; + sha512_Update(&ctx, salt, saltlen); + sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr)); + sha512_Final(&ctx, (uint8_t *)pctx->g); #if BYTE_ORDER == LITTLE_ENDIAN - for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) { - REVERSE64(pctx->g[k], pctx->g[k]); - } + for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) { + REVERSE64(pctx->g[k], pctx->g[k]); + } #endif - sha512_Transform(pctx->odig, pctx->g, pctx->g); - memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH); - pctx->first = 1; + sha512_Transform(pctx->odig, pctx->g, pctx->g); + memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH); + pctx->first = 1; } -void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations) -{ - for (uint32_t i = pctx->first; i < iterations; i++) { - sha512_Transform(pctx->idig, pctx->g, pctx->g); - sha512_Transform(pctx->odig, pctx->g, pctx->g); - for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) { - pctx->f[j] ^= pctx->g[j]; - } - } - pctx->first = 0; +void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, + uint32_t iterations) { + for (uint32_t i = pctx->first; i < iterations; i++) { + sha512_Transform(pctx->idig, pctx->g, pctx->g); + sha512_Transform(pctx->odig, pctx->g, pctx->g); + for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) { + pctx->f[j] ^= pctx->g[j]; + } + } + pctx->first = 0; } -void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) -{ +void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) { #if BYTE_ORDER == LITTLE_ENDIAN - for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH/sizeof(uint64_t); k++) { - REVERSE64(pctx->f[k], pctx->f[k]); - } + for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) { + REVERSE64(pctx->f[k], pctx->f[k]); + } #endif - memcpy(key, pctx->f, SHA512_DIGEST_LENGTH); - memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX)); + memcpy(key, pctx->f, SHA512_DIGEST_LENGTH); + memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX)); } -void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen) -{ - uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH; - uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH; - if (last_block_size) { - blocks_count++; - } else { - last_block_size = SHA512_DIGEST_LENGTH; - } - for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { - PBKDF2_HMAC_SHA512_CTX pctx; - pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr); - pbkdf2_hmac_sha512_Update(&pctx, iterations); - uint8_t digest[SHA512_DIGEST_LENGTH]; - pbkdf2_hmac_sha512_Final(&pctx, digest); - uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH; - if (blocknr < blocks_count) { - memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH); - } else { - memcpy(key + key_offset, digest, last_block_size); - } - } +void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, + int saltlen, uint32_t iterations, uint8_t *key, + int keylen) { + uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH; + uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH; + if (last_block_size) { + blocks_count++; + } else { + last_block_size = SHA512_DIGEST_LENGTH; + } + for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { + PBKDF2_HMAC_SHA512_CTX pctx; + pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr); + pbkdf2_hmac_sha512_Update(&pctx, iterations); + uint8_t digest[SHA512_DIGEST_LENGTH]; + pbkdf2_hmac_sha512_Final(&pctx, digest); + uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH; + if (blocknr < blocks_count) { + memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH); + } else { + memcpy(key + key_offset, digest, last_block_size); + } + } } diff --git a/pbkdf2.h b/pbkdf2.h index e3f440c8f..c2e3f04a6 100644 --- a/pbkdf2.h +++ b/pbkdf2.h @@ -28,29 +28,39 @@ #include "sha2.h" typedef struct _PBKDF2_HMAC_SHA256_CTX { - uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; - uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; - uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; - uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; - char first; + uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; + uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; + uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; + uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; + char first; } PBKDF2_HMAC_SHA256_CTX; typedef struct _PBKDF2_HMAC_SHA512_CTX { - uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; - uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; - uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; - uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; - char first; + uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; + uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; + uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; + uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; + char first; } PBKDF2_HMAC_SHA512_CTX; -void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr); -void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations); +void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, + int passlen, const uint8_t *salt, int saltlen, + uint32_t blocknr); +void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, + uint32_t iterations); void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key); -void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen); +void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, + int saltlen, uint32_t iterations, uint8_t *key, + int keylen); -void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr); -void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations); +void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, + int passlen, const uint8_t *salt, int saltlen, + uint32_t blocknr); +void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, + uint32_t iterations); void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key); -void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen); +void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, + int saltlen, uint32_t iterations, uint8_t *key, + int keylen); #endif diff --git a/rand.c b/rand.c index 411c755a3..bed9002cc 100644 --- a/rand.c +++ b/rand.c @@ -25,28 +25,27 @@ #ifndef RAND_PLATFORM_INDEPENDENT -#pragma message("NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.") +#pragma message( \ + "NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.") // The following code is not supposed to be used in a production environment. // It's included only to make the library testable. -// The message above tries to prevent any accidental use outside of the test environment. +// The message above tries to prevent any accidental use outside of the test +// environment. // -// You are supposed to replace the random8() and random32() function with your own secure code. -// There is also a possibility to replace the random_buffer() function as it is defined as a weak symbol. +// You are supposed to replace the random8() and random32() function with your +// own secure code. There is also a possibility to replace the random_buffer() +// function as it is defined as a weak symbol. static uint32_t seed = 0; -void random_reseed(const uint32_t value) -{ - seed = value; -} +void random_reseed(const uint32_t value) { seed = value; } -uint32_t random32(void) -{ - // Linear congruential generator from Numerical Recipes - // https://en.wikipedia.org/wiki/Linear_congruential_generator - seed = 1664525 * seed + 1013904223; - return seed; +uint32_t random32(void) { + // Linear congruential generator from Numerical Recipes + // https://en.wikipedia.org/wiki/Linear_congruential_generator + seed = 1664525 * seed + 1013904223; + return seed; } #endif /* RAND_PLATFORM_INDEPENDENT */ @@ -55,30 +54,28 @@ uint32_t random32(void) // The following code is platform independent // -void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) -{ - uint32_t r = 0; - for (size_t i = 0; i < len; i++) { - if (i % 4 == 0) { - r = random32(); - } - buf[i] = (r >> ((i % 4) * 8)) & 0xFF; - } +void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) { + uint32_t r = 0; + for (size_t i = 0; i < len; i++) { + if (i % 4 == 0) { + r = random32(); + } + buf[i] = (r >> ((i % 4) * 8)) & 0xFF; + } } -uint32_t random_uniform(uint32_t n) -{ - uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n); - while ((x = random32()) >= max); - return x / (max / n); +uint32_t random_uniform(uint32_t n) { + uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n); + while ((x = random32()) >= max) + ; + return x / (max / n); } -void random_permute(char *str, size_t len) -{ - for (int i = len - 1; i >= 1; i--) { - int j = random_uniform(i + 1); - char t = str[j]; - str[j] = str[i]; - str[i] = t; - } +void random_permute(char *str, size_t len) { + for (int i = len - 1; i >= 1; i--) { + int j = random_uniform(i + 1); + char t = str[j]; + str[j] = str[i]; + str[i] = t; + } } diff --git a/rc4.c b/rc4.c index db9eb1ffa..fea73cab1 100644 --- a/rc4.c +++ b/rc4.c @@ -23,34 +23,34 @@ #include "rc4.h" static inline void rc4_swap(RC4_CTX *ctx, uint8_t i, uint8_t j) { - uint8_t temp = ctx->S[i]; - ctx->S[i] = ctx->S[j]; - ctx->S[j] = temp; + uint8_t temp = ctx->S[i]; + ctx->S[i] = ctx->S[j]; + ctx->S[j] = temp; } void rc4_init(RC4_CTX *ctx, const uint8_t *key, size_t length) { - ctx->i = 0; - ctx->j = 0; - - for (size_t i = 0; i < 256; i++) { - ctx->S[i] = i; - } - - uint8_t j = 0; - for (size_t i = 0; i < 256; i++) { - j += ctx->S[i] + key[i % length]; - rc4_swap(ctx, i, j); - } + ctx->i = 0; + ctx->j = 0; + + for (size_t i = 0; i < 256; i++) { + ctx->S[i] = i; + } + + uint8_t j = 0; + for (size_t i = 0; i < 256; i++) { + j += ctx->S[i] + key[i % length]; + rc4_swap(ctx, i, j); + } } void rc4_encrypt(RC4_CTX *ctx, uint8_t *buffer, size_t length) { - for (size_t idx = 0; idx < length; idx++) { - ctx->i++; - ctx->j += ctx->S[ctx->i]; + for (size_t idx = 0; idx < length; idx++) { + ctx->i++; + ctx->j += ctx->S[ctx->i]; - rc4_swap(ctx, ctx->i, ctx->j); + rc4_swap(ctx, ctx->i, ctx->j); - uint8_t K = ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256]; - buffer[idx] ^= K; - } + uint8_t K = ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256]; + buffer[idx] ^= K; + } } diff --git a/rc4.h b/rc4.h index 7b56e4a3d..8ba8a9b25 100644 --- a/rc4.h +++ b/rc4.h @@ -23,12 +23,12 @@ #ifndef __RC4_H__ #define __RC4_H__ -#include #include +#include typedef struct { - uint8_t S[256]; - uint8_t i, j; + uint8_t S[256]; + uint8_t i, j; } RC4_CTX; void rc4_init(RC4_CTX *ctx, const uint8_t *key, size_t length); diff --git a/rfc6979.c b/rfc6979.c index ec808a7cf..8f5f1c913 100644 --- a/rfc6979.c +++ b/rfc6979.c @@ -22,57 +22,56 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include #include "rfc6979.h" +#include #include "hmac.h" #include "memzero.h" -void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { - uint8_t bx[2*32]; - uint8_t buf[32 + 1 + 2*32]; +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, + rfc6979_state *state) { + uint8_t bx[2 * 32]; + uint8_t buf[32 + 1 + 2 * 32]; - memcpy(bx, priv_key, 32); - memcpy(bx+32, hash, 32); + memcpy(bx, priv_key, 32); + memcpy(bx + 32, hash, 32); - memset(state->v, 1, sizeof(state->v)); - memset(state->k, 0, sizeof(state->k)); + memset(state->v, 1, sizeof(state->v)); + memset(state->k, 0, sizeof(state->k)); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x00; - memcpy(buf + sizeof(state->v) + 1, bx, 64); - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x01; - memcpy(buf + sizeof(state->v) + 1, bx, 64); - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x01; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memzero(bx, sizeof(bx)); - memzero(buf, sizeof(buf)); + memzero(bx, sizeof(bx)); + memzero(buf, sizeof(buf)); } // generate next number from deterministic random number generator -void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) -{ - uint8_t buf[32 + 1]; +void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) { + uint8_t buf[32 + 1]; - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(buf, state->v, sizeof(state->v)); - buf[sizeof(state->v)] = 0x00; - hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); - hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - memcpy(rnd, buf, 32); - memzero(buf, sizeof(buf)); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(rnd, buf, 32); + memzero(buf, sizeof(buf)); } // generate K in a deterministic way, according to RFC6979 // http://tools.ietf.org/html/rfc6979 -void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) -{ - uint8_t buf[32]; - generate_rfc6979(buf, state); - bn_read_be(buf, k); - memzero(buf, sizeof(buf)); +void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) { + uint8_t buf[32]; + generate_rfc6979(buf, state); + bn_read_be(buf, k); + memzero(buf, sizeof(buf)); } diff --git a/rfc6979.h b/rfc6979.h index e541d6ade..30ef0f17a 100644 --- a/rfc6979.h +++ b/rfc6979.h @@ -30,10 +30,11 @@ // rfc6979 pseudo random number generator state typedef struct { - uint8_t v[32], k[32]; + uint8_t v[32], k[32]; } rfc6979_state; -void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng); +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, + rfc6979_state *rng); void generate_rfc6979(uint8_t rnd[32], rfc6979_state *rng); void generate_k_rfc6979(bignum256 *k, rfc6979_state *rng); diff --git a/ripemd160.h b/ripemd160.h index a62de5cfc..8256b08a1 100644 --- a/ripemd160.h +++ b/ripemd160.h @@ -3,18 +3,20 @@ #include -#define RIPEMD160_BLOCK_LENGTH 64 -#define RIPEMD160_DIGEST_LENGTH 20 +#define RIPEMD160_BLOCK_LENGTH 64 +#define RIPEMD160_DIGEST_LENGTH 20 typedef struct _RIPEMD160_CTX { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */ } RIPEMD160_CTX; void ripemd160_Init(RIPEMD160_CTX *ctx); void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen); -void ripemd160_Final(RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH]); -void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]); +void ripemd160_Final(RIPEMD160_CTX *ctx, + uint8_t output[RIPEMD160_DIGEST_LENGTH]); +void ripemd160(const uint8_t *msg, uint32_t msg_len, + uint8_t hash[RIPEMD160_DIGEST_LENGTH]); #endif diff --git a/script.c b/script.c index 3ddb3a658..45691044e 100644 --- a/script.c +++ b/script.c @@ -20,45 +20,47 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "script.h" #include #include "base58.h" -#include "script.h" -int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, int addrsize) -{ - uint8_t raw[35]; +int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, + int addrsize) { + uint8_t raw[35]; - // P2PKH - if (scriptlen == 25 && script[0] == 0x76 && script[1] == 0xA9 && script[2] == 0x14 && script[23] == 0x88 && script[24] == 0xAC) { - raw[0] = 0x00; - memcpy(raw + 1, script + 3, 20); - return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize); - } + // P2PKH + if (scriptlen == 25 && script[0] == 0x76 && script[1] == 0xA9 && + script[2] == 0x14 && script[23] == 0x88 && script[24] == 0xAC) { + raw[0] = 0x00; + memcpy(raw + 1, script + 3, 20); + return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize); + } - // P2SH - if (scriptlen == 23 && script[0] == 0xA9 && script[1] == 0x14 && script[22] == 0x87) { - raw[0] = 0x05; - memcpy(raw + 1, script + 2, 20); - return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize); - } + // P2SH + if (scriptlen == 23 && script[0] == 0xA9 && script[1] == 0x14 && + script[22] == 0x87) { + raw[0] = 0x05; + memcpy(raw + 1, script + 2, 20); + return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize); + } - // P2WPKH - if (scriptlen == 22 && script[0] == 0x00 && script[1] == 0x14) { - raw[0] = 0x06; - raw[1] = 0x00; - raw[2] = 0x00; - memcpy(raw + 3, script + 2, 20); - return base58_encode_check(raw, 3 + 20, HASHER_SHA2D, addr, addrsize); - } + // P2WPKH + if (scriptlen == 22 && script[0] == 0x00 && script[1] == 0x14) { + raw[0] = 0x06; + raw[1] = 0x00; + raw[2] = 0x00; + memcpy(raw + 3, script + 2, 20); + return base58_encode_check(raw, 3 + 20, HASHER_SHA2D, addr, addrsize); + } - // P2WSH - if (scriptlen == 34 && script[0] == 0x00 && script[1] == 0x20) { - raw[0] = 0x0A; - raw[1] = 0x00; - raw[2] = 0x00; - memcpy(raw + 3, script + 2, 32); - return base58_encode_check(raw, 3 + 32, HASHER_SHA2D, addr, addrsize); - } + // P2WSH + if (scriptlen == 34 && script[0] == 0x00 && script[1] == 0x20) { + raw[0] = 0x0A; + raw[1] = 0x00; + raw[2] = 0x00; + memcpy(raw + 3, script + 2, 32); + return base58_encode_check(raw, 3 + 32, HASHER_SHA2D, addr, addrsize); + } - return 0; + return 0; } diff --git a/script.h b/script.h index 9544bf7ca..c9cc003b8 100644 --- a/script.h +++ b/script.h @@ -25,6 +25,7 @@ #include -int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, int addrsize); +int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, + int addrsize); #endif diff --git a/secp256k1.c b/secp256k1.c index f7ec89042..097c7cc17 100644 --- a/secp256k1.c +++ b/secp256k1.c @@ -24,69 +24,70 @@ #include "secp256k1.h" const ecdsa_curve secp256k1 = { - /* .prime */ { - /*.val =*/ {0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} - }, + /* .prime */ {/*.val =*/{0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, + 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, + 0xffff}}, - /* G */ { - /*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}}, - /*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}} - }, + /* G */ + {/*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, + 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}}, + /*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, + 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, + 0x483a}}}, - /* order */ { - /*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} - }, + /* order */ + {/*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, + 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}}, - /* order_half */ { - /*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff} - }, + /* order_half */ + {/*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, + 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff}}, - /* a */ 0, + /* a */ 0, - /* b */ { - /*.val =*/{7} - } + /* b */ {/*.val =*/{7}} #if USE_PRECOMPUTED_CP - , - /* cp */ { + , + /* cp */ + { #include "secp256k1.table" - } + } #endif }; const curve_info secp256k1_info = { - .bip32_name = "Bitcoin seed", - .params = &secp256k1, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; const curve_info secp256k1_decred_info = { - .bip32_name = "Bitcoin seed", - .params = &secp256k1, - .hasher_base58 = HASHER_BLAKED, - .hasher_sign = HASHER_BLAKE, - .hasher_pubkey = HASHER_BLAKE_RIPEMD, - .hasher_script = HASHER_BLAKE, + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_BLAKED, + .hasher_sign = HASHER_BLAKE, + .hasher_pubkey = HASHER_BLAKE_RIPEMD, + .hasher_script = HASHER_BLAKE, }; const curve_info secp256k1_groestl_info = { - .bip32_name = "Bitcoin seed", - .params = &secp256k1, - .hasher_base58 = HASHER_GROESTLD_TRUNC, - .hasher_sign = HASHER_SHA2, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_GROESTLD_TRUNC, + .hasher_sign = HASHER_SHA2, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; const curve_info secp256k1_smart_info = { - .bip32_name = "Bitcoin seed", - .params = &secp256k1, - .hasher_base58 = HASHER_SHA3K, - .hasher_sign = HASHER_SHA2, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_SHA3K, + .hasher_sign = HASHER_SHA2, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, }; diff --git a/secp256k1.h b/secp256k1.h index 234ca97a9..3b45e48fe 100644 --- a/secp256k1.h +++ b/secp256k1.h @@ -26,8 +26,8 @@ #include -#include "ecdsa.h" #include "bip32.h" +#include "ecdsa.h" extern const ecdsa_curve secp256k1; extern const curve_info secp256k1_info; diff --git a/segwit_addr.h b/segwit_addr.h index dbec91b02..c842fca2a 100644 --- a/segwit_addr.h +++ b/segwit_addr.h @@ -35,13 +35,8 @@ * prog_len: Number of data bytes in prog. * Returns 1 if successful. */ -int segwit_addr_encode( - char *output, - const char *hrp, - int ver, - const uint8_t *prog, - size_t prog_len -); +int segwit_addr_encode(char *output, const char *hrp, int ver, + const uint8_t *prog, size_t prog_len); /** Decode a SegWit address * @@ -49,20 +44,13 @@ int segwit_addr_encode( * program version (between 0 and 16 inclusive). * prog: Pointer to a buffer of size 40 that will be updated to * contain the witness program bytes. - * prog_len: Pointer to a size_t that will be updated to contain the length - * of bytes in prog. - * hrp: Pointer to the null-terminated human readable part that is - * expected (chain/network specific). - * addr: Pointer to the null-terminated address. - * Returns 1 if successful. + * prog_len: Pointer to a size_t that will be updated to contain the + * length of bytes in prog. hrp: Pointer to the null-terminated human + * readable part that is expected (chain/network specific). addr: Pointer to + * the null-terminated address. Returns 1 if successful. */ -int segwit_addr_decode( - int* ver, - uint8_t* prog, - size_t* prog_len, - const char* hrp, - const char* addr -); +int segwit_addr_decode(int *ver, uint8_t *prog, size_t *prog_len, + const char *hrp, const char *addr); /** Encode a Bech32 string * @@ -73,12 +61,8 @@ int segwit_addr_decode( * data_len: Length of the data array. * Returns 1 if successful. */ -int bech32_encode( - char *output, - const char *hrp, - const uint8_t *data, - size_t data_len -); +int bech32_encode(char *output, const char *hrp, const uint8_t *data, + size_t data_len); /** Decode a Bech32 string * @@ -91,11 +75,7 @@ int bech32_encode( * In: input: Pointer to a null-terminated Bech32 string. * Returns 1 if succesful. */ -int bech32_decode( - char *hrp, - uint8_t *data, - size_t *data_len, - const char *input -); +int bech32_decode(char *hrp, uint8_t *data, size_t *data_len, + const char *input); #endif diff --git a/shell.nix b/shell.nix index 0cfc3dd05..d4493bbb5 100644 --- a/shell.nix +++ b/shell.nix @@ -2,5 +2,5 @@ with import {}; stdenv.mkDerivation { name = "trezor-crypto-dev"; - buildInputs = [ gnumake gcc pkgconfig openssl check valgrind ]; + buildInputs = [ gnumake gcc pkgconfig openssl check valgrind clang-tools ]; } diff --git a/tests/test_check.c b/tests/test_check.c index e72c16a2a..5fe219c4e 100644 --- a/tests/test_check.c +++ b/tests/test_check.c @@ -21,9 +21,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include -#include #include #include #include @@ -32,40 +32,39 @@ #include "check_mem.h" #if VALGRIND -#include #include +#include #endif #include "options.h" +#include "address.h" #include "aes/aes.h" -#include "bignum.h" #include "base32.h" #include "base58.h" +#include "bignum.h" #include "bip32.h" #include "bip39.h" -#include "ecdsa.h" -#include "pbkdf2.h" -#include "rand.h" -#include "sha2.h" -#include "sha3.h" #include "blake256.h" #include "blake2b.h" #include "blake2s.h" #include "curves.h" -#include "secp256k1.h" -#include "nist256p1.h" -#include "ed25519-donna/ed25519.h" +#include "ecdsa.h" #include "ed25519-donna/ed25519-donna.h" #include "ed25519-donna/ed25519-keccak.h" -#include "script.h" -#include "rfc6979.h" -#include "address.h" -#include "rc4.h" -#include "nem.h" -#include "monero/monero.h" +#include "ed25519-donna/ed25519.h" #include "memzero.h" - +#include "monero/monero.h" +#include "nem.h" +#include "nist256p1.h" +#include "pbkdf2.h" +#include "rand.h" +#include "rc4.h" +#include "rfc6979.h" +#include "script.h" +#include "secp256k1.h" +#include "sha2.h" +#include "sha3.h" #if VALGRIND /* @@ -74,2121 +73,3672 @@ */ /* Call after secret data is written, before first use */ -#define MARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) -/* Call before secret data is freed or to mark non-secret data (public keys or signatures) */ -#define UNMARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_DEFINED (addr, len) +#define MARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) +/* Call before secret data is freed or to mark non-secret data (public keys or + * signatures) */ +#define UNMARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len) #else -#define MARK_SECRET_DATA(addr, len) +#define MARK_SECRET_DATA(addr, len) #define UNMARK_SECRET_DATA(addr, len) #endif #define FROMHEX_MAXLEN 512 -#define VERSION_PUBLIC 0x0488b21e +#define VERSION_PUBLIC 0x0488b21e #define VERSION_PRIVATE 0x0488ade4 -#define DECRED_VERSION_PUBLIC 0x02fda926 +#define DECRED_VERSION_PUBLIC 0x02fda926 #define DECRED_VERSION_PRIVATE 0x02fda4e8 -const uint8_t *fromhex(const char *str) -{ - static uint8_t buf[FROMHEX_MAXLEN]; - size_t len = strlen(str) / 2; - if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN; - for (size_t i = 0; i < len; i++) { - uint8_t c = 0; - if (str[i * 2] >= '0' && str[i*2] <= '9') c += (str[i * 2] - '0') << 4; - if ((str[i * 2] & ~0x20) >= 'A' && (str[i*2] & ~0x20) <= 'F') c += (10 + (str[i * 2] & ~0x20) - 'A') << 4; - if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') c += (str[i * 2 + 1] - '0'); - if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') c += (10 + (str[i * 2 + 1] & ~0x20) - 'A'); - buf[i] = c; - } - return buf; +const uint8_t *fromhex(const char *str) { + static uint8_t buf[FROMHEX_MAXLEN]; + size_t len = strlen(str) / 2; + if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN; + for (size_t i = 0; i < len; i++) { + uint8_t c = 0; + if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4; + if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F') + c += (10 + (str[i * 2] & ~0x20) - 'A') << 4; + if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') + c += (str[i * 2 + 1] - '0'); + if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') + c += (10 + (str[i * 2 + 1] & ~0x20) - 'A'); + buf[i] = c; + } + return buf; } void nem_private_key(const char *reversed_hex, ed25519_secret_key private_key) { - const uint8_t *reversed_key = fromhex(reversed_hex); - for (size_t j = 0; j < sizeof(ed25519_secret_key); j++) { - private_key[j] = reversed_key[sizeof(ed25519_secret_key) - j - 1]; - } + const uint8_t *reversed_key = fromhex(reversed_hex); + for (size_t j = 0; j < sizeof(ed25519_secret_key); j++) { + private_key[j] = reversed_key[sizeof(ed25519_secret_key) - j - 1]; + } } -START_TEST(test_bignum_read_be) -{ - bignum256 a; - uint8_t input[32]; +START_TEST(test_bignum_read_be) { + bignum256 a; + uint8_t input[32]; - memcpy(input, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32); + memcpy( + input, + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + 32); - bn_read_be(input, &a); + bn_read_be(input, &a); - bignum256 b = { { 0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e } }; + bignum256 b = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, + 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}}; - for (int i = 0; i < 9; i++) { - ck_assert_int_eq(a.val[i], b.val[i]); - } + for (int i = 0; i < 9; i++) { + ck_assert_int_eq(a.val[i], b.val[i]); + } } END_TEST -START_TEST(test_bignum_write_be) -{ - bignum256 a = { { 0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e } }; - uint8_t tmp[32]; +START_TEST(test_bignum_write_be) { + bignum256 a = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, + 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}}; + uint8_t tmp[32]; - bn_write_be(&a, tmp); + bn_write_be(&a, tmp); - ck_assert_mem_eq(tmp, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32); + ck_assert_mem_eq( + tmp, + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + 32); } END_TEST -START_TEST(test_bignum_is_equal) -{ - bignum256 a = { { 0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e } }; - bignum256 b = { { 0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e } }; - bignum256 c = { { 0, } }; - - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - ck_assert_int_eq(bn_is_equal(&c, &c), 1); - ck_assert_int_eq(bn_is_equal(&a, &c), 0); +START_TEST(test_bignum_is_equal) { + bignum256 a = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, + 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}}; + bignum256 b = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3, + 0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}}; + bignum256 c = {{ + 0, + }}; + + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + ck_assert_int_eq(bn_is_equal(&c, &c), 1); + ck_assert_int_eq(bn_is_equal(&a, &c), 0); } END_TEST -START_TEST(test_bignum_zero) -{ - bignum256 a; - bignum256 b; +START_TEST(test_bignum_zero) { + bignum256 a; + bignum256 b; - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - bn_zero(&b); + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + bn_zero(&b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_is_zero) -{ - bignum256 a; - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - ck_assert_int_eq(bn_is_zero(&a), 1); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000001"), &a); - ck_assert_int_eq(bn_is_zero(&a), 0); - - bn_read_be(fromhex("1000000000000000000000000000000000000000000000000000000000000000"), &a); - ck_assert_int_eq(bn_is_zero(&a), 0); - - bn_read_be(fromhex("f000000000000000000000000000000000000000000000000000000000000000"), &a); - ck_assert_int_eq(bn_is_zero(&a), 0); +START_TEST(test_bignum_is_zero) { + bignum256 a; + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + ck_assert_int_eq(bn_is_zero(&a), 1); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + ck_assert_int_eq(bn_is_zero(&a), 0); + + bn_read_be( + fromhex( + "1000000000000000000000000000000000000000000000000000000000000000"), + &a); + ck_assert_int_eq(bn_is_zero(&a), 0); + + bn_read_be( + fromhex( + "f000000000000000000000000000000000000000000000000000000000000000"), + &a); + ck_assert_int_eq(bn_is_zero(&a), 0); } END_TEST -START_TEST(test_bignum_one) -{ - bignum256 a; - bignum256 b; +START_TEST(test_bignum_one) { + bignum256 a; + bignum256 b; - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000001"), &a); - bn_one(&b); + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + bn_one(&b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_read_le) -{ - bignum256 a; - bignum256 b; +START_TEST(test_bignum_read_le) { + bignum256 a; + bignum256 b; - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a); - bn_read_le(fromhex("d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), &b); + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + &a); + bn_read_le( + fromhex( + "d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), + &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_write_le) -{ - bignum256 a; - bignum256 b; - uint8_t tmp[32]; - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a); - bn_write_le(&a, tmp); - - bn_read_le(tmp, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - bn_read_be(fromhex("d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), &a); - bn_read_be(tmp, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); +START_TEST(test_bignum_write_le) { + bignum256 a; + bignum256 b; + uint8_t tmp[32]; + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + &a); + bn_write_le(&a, tmp); + + bn_read_le(tmp, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + bn_read_be( + fromhex( + "d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), + &a); + bn_read_be(tmp, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_read_uint32) -{ - bignum256 a; - bignum256 b; - - // lowest 30 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000000000003fffffff"), &a); - bn_read_uint32(0x3fffffff, &b); - - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - // bit 31 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000040000000"), &a); - bn_read_uint32(0x40000000, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); +START_TEST(test_bignum_read_uint32) { + bignum256 a; + bignum256 b; + + // lowest 30 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000003fffffff"), + &a); + bn_read_uint32(0x3fffffff, &b); + + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + // bit 31 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000040000000"), + &a); + bn_read_uint32(0x40000000, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_read_uint64) -{ - bignum256 a; - bignum256 b; - - // lowest 30 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000000000003fffffff"), &a); - bn_read_uint64(0x3fffffff, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - // bit 31 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000040000000"), &a); - bn_read_uint64(0x40000000, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - // bit 33 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000100000000"), &a); - bn_read_uint64(0x100000000LL, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - // bit 61 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000002000000000000000"), &a); - bn_read_uint64(0x2000000000000000LL, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); - - // all 64 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000ffffffffffffffff"), &a); - bn_read_uint64(0xffffffffffffffffLL, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); +START_TEST(test_bignum_read_uint64) { + bignum256 a; + bignum256 b; + + // lowest 30 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000003fffffff"), + &a); + bn_read_uint64(0x3fffffff, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + // bit 31 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000040000000"), + &a); + bn_read_uint64(0x40000000, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + // bit 33 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000100000000"), + &a); + bn_read_uint64(0x100000000LL, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + // bit 61 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000002000000000000000"), + &a); + bn_read_uint64(0x2000000000000000LL, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); + + // all 64 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000ffffffffffffffff"), + &a); + bn_read_uint64(0xffffffffffffffffLL, &b); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_write_uint32) -{ - bignum256 a; - - // lowest 30 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000000000003fffffff"), &a); - ck_assert_int_eq(bn_write_uint32(&a), 0x3fffffff); - - // bit 31 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000040000000"), &a); - ck_assert_int_eq(bn_write_uint32(&a), 0x40000000); +START_TEST(test_bignum_write_uint32) { + bignum256 a; + + // lowest 30 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000003fffffff"), + &a); + ck_assert_int_eq(bn_write_uint32(&a), 0x3fffffff); + + // bit 31 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000040000000"), + &a); + ck_assert_int_eq(bn_write_uint32(&a), 0x40000000); } END_TEST -START_TEST(test_bignum_write_uint64) -{ - bignum256 a; - - // lowest 30 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000000000003fffffff"), &a); - ck_assert_int_eq(bn_write_uint64(&a), 0x3fffffff); - - // bit 31 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000040000000"), &a); - ck_assert_int_eq(bn_write_uint64(&a), 0x40000000); - - // bit 33 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000100000000"), &a); - ck_assert_int_eq(bn_write_uint64(&a), 0x100000000LL); - - // bit 61 set - bn_read_be(fromhex("0000000000000000000000000000000000000000000000002000000000000000"), &a); - ck_assert_int_eq(bn_write_uint64(&a), 0x2000000000000000LL); - - // all 64 bits set - bn_read_be(fromhex("000000000000000000000000000000000000000000000000ffffffffffffffff"), &a); - ck_assert_int_eq(bn_write_uint64(&a), 0xffffffffffffffffLL); +START_TEST(test_bignum_write_uint64) { + bignum256 a; + + // lowest 30 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000003fffffff"), + &a); + ck_assert_int_eq(bn_write_uint64(&a), 0x3fffffff); + + // bit 31 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000040000000"), + &a); + ck_assert_int_eq(bn_write_uint64(&a), 0x40000000); + + // bit 33 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000100000000"), + &a); + ck_assert_int_eq(bn_write_uint64(&a), 0x100000000LL); + + // bit 61 set + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000002000000000000000"), + &a); + ck_assert_int_eq(bn_write_uint64(&a), 0x2000000000000000LL); + + // all 64 bits set + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000ffffffffffffffff"), + &a); + ck_assert_int_eq(bn_write_uint64(&a), 0xffffffffffffffffLL); } END_TEST -START_TEST(test_bignum_copy) -{ - bignum256 a; - bignum256 b; +START_TEST(test_bignum_copy) { + bignum256 a; + bignum256 b; - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a); - bn_copy(&a, &b); + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + &a); + bn_copy(&a, &b); - ck_assert_int_eq(bn_is_equal(&a, &b), 1); + ck_assert_int_eq(bn_is_equal(&a, &b), 1); } END_TEST -START_TEST(test_bignum_is_even) -{ - bignum256 a; - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a); - ck_assert_int_eq(bn_is_even(&a), 0); - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"), &a); - ck_assert_int_eq(bn_is_even(&a), 1); - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"), &a); - ck_assert_int_eq(bn_is_even(&a), 1); +START_TEST(test_bignum_is_even) { + bignum256 a; + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + &a); + ck_assert_int_eq(bn_is_even(&a), 0); + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"), + &a); + ck_assert_int_eq(bn_is_even(&a), 1); + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"), + &a); + ck_assert_int_eq(bn_is_even(&a), 1); } END_TEST -START_TEST(test_bignum_is_odd) -{ - bignum256 a; - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a); - ck_assert_int_eq(bn_is_odd(&a), 1); - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"), &a); - ck_assert_int_eq(bn_is_odd(&a), 0); - - bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"), &a); - ck_assert_int_eq(bn_is_odd(&a), 0); +START_TEST(test_bignum_is_odd) { + bignum256 a; + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), + &a); + ck_assert_int_eq(bn_is_odd(&a), 1); + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"), + &a); + ck_assert_int_eq(bn_is_odd(&a), 0); + + bn_read_be( + fromhex( + "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"), + &a); + ck_assert_int_eq(bn_is_odd(&a), 0); } END_TEST -START_TEST(test_bignum_is_less) -{ - bignum256 a; - bignum256 b; +START_TEST(test_bignum_is_less) { + bignum256 a; + bignum256 b; - bn_read_uint32(0x1234, &a); - bn_read_uint32(0x8765, &b); + bn_read_uint32(0x1234, &a); + bn_read_uint32(0x8765, &b); - ck_assert_int_eq(bn_is_less(&a, &b), 1); - ck_assert_int_eq(bn_is_less(&b, &a), 0); + ck_assert_int_eq(bn_is_less(&a, &b), 1); + ck_assert_int_eq(bn_is_less(&b, &a), 0); - bn_zero(&a); - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &b); + bn_zero(&a); + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &b); - ck_assert_int_eq(bn_is_less(&a, &b), 1); - ck_assert_int_eq(bn_is_less(&b, &a), 0); + ck_assert_int_eq(bn_is_less(&a, &b), 1); + ck_assert_int_eq(bn_is_less(&b, &a), 0); } END_TEST -START_TEST(test_bignum_bitcount) -{ - bignum256 a, b; - - bn_zero(&a); - ck_assert_int_eq(bn_bitcount(&a), 0); - - bn_one(&a); - ck_assert_int_eq(bn_bitcount(&a), 1); - - // test for 10000 and 11111 when i=5 - for (int i = 2; i <= 256; i++) { - bn_one(&a); - bn_one(&b); - for (int j = 2; j <= i; j++) { - bn_lshift(&a); - bn_lshift(&b); - bn_addi(&b, 1); - } - ck_assert_int_eq(bn_bitcount(&a), i); - ck_assert_int_eq(bn_bitcount(&b), i); - } - - bn_read_uint32(0x3fffffff, &a); - ck_assert_int_eq(bn_bitcount(&a), 30); - - bn_read_uint32(0xffffffff, &a); - ck_assert_int_eq(bn_bitcount(&a), 32); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - ck_assert_int_eq(bn_bitcount(&a), 256); +START_TEST(test_bignum_bitcount) { + bignum256 a, b; + + bn_zero(&a); + ck_assert_int_eq(bn_bitcount(&a), 0); + + bn_one(&a); + ck_assert_int_eq(bn_bitcount(&a), 1); + + // test for 10000 and 11111 when i=5 + for (int i = 2; i <= 256; i++) { + bn_one(&a); + bn_one(&b); + for (int j = 2; j <= i; j++) { + bn_lshift(&a); + bn_lshift(&b); + bn_addi(&b, 1); + } + ck_assert_int_eq(bn_bitcount(&a), i); + ck_assert_int_eq(bn_bitcount(&b), i); + } + + bn_read_uint32(0x3fffffff, &a); + ck_assert_int_eq(bn_bitcount(&a), 30); + + bn_read_uint32(0xffffffff, &a); + ck_assert_int_eq(bn_bitcount(&a), 32); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + ck_assert_int_eq(bn_bitcount(&a), 256); } END_TEST -START_TEST(test_bignum_digitcount) -{ - bignum256 a; +START_TEST(test_bignum_digitcount) { + bignum256 a; - bn_zero(&a); - ck_assert_int_eq(bn_digitcount(&a), 1); + bn_zero(&a); + ck_assert_int_eq(bn_digitcount(&a), 1); - // test for (10^i) and (10^i) - 1 - uint64_t m = 1; - for (int i = 0; i <= 19; i++, m *= 10) { - bn_read_uint64(m, &a); - ck_assert_int_eq(bn_digitcount(&a), i + 1); + // test for (10^i) and (10^i) - 1 + uint64_t m = 1; + for (int i = 0; i <= 19; i++, m *= 10) { + bn_read_uint64(m, &a); + ck_assert_int_eq(bn_digitcount(&a), i + 1); - uint64_t n = m - 1; - bn_read_uint64(n, &a); - ck_assert_int_eq(bn_digitcount(&a), n == 0 ? 1 : i); - } + uint64_t n = m - 1; + bn_read_uint64(n, &a); + ck_assert_int_eq(bn_digitcount(&a), n == 0 ? 1 : i); + } - bn_read_uint32(0x3fffffff, &a); - ck_assert_int_eq(bn_digitcount(&a), 10); + bn_read_uint32(0x3fffffff, &a); + ck_assert_int_eq(bn_digitcount(&a), 10); - bn_read_uint32(0xffffffff, &a); - ck_assert_int_eq(bn_digitcount(&a), 10); + bn_read_uint32(0xffffffff, &a); + ck_assert_int_eq(bn_digitcount(&a), 10); - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - ck_assert_int_eq(bn_digitcount(&a), 78); + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + ck_assert_int_eq(bn_digitcount(&a), 78); } END_TEST START_TEST(test_bignum_format_uint64) { - char buf[128], str[128]; - int r; - // test for (10^i) and (10^i) - 1 - uint64_t m = 1; - for (int i = 0; i <= 19; i++, m *= 10) { - sprintf(str, "%" PRIu64, m); - r = bn_format_uint64(m, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, strlen(str)); - ck_assert_str_eq(buf, str); - - uint64_t n = m - 1; - sprintf(str, "%" PRIu64, n); - r = bn_format_uint64(n, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, strlen(str)); - ck_assert_str_eq(buf, str); - } + char buf[128], str[128]; + int r; + // test for (10^i) and (10^i) - 1 + uint64_t m = 1; + for (int i = 0; i <= 19; i++, m *= 10) { + sprintf(str, "%" PRIu64, m); + r = bn_format_uint64(m, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, strlen(str)); + ck_assert_str_eq(buf, str); + + uint64_t n = m - 1; + sprintf(str, "%" PRIu64, n); + r = bn_format_uint64(n, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, strlen(str)); + ck_assert_str_eq(buf, str); + } } END_TEST START_TEST(test_bignum_format) { - bignum256 a; - char buf[128]; - int r; - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 20, 0, true, buf, sizeof(buf)); - ck_assert_int_eq(r, 22); - ck_assert_str_eq(buf, "0.00000000000000000000"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, 5, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, -5, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "", "", 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, "SFFX", 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1 + 4); - ck_assert_str_eq(buf, "0SFFX"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "PRFX", NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 4 + 1); - ck_assert_str_eq(buf, "PRFX0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "PRFX", "SFFX", 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 4 + 1 + 4); - ck_assert_str_eq(buf, "PRFX0SFFX"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "0.0"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000001"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "1"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000001"), &a); - r = bn_format(&a, NULL, NULL, 6, 6, true, buf, sizeof(buf)); - ck_assert_int_eq(r, 8); - ck_assert_str_eq(buf, "1.000000"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000002"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "2"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000005"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "5"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000009"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 1); - ck_assert_str_eq(buf, "9"); - - bn_read_be(fromhex("000000000000000000000000000000000000000000000000000000000000000a"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 2); - ck_assert_str_eq(buf, "10"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000014"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 2); - ck_assert_str_eq(buf, "20"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000032"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 2); - ck_assert_str_eq(buf, "50"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000063"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 2); - ck_assert_str_eq(buf, "99"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000000064"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "100"); - - bn_read_be(fromhex("00000000000000000000000000000000000000000000000000000000000000c8"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "200"); - - bn_read_be(fromhex("00000000000000000000000000000000000000000000000000000000000001f4"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "500"); - - bn_read_be(fromhex("00000000000000000000000000000000000000000000000000000000000003e7"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "999"); - - bn_read_be(fromhex("00000000000000000000000000000000000000000000000000000000000003e8"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 4); - ck_assert_str_eq(buf, "1000"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000000000000989680"), &a); - r = bn_format(&a, NULL, NULL, 7, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 3); - ck_assert_str_eq(buf, "1.0"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 78); - ck_assert_str_eq(buf, "115792089237316195423570985008687907853269984665640564039457584007913129639935"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 1, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 79); - ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945758400791312963993.5"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 2, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 79); - ck_assert_str_eq(buf, "1157920892373161954235709850086879078532699846656405640394575840079131296399.35"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 79); - ck_assert_str_eq(buf, "1157920892373161954235709850086879078532699846656405640394575840079131.29639935"); - - bn_read_be(fromhex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3bbb00"), &a); - r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 72); - ck_assert_str_eq(buf, "1157920892373161954235709850086879078532699846656405640394575840079131.0"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 79); - ck_assert_str_eq(buf, "115792089237316195423570985008687907853269984665640564039457.584007913129639935"); - - bn_read_be(fromhex("fffffffffffffffffffffffffffffffffffffffffffffffff7e52fe5afe40000"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 62); - ck_assert_str_eq(buf, "115792089237316195423570985008687907853269984665640564039457.0"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 78, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 80); - ck_assert_str_eq(buf, "0.115792089237316195423570985008687907853269984665640564039457584007913129639935"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 0, 10, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 88); - ck_assert_str_eq(buf, "1157920892373161954235709850086879078532699846656405640394575840079131296399350000000000"); - - bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, "quite a long prefix", "even longer suffix", 60, 0, false, buf, sizeof(buf)); - ck_assert_int_eq(r, 116); - ck_assert_str_eq(buf, "quite a long prefix115792089237316195.423570985008687907853269984665640564039457584007913129639935even longer suffix"); - - bn_read_be(fromhex("0000000000000000000000000000000000000000000000000123456789abcdef"), &a); - memset(buf, 'a', sizeof(buf)); - r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 31); - ck_assert_str_eq(buf, "prefix8198552.9216486895suffix"); - ck_assert_int_eq(r, 30); - - memset(buf, 'a', sizeof(buf)); - r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 30); - ck_assert_int_eq(r, 0); - ck_assert_str_eq(buf, "prefix198552.9216486895suffix"); + bignum256 a; + char buf[128]; + int r; + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, NULL, 20, 0, true, buf, sizeof(buf)); + ck_assert_int_eq(r, 22); + ck_assert_str_eq(buf, "0.00000000000000000000"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, NULL, 0, 5, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, NULL, 0, -5, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, "", "", 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, "SFFX", 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1 + 4); + ck_assert_str_eq(buf, "0SFFX"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, "PRFX", NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 4 + 1); + ck_assert_str_eq(buf, "PRFX0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, "PRFX", "SFFX", 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 4 + 1 + 4); + ck_assert_str_eq(buf, "PRFX0SFFX"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + &a); + r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "0.0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "1"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + r = bn_format(&a, NULL, NULL, 6, 6, true, buf, sizeof(buf)); + ck_assert_int_eq(r, 8); + ck_assert_str_eq(buf, "1.000000"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000002"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "2"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000005"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "5"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000009"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 1); + ck_assert_str_eq(buf, "9"); + + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000000000000a"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 2); + ck_assert_str_eq(buf, "10"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000014"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 2); + ck_assert_str_eq(buf, "20"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000032"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 2); + ck_assert_str_eq(buf, "50"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000063"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 2); + ck_assert_str_eq(buf, "99"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000064"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "100"); + + bn_read_be( + fromhex( + "00000000000000000000000000000000000000000000000000000000000000c8"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "200"); + + bn_read_be( + fromhex( + "00000000000000000000000000000000000000000000000000000000000001f4"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "500"); + + bn_read_be( + fromhex( + "00000000000000000000000000000000000000000000000000000000000003e7"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "999"); + + bn_read_be( + fromhex( + "00000000000000000000000000000000000000000000000000000000000003e8"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 4); + ck_assert_str_eq(buf, "1000"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000989680"), + &a); + r = bn_format(&a, NULL, NULL, 7, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 3); + ck_assert_str_eq(buf, "1.0"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 78); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "7584007913129639935"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 1, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 79); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "758400791312963993.5"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 2, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 79); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "75840079131296399.35"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 79); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "75840079131.29639935"); + + bn_read_be( + fromhex( + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3bbb00"), + &a); + r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 72); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "75840079131.0"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 79); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "7.584007913129639935"); + + bn_read_be( + fromhex( + "fffffffffffffffffffffffffffffffffffffffffffffffff7e52fe5afe40000"), + &a); + r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 62); + ck_assert_str_eq( + buf, "115792089237316195423570985008687907853269984665640564039457.0"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 78, 0, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 80); + ck_assert_str_eq(buf, + "0." + "11579208923731619542357098500868790785326998466564056403945" + "7584007913129639935"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 0, 10, false, buf, sizeof(buf)); + ck_assert_int_eq(r, 88); + ck_assert_str_eq(buf, + "11579208923731619542357098500868790785326998466564056403945" + "75840079131296399350000000000"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, "quite a long prefix", "even longer suffix", 60, 0, false, + buf, sizeof(buf)); + ck_assert_int_eq(r, 116); + ck_assert_str_eq(buf, + "quite a long " + "prefix115792089237316195." + "42357098500868790785326998466564056403945758400791312963993" + "5even longer suffix"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000123456789abcdef"), + &a); + memset(buf, 'a', sizeof(buf)); + r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 31); + ck_assert_str_eq(buf, "prefix8198552.9216486895suffix"); + ck_assert_int_eq(r, 30); + + memset(buf, 'a', sizeof(buf)); + r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 30); + ck_assert_int_eq(r, 0); + ck_assert_str_eq(buf, "prefix198552.9216486895suffix"); } END_TEST // https://tools.ietf.org/html/rfc4648#section-10 -START_TEST(test_base32_rfc4648) -{ - static const struct { - const char *decoded; - const char *encoded; - const char *encoded_lowercase; - } tests[] = { - { "", "", ""}, - { "f", "MY", "my" }, - { "fo", "MZXQ", "mzxq" }, - { "foo", "MZXW6", "mzxw6" }, - { "foob", "MZXW6YQ", "mzxw6yq" }, - { "fooba", "MZXW6YTB", "mzxw6ytb" }, - { "foobar", "MZXW6YTBOI", "mzxw6ytboi" }, - }; - - char buffer[64]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - const char *in = tests[i].decoded; - const char *out = tests[i].encoded; - const char *out_lowercase = tests[i].encoded_lowercase; - - size_t inlen = strlen(in); - size_t outlen = strlen(out); - - ck_assert_int_eq(outlen, base32_encoded_length(inlen)); - ck_assert_int_eq(inlen, base32_decoded_length(outlen)); - - ck_assert(base32_encode((uint8_t *) in, inlen, buffer, sizeof(buffer), BASE32_ALPHABET_RFC4648) != NULL); - ck_assert_str_eq(buffer, out); - - char *ret = (char *) base32_decode(out, outlen, (uint8_t *) buffer, sizeof(buffer), BASE32_ALPHABET_RFC4648); - ck_assert(ret != NULL); - *ret = '\0'; - ck_assert_str_eq(buffer, in); - - ret = (char *) base32_decode(out_lowercase, outlen, (uint8_t *) buffer, sizeof(buffer), BASE32_ALPHABET_RFC4648); - ck_assert(ret != NULL); - *ret = '\0'; - ck_assert_str_eq(buffer, in); - } +START_TEST(test_base32_rfc4648) { + static const struct { + const char *decoded; + const char *encoded; + const char *encoded_lowercase; + } tests[] = { + {"", "", ""}, + {"f", "MY", "my"}, + {"fo", "MZXQ", "mzxq"}, + {"foo", "MZXW6", "mzxw6"}, + {"foob", "MZXW6YQ", "mzxw6yq"}, + {"fooba", "MZXW6YTB", "mzxw6ytb"}, + {"foobar", "MZXW6YTBOI", "mzxw6ytboi"}, + }; + + char buffer[64]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + const char *in = tests[i].decoded; + const char *out = tests[i].encoded; + const char *out_lowercase = tests[i].encoded_lowercase; + + size_t inlen = strlen(in); + size_t outlen = strlen(out); + + ck_assert_int_eq(outlen, base32_encoded_length(inlen)); + ck_assert_int_eq(inlen, base32_decoded_length(outlen)); + + ck_assert(base32_encode((uint8_t *)in, inlen, buffer, sizeof(buffer), + BASE32_ALPHABET_RFC4648) != NULL); + ck_assert_str_eq(buffer, out); + + char *ret = (char *)base32_decode(out, outlen, (uint8_t *)buffer, + sizeof(buffer), BASE32_ALPHABET_RFC4648); + ck_assert(ret != NULL); + *ret = '\0'; + ck_assert_str_eq(buffer, in); + + ret = (char *)base32_decode(out_lowercase, outlen, (uint8_t *)buffer, + sizeof(buffer), BASE32_ALPHABET_RFC4648); + ck_assert(ret != NULL); + *ret = '\0'; + ck_assert_str_eq(buffer, in); + } } END_TEST -// from https://github.com/bitcoin/bitcoin/blob/master/src/test/data/base58_keys_valid.json -START_TEST(test_base58) -{ - static const char *base58_vector[] = { - "0065a16059864a2fdbc7c99a4723a8395bc6f188eb", "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", - "0574f209f6ea907e2ea48f74fae05782ae8a665257", "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", - "6f53c0307d6851aa0ce7825ba883c6bd9ad242b486", "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", - "c46349a418fc4578d10a372b54b45c280cc8c4382f", "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", - "80eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", - "8055c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c401", "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", - "ef36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", - "efb9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f301", "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", - "006d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4", "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", - "05fcc5460dd6e2487c7d75b1963625da0e8f4c5975", "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", - "6ff1d470f9b02370fdec2e6b708b08ac431bf7a5f7", "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", - "c4c579342c2c4c9220205e2cdc285617040c924a0a", "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", - "80a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", - "807d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb401", "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", - "efd6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", - "efa81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d901", "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", - "007987ccaa53d02c8873487ef919677cd3db7a6912", "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", - "0563bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb", "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", - "6fef66444b5b17f14e8fae6e7e19b045a78c54fd79", "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", - "c4c3e55fceceaa4391ed2a9677f4a4d34eacd021a0", "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", - "80e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", - "808248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c01", "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", - "ef44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", - "efd1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c6901", "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", - "00adc1cc2081a27206fae25792f28bbc55b831549d", "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", - "05188f91a931947eddd7432d6e614387e32b244709", "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", - "6f1694f5bc1a7295b600f40018a618a6ea48eeb498", "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", - "c43b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3", "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", - "80091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", - "80ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af01", "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", - "efb4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", - "efe7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef01", "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", - "00c4c1b72491ede1eedaca00618407ee0b772cad0d", "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", - "05f6fe69bcb548a829cce4c57bf6fff8af3a5981f9", "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", - "6f261f83568a098a8638844bd7aeca039d5f2352c0", "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", - "c4e930e1834a4d234702773951d627cce82fbb5d2e", "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", - "80d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", - "80b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b301", "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", - "ef037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", - "ef6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de01", "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", - "005eadaf9bb7121f0f192561a5a62f5e5f54210292", "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", - "053f210e7277c899c3a155cc1c90f4106cbddeec6e", "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", - "6fc8a3c2a09a298592c3e180f02487cd91ba3400b5", "myoqcgYiehufrsnnkqdqbp69dddVDMopJu", - "c499b31df7c9068d1481b596578ddbb4d3bd90baeb", "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", - "80c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", - "8007f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd01", "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", - "efea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", - "ef0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c01", "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", - "001ed467017f043e91ed4c44b4e8dd674db211c4e6", "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", - "055ece0cadddc415b1980f001785947120acdb36fc", "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", - 0, 0, - }; - const char **raw = base58_vector; - const char **str = base58_vector + 1; - uint8_t rawn[34]; - char strn[53]; - int r; - while (*raw && *str) { - int len = strlen(*raw) / 2; - - memcpy(rawn, fromhex(*raw), len); - r = base58_encode_check(rawn, len, HASHER_SHA2D, strn, sizeof(strn)); - ck_assert_int_eq((size_t)r, strlen(*str) + 1); - ck_assert_str_eq(strn, *str); - - r = base58_decode_check(strn, HASHER_SHA2D, rawn, len); - ck_assert_int_eq(r, len); - ck_assert_mem_eq(rawn, fromhex(*raw), len); - - raw += 2; str += 2; - } +// from +// https://github.com/bitcoin/bitcoin/blob/master/src/test/data/base58_keys_valid.json +START_TEST(test_base58) { + static const char *base58_vector[] = { + "0065a16059864a2fdbc7c99a4723a8395bc6f188eb", + "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", + "0574f209f6ea907e2ea48f74fae05782ae8a665257", + "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", + "6f53c0307d6851aa0ce7825ba883c6bd9ad242b486", + "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", + "c46349a418fc4578d10a372b54b45c280cc8c4382f", + "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", + "80eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", + "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", + "8055c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c401", + "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", + "ef36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", + "efb9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f301", + "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", + "006d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4", + "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", + "05fcc5460dd6e2487c7d75b1963625da0e8f4c5975", + "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", + "6ff1d470f9b02370fdec2e6b708b08ac431bf7a5f7", + "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", + "c4c579342c2c4c9220205e2cdc285617040c924a0a", + "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", + "80a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", + "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", + "807d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb401", + "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", + "efd6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", + "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", + "efa81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d901", + "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", + "007987ccaa53d02c8873487ef919677cd3db7a6912", + "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", + "0563bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb", + "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", + "6fef66444b5b17f14e8fae6e7e19b045a78c54fd79", + "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", + "c4c3e55fceceaa4391ed2a9677f4a4d34eacd021a0", + "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", + "80e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", + "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", + "808248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c01", + "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", + "ef44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", + "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", + "efd1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c6901", + "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", + "00adc1cc2081a27206fae25792f28bbc55b831549d", + "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", + "05188f91a931947eddd7432d6e614387e32b244709", + "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", + "6f1694f5bc1a7295b600f40018a618a6ea48eeb498", + "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", + "c43b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3", + "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", + "80091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", + "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", + "80ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af01", + "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", + "efb4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", + "efe7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef01", + "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", + "00c4c1b72491ede1eedaca00618407ee0b772cad0d", + "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", + "05f6fe69bcb548a829cce4c57bf6fff8af3a5981f9", + "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", + "6f261f83568a098a8638844bd7aeca039d5f2352c0", + "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", + "c4e930e1834a4d234702773951d627cce82fbb5d2e", + "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", + "80d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", + "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", + "80b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b301", + "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", + "ef037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", + "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", + "ef6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de01", + "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", + "005eadaf9bb7121f0f192561a5a62f5e5f54210292", + "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", + "053f210e7277c899c3a155cc1c90f4106cbddeec6e", + "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", + "6fc8a3c2a09a298592c3e180f02487cd91ba3400b5", + "myoqcgYiehufrsnnkqdqbp69dddVDMopJu", + "c499b31df7c9068d1481b596578ddbb4d3bd90baeb", + "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", + "80c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", + "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", + "8007f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd01", + "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", + "efea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", + "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", + "ef0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c01", + "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", + "001ed467017f043e91ed4c44b4e8dd674db211c4e6", + "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", + "055ece0cadddc415b1980f001785947120acdb36fc", + "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", + 0, + 0, + }; + const char **raw = base58_vector; + const char **str = base58_vector + 1; + uint8_t rawn[34]; + char strn[53]; + int r; + while (*raw && *str) { + int len = strlen(*raw) / 2; + + memcpy(rawn, fromhex(*raw), len); + r = base58_encode_check(rawn, len, HASHER_SHA2D, strn, sizeof(strn)); + ck_assert_int_eq((size_t)r, strlen(*str) + 1); + ck_assert_str_eq(strn, *str); + + r = base58_decode_check(strn, HASHER_SHA2D, rawn, len); + ck_assert_int_eq(r, len); + ck_assert_mem_eq(rawn, fromhex(*raw), len); + + raw += 2; + str += 2; + } } END_TEST #if USE_GRAPHENE // Graphene Base85CheckEncoding -START_TEST(test_base58gph) -{ - static const char *base58_vector[] = { - "02e649f63f8e8121345fd7f47d0d185a3ccaa843115cd2e9392dcd9b82263bc680", "6dumtt9swxCqwdPZBGXh9YmHoEjFFnNfwHaTqRbQTghGAY2gRz", - "021c7359cd885c0e319924d97e3980206ad64387aff54908241125b3a88b55ca16", "5725vivYpuFWbeyTifZ5KevnHyqXCi5hwHbNU9cYz1FHbFXCxX", - "02f561e0b57a552df3fa1df2d87a906b7a9fc33a83d5d15fa68a644ecb0806b49a", "6kZKHSuxqAwdCYsMvwTcipoTsNE2jmEUNBQufGYywpniBKXWZK", - "03e7595c3e6b58f907bee951dc29796f3757307e700ecf3d09307a0cc4a564eba3", "8b82mpnH8YX1E9RHnU2a2YgLTZ8ooevEGP9N15c1yFqhoBvJur", - 0, 0, - }; - const char **raw = base58_vector; - const char **str = base58_vector + 1; - uint8_t rawn[34]; - char strn[53]; - int r; - while (*raw && *str) { - int len = strlen(*raw) / 2; - - memcpy(rawn, fromhex(*raw), len); - r = base58gph_encode_check(rawn, len, strn, sizeof(strn)); - ck_assert_int_eq((size_t)r, strlen(*str) + 1); - ck_assert_str_eq(strn, *str); - - r = base58gph_decode_check(strn, rawn, len); - ck_assert_int_eq(r, len); - ck_assert_mem_eq(rawn, fromhex(*raw), len); - - raw += 2; str += 2; - } +START_TEST(test_base58gph) { + static const char *base58_vector[] = { + "02e649f63f8e8121345fd7f47d0d185a3ccaa843115cd2e9392dcd9b82263bc680", + "6dumtt9swxCqwdPZBGXh9YmHoEjFFnNfwHaTqRbQTghGAY2gRz", + "021c7359cd885c0e319924d97e3980206ad64387aff54908241125b3a88b55ca16", + "5725vivYpuFWbeyTifZ5KevnHyqXCi5hwHbNU9cYz1FHbFXCxX", + "02f561e0b57a552df3fa1df2d87a906b7a9fc33a83d5d15fa68a644ecb0806b49a", + "6kZKHSuxqAwdCYsMvwTcipoTsNE2jmEUNBQufGYywpniBKXWZK", + "03e7595c3e6b58f907bee951dc29796f3757307e700ecf3d09307a0cc4a564eba3", + "8b82mpnH8YX1E9RHnU2a2YgLTZ8ooevEGP9N15c1yFqhoBvJur", + 0, + 0, + }; + const char **raw = base58_vector; + const char **str = base58_vector + 1; + uint8_t rawn[34]; + char strn[53]; + int r; + while (*raw && *str) { + int len = strlen(*raw) / 2; + + memcpy(rawn, fromhex(*raw), len); + r = base58gph_encode_check(rawn, len, strn, sizeof(strn)); + ck_assert_int_eq((size_t)r, strlen(*str) + 1); + ck_assert_str_eq(strn, *str); + + r = base58gph_decode_check(strn, rawn, len); + ck_assert_int_eq(r, len); + ck_assert_mem_eq(rawn, fromhex(*raw), len); + + raw += 2; + str += 2; + } } END_TEST #endif -START_TEST(test_bignum_divmod) -{ - uint32_t r; - int i; - - bignum256 a = { { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} }; - uint32_t ar[] = { 15, 14, 55, 29, 44, 24, 53, 49, 18, 55, 2, 28, 5, 4, 12, 43, 18, 37, 28, 14, 30, 46, 12, 11, 17, 10, 10, 13, 24, 45, 4, 33, 44, 42, 2, 46, 34, 43, 45, 28, 21, 18, 13, 17 }; - - i = 0; - while (!bn_is_zero(&a) && i < 44) { - bn_divmod58(&a, &r); - ck_assert_int_eq(r, ar[i]); - i++; - } - ck_assert_int_eq(i, 44); - - bignum256 b = { { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} }; - uint32_t br[] = { 935, 639, 129, 913, 7, 584, 457, 39, 564, 640, 665, 984, 269, 853, 907, 687, 8, 985, 570, 423, 195, 316, 237, 89, 792, 115 }; - - i = 0; - while (!bn_is_zero(&b) && i < 26) { - bn_divmod1000(&b, &r); - ck_assert_int_eq(r, br[i]); - i++; - } - ck_assert_int_eq(i, 26); - +START_TEST(test_bignum_divmod) { + uint32_t r; + int i; + + bignum256 a = {{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, + 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}}; + uint32_t ar[] = {15, 14, 55, 29, 44, 24, 53, 49, 18, 55, 2, 28, 5, 4, 12, + 43, 18, 37, 28, 14, 30, 46, 12, 11, 17, 10, 10, 13, 24, 45, + 4, 33, 44, 42, 2, 46, 34, 43, 45, 28, 21, 18, 13, 17}; + + i = 0; + while (!bn_is_zero(&a) && i < 44) { + bn_divmod58(&a, &r); + ck_assert_int_eq(r, ar[i]); + i++; + } + ck_assert_int_eq(i, 44); + + bignum256 b = {{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, + 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}}; + uint32_t br[] = {935, 639, 129, 913, 7, 584, 457, 39, 564, + 640, 665, 984, 269, 853, 907, 687, 8, 985, + 570, 423, 195, 316, 237, 89, 792, 115}; + + i = 0; + while (!bn_is_zero(&b) && i < 26) { + bn_divmod1000(&b, &r); + ck_assert_int_eq(r, br[i]); + i++; + } + ck_assert_int_eq(i, 26); } END_TEST -// test vector 1 from https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-1 -START_TEST(test_bip32_vector_1) -{ - HDNode node, node2, node3; - uint32_t fingerprint; - char str[112]; - int r; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, SECP256K1_NAME, &node); - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"), 32); - ck_assert_mem_eq(node.private_key, fromhex("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 0); - ck_assert_int_eq(fingerprint, 0x3442193e); - ck_assert_mem_eq(node.chain_code, fromhex("47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"), 32); - ck_assert_mem_eq(node.private_key, fromhex("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1); - ck_assert_int_eq(fingerprint, 0x5c1bd648); - ck_assert_mem_eq(node.chain_code, fromhex("2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"), 32); - ck_assert_mem_eq(node.private_key, fromhex("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 2); - ck_assert_int_eq(fingerprint, 0xbef5a2f9); - ck_assert_mem_eq(node.chain_code, fromhex("04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"), 32); - ck_assert_mem_eq(node.private_key, fromhex("cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'/2] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 2); - ck_assert_int_eq(fingerprint, 0xee7ab90c); - ck_assert_mem_eq(node.chain_code, fromhex("cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'/2/1000000000] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1000000000); - ck_assert_int_eq(fingerprint, 0xd880d7d8); - ck_assert_mem_eq(node.chain_code, fromhex("c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"), 32); - ck_assert_mem_eq(node.private_key, fromhex("471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); +// test vector 1 from +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-1 +START_TEST(test_bip32_vector_1) { + HDNode node, node2, node3; + uint32_t fingerprint; + char str[112]; + int r; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + SECP256K1_NAME, &node); + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqji" + "ChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2" + "gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 0); + ck_assert_int_eq(fingerprint, 0x3442193e); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4" + "cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP" + "6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1); + ck_assert_int_eq(fingerprint, 0x5c1bd648); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSx" + "qu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFH" + "KkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 2); + ck_assert_int_eq(fingerprint, 0xbef5a2f9); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptW" + "mT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgq" + "FJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'/2] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 2); + ck_assert_int_eq(fingerprint, 0xee7ab90c); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Ty" + "h8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJ" + "AyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'/2/1000000000] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1000000000); + ck_assert_int_eq(fingerprint, 0xd880d7d8); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8" + "kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNT" + "EcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); } END_TEST -// test vector 2 from https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-2 -START_TEST(test_bip32_vector_2) -{ - HDNode node, node2, node3; - uint32_t fingerprint; - char str[112]; - int r; - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, SECP256K1_NAME, &node); - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"), 32); - ck_assert_mem_eq(node.private_key, fromhex("4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0xbd16bee5); - ck_assert_mem_eq(node.chain_code, fromhex("f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483647); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x5a61ff8e); - ck_assert_mem_eq(node.chain_code, fromhex("be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"), 32); - ck_assert_mem_eq(node.private_key, fromhex("877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 1); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0xd8ab4937); - ck_assert_mem_eq(node.chain_code, fromhex("f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"), 32); - ck_assert_mem_eq(node.private_key, fromhex("704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1/2147483646'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483646); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x78412e3a); - ck_assert_mem_eq(node.chain_code, fromhex("637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"), 32); - ck_assert_mem_eq(node.private_key, fromhex("f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1/2147483646'/2] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 2); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x31a507b8); - ck_assert_mem_eq(node.chain_code, fromhex("9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"), 32); - ck_assert_mem_eq(node.private_key, fromhex("bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"), 33); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, SECP256K1_NAME, &node); - - // test public derivation - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_public_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0xbd16bee5); - ck_assert_mem_eq(node.chain_code, fromhex("f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), 33); +// test vector 2 from +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-2 +START_TEST(test_bip32_vector_2) { + HDNode node, node2, node3; + uint32_t fingerprint; + char str[112]; + int r; + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, SECP256K1_NAME, &node); + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGds" + "o3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSC" + "Gu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0xbd16bee5); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT" + "3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGm" + "XUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483647); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x5a61ff8e); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYE" + "eEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ" + "85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 1); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0xd8ab4937); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd" + "25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5Ew" + "VvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1/2147483646'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483646); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x78412e3a); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz" + "7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJ" + "bZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1/2147483646'/2] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 2); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x31a507b8); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"), + 33); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw" + "7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLF" + "bdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, SECP256K1_NAME, &node); + + // test public derivation + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_public_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0xbd16bee5); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), + 33); } END_TEST -// test vector 3 from https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-3 -START_TEST(test_bip32_vector_3) -{ - HDNode node, node2, node3; - uint32_t fingerprint; - char str[112]; - int r; - - // init m - hdnode_from_seed(fromhex("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"), 64, SECP256K1_NAME, &node); - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - hdnode_fill_public_key(&node); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 0); - ck_assert_int_eq(r, 1); - hdnode_fill_public_key(&node); - hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); - r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); +// test vector 3 from +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-3 +START_TEST(test_bip32_vector_3) { + HDNode node, node2, node3; + uint32_t fingerprint; + char str[112]; + int r; + + // init m + hdnode_from_seed( + fromhex( + "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45" + "d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"), + 64, SECP256K1_NAME, &node); + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + hdnode_fill_public_key(&node); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7" + "KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhR" + "oP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 0); + ck_assert_int_eq(r, 1); + hdnode_fill_public_key(&node); + hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu" + "2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str)); + ck_assert_str_eq(str, + "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrAD" + "WgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); + r = hdnode_deserialize(str, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); } END_TEST -START_TEST(test_bip32_compare) -{ - HDNode node1, node2, node3; - int i, r; - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node1); - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node2); - hdnode_fill_public_key(&node2); - for (i = 0; i < 100; i++) { - memcpy(&node3, &node1, sizeof(HDNode)); - hdnode_fill_public_key(&node3); - r = hdnode_private_ckd(&node1, i); ck_assert_int_eq(r, 1); - r = hdnode_public_ckd(&node2, i); ck_assert_int_eq(r, 1); - r = hdnode_public_ckd(&node3, i); ck_assert_int_eq(r, 1); - ck_assert_int_eq(node1.depth, node2.depth); - ck_assert_int_eq(node1.depth, node3.depth); - ck_assert_int_eq(node1.child_num, node2.child_num); - ck_assert_int_eq(node1.child_num, node3.child_num); - ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32); - ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32); - ck_assert_mem_eq(node2.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - ck_assert_mem_eq(node3.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - hdnode_fill_public_key(&node1); - ck_assert_mem_eq(node1.public_key, node2.public_key, 33); - ck_assert_mem_eq(node1.public_key, node3.public_key, 33); - } +START_TEST(test_bip32_compare) { + HDNode node1, node2, node3; + int i, r; + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node1); + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node2); + hdnode_fill_public_key(&node2); + for (i = 0; i < 100; i++) { + memcpy(&node3, &node1, sizeof(HDNode)); + hdnode_fill_public_key(&node3); + r = hdnode_private_ckd(&node1, i); + ck_assert_int_eq(r, 1); + r = hdnode_public_ckd(&node2, i); + ck_assert_int_eq(r, 1); + r = hdnode_public_ckd(&node3, i); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(node1.depth, node2.depth); + ck_assert_int_eq(node1.depth, node3.depth); + ck_assert_int_eq(node1.child_num, node2.child_num); + ck_assert_int_eq(node1.child_num, node3.child_num); + ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32); + ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32); + ck_assert_mem_eq( + node2.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + ck_assert_mem_eq( + node3.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + hdnode_fill_public_key(&node1); + ck_assert_mem_eq(node1.public_key, node2.public_key, 33); + ck_assert_mem_eq(node1.public_key, node3.public_key, 33); + } } END_TEST -START_TEST(test_bip32_optimized) -{ - HDNode root; - hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root); - hdnode_fill_public_key(&root); - - curve_point pub; - ecdsa_read_pubkey(&secp256k1, root.public_key, &pub); - - HDNode node; - char addr1[MAX_ADDR_SIZE], addr2[MAX_ADDR_SIZE]; - - for (int i = 0; i < 40; i++) { - // unoptimized - memcpy(&node, &root, sizeof(HDNode)); - hdnode_public_ckd(&node, i); - hdnode_fill_public_key(&node); - ecdsa_get_address(node.public_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, addr1, sizeof(addr1)); - // optimized - hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, addr2, sizeof(addr2), 0); - // check - ck_assert_str_eq(addr1, addr2); - } +START_TEST(test_bip32_optimized) { + HDNode root; + hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root); + hdnode_fill_public_key(&root); + + curve_point pub; + ecdsa_read_pubkey(&secp256k1, root.public_key, &pub); + + HDNode node; + char addr1[MAX_ADDR_SIZE], addr2[MAX_ADDR_SIZE]; + + for (int i = 0; i < 40; i++) { + // unoptimized + memcpy(&node, &root, sizeof(HDNode)); + hdnode_public_ckd(&node, i); + hdnode_fill_public_key(&node); + ecdsa_get_address(node.public_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + addr1, sizeof(addr1)); + // optimized + hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0, + HASHER_SHA2_RIPEMD, HASHER_SHA2D, addr2, + sizeof(addr2), 0); + // check + ck_assert_str_eq(addr1, addr2); + } } END_TEST -START_TEST(test_bip32_cache_1) -{ - HDNode node1, node2; - int i, r; - - // test 1 .. 8 - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node1); - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node2); - - uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004, 0x80000005, 0x80000006, 0x80000007, 0x80000008}; - - for (i = 0; i < 8; i++) { - r = hdnode_private_ckd(&node1, ii[i]); ck_assert_int_eq(r, 1); - } - r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); ck_assert_int_eq(r, 1); - ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); - - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node1); - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node2); - - // test 1 .. 7, 20 - ii[7] = 20; - for (i = 0; i < 8; i++) { - r = hdnode_private_ckd(&node1, ii[i]); ck_assert_int_eq(r, 1); - } - r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); ck_assert_int_eq(r, 1); - ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); - - // test different root node - hdnode_from_seed(fromhex("000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node1); - hdnode_from_seed(fromhex("000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &node2); - - for (i = 0; i < 8; i++) { - r = hdnode_private_ckd(&node1, ii[i]); ck_assert_int_eq(r, 1); - } - r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); ck_assert_int_eq(r, 1); - ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); +START_TEST(test_bip32_cache_1) { + HDNode node1, node2; + int i, r; + + // test 1 .. 8 + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node1); + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node2); + + uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004, + 0x80000005, 0x80000006, 0x80000007, 0x80000008}; + + for (i = 0; i < 8; i++) { + r = hdnode_private_ckd(&node1, ii[i]); + ck_assert_int_eq(r, 1); + } + r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); + + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node1); + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node2); + + // test 1 .. 7, 20 + ii[7] = 20; + for (i = 0; i < 8; i++) { + r = hdnode_private_ckd(&node1, ii[i]); + ck_assert_int_eq(r, 1); + } + r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); + + // test different root node + hdnode_from_seed( + fromhex( + "000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node1); + hdnode_from_seed( + fromhex( + "000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &node2); + + for (i = 0; i < 8; i++) { + r = hdnode_private_ckd(&node1, ii[i]); + ck_assert_int_eq(r, 1); + } + r = hdnode_private_ckd_cached(&node2, ii, 8, NULL); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq(&node1, &node2, sizeof(HDNode)); } END_TEST -START_TEST(test_bip32_cache_2) -{ - HDNode nodea[9], nodeb[9]; - int i, j, r; - - for (j = 0; j < 9; j++) { - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &(nodea[j])); - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, SECP256K1_NAME, &(nodeb[j])); - } - - uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004, 0x80000005, 0x80000006, 0x80000007, 0x80000008}; - for (j = 0; j < 9; j++) { - // non cached - for (i = 1; i <= j; i++) { - r = hdnode_private_ckd(&(nodea[j]), ii[i - 1]); ck_assert_int_eq(r, 1); - } - // cached - r = hdnode_private_ckd_cached(&(nodeb[j]), ii, j, NULL); ck_assert_int_eq(r, 1); - } - - ck_assert_mem_eq(&(nodea[0]), &(nodeb[0]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[1]), &(nodeb[1]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[2]), &(nodeb[2]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[3]), &(nodeb[3]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[4]), &(nodeb[4]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[5]), &(nodeb[5]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[6]), &(nodeb[6]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[7]), &(nodeb[7]), sizeof(HDNode)); - ck_assert_mem_eq(&(nodea[8]), &(nodeb[8]), sizeof(HDNode)); +START_TEST(test_bip32_cache_2) { + HDNode nodea[9], nodeb[9]; + int i, j, r; + + for (j = 0; j < 9; j++) { + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d627" + "88f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &(nodea[j])); + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d627" + "88f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, SECP256K1_NAME, &(nodeb[j])); + } + + uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004, + 0x80000005, 0x80000006, 0x80000007, 0x80000008}; + for (j = 0; j < 9; j++) { + // non cached + for (i = 1; i <= j; i++) { + r = hdnode_private_ckd(&(nodea[j]), ii[i - 1]); + ck_assert_int_eq(r, 1); + } + // cached + r = hdnode_private_ckd_cached(&(nodeb[j]), ii, j, NULL); + ck_assert_int_eq(r, 1); + } + + ck_assert_mem_eq(&(nodea[0]), &(nodeb[0]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[1]), &(nodeb[1]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[2]), &(nodeb[2]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[3]), &(nodeb[3]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[4]), &(nodeb[4]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[5]), &(nodeb[5]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[6]), &(nodeb[6]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[7]), &(nodeb[7]), sizeof(HDNode)); + ck_assert_mem_eq(&(nodea[8]), &(nodeb[8]), sizeof(HDNode)); } END_TEST -START_TEST(test_bip32_nist_seed) -{ - HDNode node; - - // init m - hdnode_from_seed(fromhex("a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446"), 32, NIST256P1_NAME, &node); - - // [Chain m] - ck_assert_mem_eq(node.private_key, fromhex("3b8c18469a4634517d6d0b65448f8e6c62091b45540a1743c5846be55d47d88f"), 32); - ck_assert_mem_eq(node.chain_code, fromhex("7762f9729fed06121fd13f326884c82f59aa95c57ac492ce8c9654e60efd130c"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0383619fadcde31063d8c5cb00dbfe1713f3e6fa169d8541a798752a1c1ca0cb20"), 33); - - // init m - hdnode_from_seed(fromhex("aa305bc8df8d0951f0cb29ad4568d7707cbdf2c6ce7e8d481fec69c7ff5e9446"), 32, NIST256P1_NAME, &node); - - // [Chain m] - ck_assert_mem_eq(node.chain_code, fromhex("a81d21f36f987fa0be3b065301bfb6aa9deefbf3dfef6744c37b9a4abc3c68f1"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0e49dc46ce1d8c29d9b80a05e40f5d0cd68cbf02ae98572186f5343be18084bf"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03aaa4c89acd9a98935330773d3dae55122f3591bac4a40942681768de8df6ba63"), 33); +START_TEST(test_bip32_nist_seed) { + HDNode node; + + // init m + hdnode_from_seed( + fromhex( + "a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446"), + 32, NIST256P1_NAME, &node); + + // [Chain m] + ck_assert_mem_eq( + node.private_key, + fromhex( + "3b8c18469a4634517d6d0b65448f8e6c62091b45540a1743c5846be55d47d88f"), + 32); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "7762f9729fed06121fd13f326884c82f59aa95c57ac492ce8c9654e60efd130c"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0383619fadcde31063d8c5cb00dbfe1713f3e6fa169d8541a798752a1c1ca0cb20"), + 33); + + // init m + hdnode_from_seed( + fromhex( + "aa305bc8df8d0951f0cb29ad4568d7707cbdf2c6ce7e8d481fec69c7ff5e9446"), + 32, NIST256P1_NAME, &node); + + // [Chain m] + ck_assert_mem_eq( + node.chain_code, + fromhex( + "a81d21f36f987fa0be3b065301bfb6aa9deefbf3dfef6744c37b9a4abc3c68f1"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0e49dc46ce1d8c29d9b80a05e40f5d0cd68cbf02ae98572186f5343be18084bf"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03aaa4c89acd9a98935330773d3dae55122f3591bac4a40942681768de8df6ba63"), + 33); } END_TEST -START_TEST(test_bip32_nist_vector_1) -{ - HDNode node; - uint32_t fingerprint; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, NIST256P1_NAME, &node); - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea"), 32); - ck_assert_mem_eq(node.private_key, fromhex("612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8"), 33); - - // [Chain m/0'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 0); - ck_assert_int_eq(fingerprint, 0xbe6105b5); - ck_assert_mem_eq(node.chain_code, fromhex("3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11"), 32); - ck_assert_mem_eq(node.private_key, fromhex("6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c"), 33); - - // [Chain m/0'/1] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1); - ck_assert_int_eq(fingerprint, 0x9b02312f); - ck_assert_mem_eq(node.chain_code, fromhex("4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844"), 33); - - // [Chain m/0'/1/2'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 2); - ck_assert_int_eq(fingerprint, 0xb98005c1); - ck_assert_mem_eq(node.chain_code, fromhex("98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318"), 32); - ck_assert_mem_eq(node.private_key, fromhex("694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0"), 33); - - // [Chain m/0'/1/2'/2] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 2); - ck_assert_int_eq(fingerprint, 0x0e9f3274); - ck_assert_mem_eq(node.chain_code, fromhex("ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0"), 32); - ck_assert_mem_eq(node.private_key, fromhex("5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20"), 33); - - // [Chain m/0'/1/2'/2/1000000000] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1000000000); - ck_assert_int_eq(fingerprint, 0x8b2b5c4b); - ck_assert_mem_eq(node.chain_code, fromhex("b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059"), 32); - ck_assert_mem_eq(node.private_key, fromhex("21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4"), 33); +START_TEST(test_bip32_nist_vector_1) { + HDNode node; + uint32_t fingerprint; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + NIST256P1_NAME, &node); + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8"), + 33); + + // [Chain m/0'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 0); + ck_assert_int_eq(fingerprint, 0xbe6105b5); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c"), + 33); + + // [Chain m/0'/1] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1); + ck_assert_int_eq(fingerprint, 0x9b02312f); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844"), + 33); + + // [Chain m/0'/1/2'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 2); + ck_assert_int_eq(fingerprint, 0xb98005c1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0"), + 33); + + // [Chain m/0'/1/2'/2] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 2); + ck_assert_int_eq(fingerprint, 0x0e9f3274); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20"), + 33); + + // [Chain m/0'/1/2'/2/1000000000] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1000000000); + ck_assert_int_eq(fingerprint, 0x8b2b5c4b); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4"), + 33); } END_TEST -START_TEST(test_bip32_nist_vector_2) -{ - HDNode node; - uint32_t fingerprint; - int r; - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, NIST256P1_NAME, &node); - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d"), 32); - ck_assert_mem_eq(node.private_key, fromhex("eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa"), 33); - - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x607f628f); - ck_assert_mem_eq(node.chain_code, fromhex("84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"), 32); - ck_assert_mem_eq(node.private_key, fromhex("d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"), 33); - - // [Chain m/0/2147483647'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483647); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x946d2a54); - ck_assert_mem_eq(node.chain_code, fromhex("f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6"), 32); - ck_assert_mem_eq(node.private_key, fromhex("96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76"), 33); - - // [Chain m/0/2147483647'/1] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 1); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x218182d8); - ck_assert_mem_eq(node.chain_code, fromhex("7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b"), 32); - ck_assert_mem_eq(node.private_key, fromhex("974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64"), 33); - - // [Chain m/0/2147483647'/1/2147483646'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483646); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x931223e4); - ck_assert_mem_eq(node.chain_code, fromhex("5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a"), 32); - ck_assert_mem_eq(node.private_key, fromhex("da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933"), 33); - - // [Chain m/0/2147483647'/1/2147483646'/2] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 2); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x956c4629); - ck_assert_mem_eq(node.chain_code, fromhex("3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7"), 32); - ck_assert_mem_eq(node.private_key, fromhex("bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f"), 33); - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, NIST256P1_NAME, &node); - - // test public derivation - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_public_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x607f628f); - ck_assert_mem_eq(node.chain_code, fromhex("84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - ck_assert_mem_eq(node.public_key, fromhex("039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"), 33); +START_TEST(test_bip32_nist_vector_2) { + HDNode node; + uint32_t fingerprint; + int r; + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, NIST256P1_NAME, &node); + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa"), + 33); + + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x607f628f); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"), + 33); + + // [Chain m/0/2147483647'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483647); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x946d2a54); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76"), + 33); + + // [Chain m/0/2147483647'/1] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 1); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x218182d8); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64"), + 33); + + // [Chain m/0/2147483647'/1/2147483646'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483646); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x931223e4); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933"), + 33); + + // [Chain m/0/2147483647'/1/2147483646'/2] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 2); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x956c4629); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f"), + 33); + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, NIST256P1_NAME, &node); + + // test public derivation + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_public_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x607f628f); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + ck_assert_mem_eq( + node.public_key, + fromhex( + "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"), + 33); } END_TEST -START_TEST(test_bip32_nist_compare) -{ - HDNode node1, node2, node3; - int i, r; - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, NIST256P1_NAME, &node1); - hdnode_from_seed(fromhex("301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), 64, NIST256P1_NAME, &node2); - hdnode_fill_public_key(&node2); - for (i = 0; i < 100; i++) { - memcpy(&node3, &node1, sizeof(HDNode)); - hdnode_fill_public_key(&node3); - r = hdnode_private_ckd(&node1, i); ck_assert_int_eq(r, 1); - r = hdnode_public_ckd(&node2, i); ck_assert_int_eq(r, 1); - r = hdnode_public_ckd(&node3, i); ck_assert_int_eq(r, 1); - ck_assert_int_eq(node1.depth, node2.depth); - ck_assert_int_eq(node1.depth, node3.depth); - ck_assert_int_eq(node1.child_num, node2.child_num); - ck_assert_int_eq(node1.child_num, node3.child_num); - ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32); - ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32); - ck_assert_mem_eq(node2.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - ck_assert_mem_eq(node3.private_key, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - hdnode_fill_public_key(&node1); - ck_assert_mem_eq(node1.public_key, node2.public_key, 33); - ck_assert_mem_eq(node1.public_key, node3.public_key, 33); - } +START_TEST(test_bip32_nist_compare) { + HDNode node1, node2, node3; + int i, r; + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, NIST256P1_NAME, &node1); + hdnode_from_seed( + fromhex( + "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788" + "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"), + 64, NIST256P1_NAME, &node2); + hdnode_fill_public_key(&node2); + for (i = 0; i < 100; i++) { + memcpy(&node3, &node1, sizeof(HDNode)); + hdnode_fill_public_key(&node3); + r = hdnode_private_ckd(&node1, i); + ck_assert_int_eq(r, 1); + r = hdnode_public_ckd(&node2, i); + ck_assert_int_eq(r, 1); + r = hdnode_public_ckd(&node3, i); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(node1.depth, node2.depth); + ck_assert_int_eq(node1.depth, node3.depth); + ck_assert_int_eq(node1.child_num, node2.child_num); + ck_assert_int_eq(node1.child_num, node3.child_num); + ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32); + ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32); + ck_assert_mem_eq( + node2.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + ck_assert_mem_eq( + node3.private_key, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + hdnode_fill_public_key(&node1); + ck_assert_mem_eq(node1.public_key, node2.public_key, 33); + ck_assert_mem_eq(node1.public_key, node3.public_key, 33); + } } END_TEST -START_TEST(test_bip32_nist_repeat) -{ - HDNode node, node2; - uint32_t fingerprint; - int r; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, NIST256P1_NAME, &node); - - // [Chain m/28578'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 28578); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0xbe6105b5); - ck_assert_mem_eq(node.chain_code, fromhex("e94c8ebe30c2250a14713212f6449b20f3329105ea15b652ca5bdfc68f6c65c2"), 32); - ck_assert_mem_eq(node.private_key, fromhex("06f0db126f023755d0b8d86d4591718a5210dd8d024e3e14b6159d63f53aa669"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02519b5554a4872e8c9c1c847115363051ec43e93400e030ba3c36b52a3e70a5b7"), 33); - - memcpy(&node2, &node, sizeof(HDNode)); - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node2, 33941); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x3e2b7bc6); - ck_assert_mem_eq(node2.chain_code, fromhex("9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"), 32); - ck_assert_mem_eq(node2.private_key, fromhex("092154eed4af83e078ff9b84322015aefe5769e31270f62c3f66c33888335f3a"), 32); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(node2.public_key, fromhex("0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"), 33); - - memcpy(&node2, &node, sizeof(HDNode)); - memzero(&node2.private_key, 32); - r = hdnode_public_ckd(&node2, 33941); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x3e2b7bc6); - ck_assert_mem_eq(node2.chain_code, fromhex("9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"), 32); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(node2.public_key, fromhex("0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"), 33); +START_TEST(test_bip32_nist_repeat) { + HDNode node, node2; + uint32_t fingerprint; + int r; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + NIST256P1_NAME, &node); + + // [Chain m/28578'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 28578); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0xbe6105b5); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "e94c8ebe30c2250a14713212f6449b20f3329105ea15b652ca5bdfc68f6c65c2"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "06f0db126f023755d0b8d86d4591718a5210dd8d024e3e14b6159d63f53aa669"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02519b5554a4872e8c9c1c847115363051ec43e93400e030ba3c36b52a3e70a5b7"), + 33); + + memcpy(&node2, &node, sizeof(HDNode)); + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node2, 33941); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x3e2b7bc6); + ck_assert_mem_eq( + node2.chain_code, + fromhex( + "9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"), + 32); + ck_assert_mem_eq( + node2.private_key, + fromhex( + "092154eed4af83e078ff9b84322015aefe5769e31270f62c3f66c33888335f3a"), + 32); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq( + node2.public_key, + fromhex( + "0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"), + 33); + + memcpy(&node2, &node, sizeof(HDNode)); + memzero(&node2.private_key, 32); + r = hdnode_public_ckd(&node2, 33941); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x3e2b7bc6); + ck_assert_mem_eq( + node2.chain_code, + fromhex( + "9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"), + 32); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq( + node2.public_key, + fromhex( + "0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"), + 33); } END_TEST // test vector 1 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors -START_TEST(test_bip32_ed25519_vector_1) -{ - HDNode node; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, ED25519_NAME, &node); - - // [Chain m] - ck_assert_mem_eq(node.chain_code, fromhex("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"), 32); - ck_assert_mem_eq(node.private_key, fromhex("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("01a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"), 33); - - // [Chain m/0'] - hdnode_private_ckd_prime(&node, 0); - ck_assert_mem_eq(node.chain_code, fromhex("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"), 32); - ck_assert_mem_eq(node.private_key, fromhex("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("018c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"), 33); - - // [Chain m/0'/1'] - hdnode_private_ckd_prime(&node, 1); - ck_assert_mem_eq(node.chain_code, fromhex("a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14"), 32); - ck_assert_mem_eq(node.private_key, fromhex("b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("011932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187"), 33); - - // [Chain m/0'/1'/2'] - hdnode_private_ckd_prime(&node, 2); - ck_assert_mem_eq(node.chain_code, fromhex("2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("01ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1"), 33); - - // [Chain m/0'/1'/2'/2'] - hdnode_private_ckd_prime(&node, 2); - ck_assert_mem_eq(node.chain_code, fromhex("8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc"), 32); - ck_assert_mem_eq(node.private_key, fromhex("30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("018abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c"), 33); - - // [Chain m/0'/1'/2'/2'/1000000000'] - hdnode_private_ckd_prime(&node, 1000000000); - ck_assert_mem_eq(node.chain_code, fromhex("68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"), 32); - ck_assert_mem_eq(node.private_key, fromhex("8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("013c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"), 33); +START_TEST(test_bip32_ed25519_vector_1) { + HDNode node; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + ED25519_NAME, &node); + + // [Chain m] + ck_assert_mem_eq( + node.chain_code, + fromhex( + "90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "01a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"), + 33); + + // [Chain m/0'] + hdnode_private_ckd_prime(&node, 0); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "018c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"), + 33); + + // [Chain m/0'/1'] + hdnode_private_ckd_prime(&node, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "011932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187"), + 33); + + // [Chain m/0'/1'/2'] + hdnode_private_ckd_prime(&node, 2); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "01ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1"), + 33); + + // [Chain m/0'/1'/2'/2'] + hdnode_private_ckd_prime(&node, 2); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "018abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c"), + 33); + + // [Chain m/0'/1'/2'/2'/1000000000'] + hdnode_private_ckd_prime(&node, 1000000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "013c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"), + 33); } END_TEST // test vector 2 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors -START_TEST(test_bip32_ed25519_vector_2) -{ - HDNode node; - int r; - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, ED25519_NAME, &node); - - // [Chain m] - ck_assert_mem_eq(node.chain_code, fromhex("ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b"), 32); - ck_assert_mem_eq(node.private_key, fromhex("171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("018fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a"), 33); - - // [Chain m/0'] - r = hdnode_private_ckd_prime(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_mem_eq(node.chain_code, fromhex("0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d"), 32); - ck_assert_mem_eq(node.private_key, fromhex("1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0186fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037"), 33); - - // [Chain m/0'/2147483647'] - r = hdnode_private_ckd_prime(&node, 2147483647); - ck_assert_int_eq(r, 1); - ck_assert_mem_eq(node.chain_code, fromhex("138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f"), 32); - ck_assert_mem_eq(node.private_key, fromhex("ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("015ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d"), 33); - - // [Chain m/0'/2147483647'/1'] - r = hdnode_private_ckd_prime(&node, 1); - ck_assert_int_eq(r, 1); - ck_assert_mem_eq(node.chain_code, fromhex("73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90"), 32); - ck_assert_mem_eq(node.private_key, fromhex("3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("012e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45"), 33); - - // [Chain m/0'/2147483647'/1'/2147483646'] - r = hdnode_private_ckd_prime(&node, 2147483646); - ck_assert_int_eq(r, 1); - ck_assert_mem_eq(node.chain_code, fromhex("0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a"), 32); - ck_assert_mem_eq(node.private_key, fromhex("5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("01e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b"), 33); - - // [Chain m/0'/2147483647'/1'/2147483646'/2'] - r = hdnode_private_ckd_prime(&node, 2); - ck_assert_int_eq(r, 1); - ck_assert_mem_eq(node.chain_code, fromhex("5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4"), 32); - ck_assert_mem_eq(node.private_key, fromhex("551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0147150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0"), 33); +START_TEST(test_bip32_ed25519_vector_2) { + HDNode node; + int r; + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, ED25519_NAME, &node); + + // [Chain m] + ck_assert_mem_eq( + node.chain_code, + fromhex( + "ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "018fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a"), + 33); + + // [Chain m/0'] + r = hdnode_private_ckd_prime(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0186fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037"), + 33); + + // [Chain m/0'/2147483647'] + r = hdnode_private_ckd_prime(&node, 2147483647); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "015ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d"), + 33); + + // [Chain m/0'/2147483647'/1'] + r = hdnode_private_ckd_prime(&node, 1); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "012e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45"), + 33); + + // [Chain m/0'/2147483647'/1'/2147483646'] + r = hdnode_private_ckd_prime(&node, 2147483646); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "01e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b"), + 33); + + // [Chain m/0'/2147483647'/1'/2147483646'/2'] + r = hdnode_private_ckd_prime(&node, 2); + ck_assert_int_eq(r, 1); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0147150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0"), + 33); } END_TEST -// test vector 1 from https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go -START_TEST(test_bip32_decred_vector_1) -{ - HDNode node, node2, node3; - uint32_t fingerprint; - char str[112]; - int r; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, SECP256K1_NAME, &node); - - // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in hdnode_from_seed - node.curve = &secp256k1_decred_info; - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"), 32); - ck_assert_mem_eq(node.private_key, fromhex("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3hCznBesA6jBtmoyVFPfyMSZ1qYZ3WdjdebquvkEfmRfxC9VFEFi2YDaJqHnx7uGe75eGSa3Mn3oHK11hBW7KZUrPxwbCPBmuCi1nwm182s"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZ9169KDAEUnyoBhjjmT2VaEodr6pUTDoqCEAeqgbfr2JfkB88BbK77jbTYbcYXb2FVz7DKBdW4P618yd51MwF8DjKVopSbS7Lkgi6bowX5w"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 0); - ck_assert_int_eq(fingerprint, 0xbc495588); - ck_assert_mem_eq(node.chain_code, fromhex("47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"), 32); - ck_assert_mem_eq(node.private_key, fromhex("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3kUQDBztdyjKuwnaL3hfKYpT7W6X2huYH5d61YSWFBebSYwEBHAXJkCpQ7rvMAxPzKqxVCGLvBqWvGxXjAyMJsV1XwKkfnQCM9KctC8k8bk"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZCGVaKZBiMo7pMgLaZm1qmchjWenTeVcUdFQkTNsFGFEA6xs4EW8PKiqYqP7HBAitt9Hw16VQkQ1tjsZQSHNWFc6bEK6bLqrbco24FzBTY4"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1); - ck_assert_int_eq(fingerprint, 0xc67bc2ef); - ck_assert_mem_eq(node.chain_code, fromhex("2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"), 32); - ck_assert_mem_eq(node.private_key, fromhex("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3nRtCZ5VAoHW4RUwQgRafSNRPUDFrmsgyY71A5eoZceVfuyL9SbZe2rcbwDW2UwpkEniE4urffgbypegscNchPajWzy9QS4cRxF8QYXsZtq"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZEDyZgdnFBMHxqNhfCUwBfAg1UmXHiTmB5jKtzbAZhF8PTzy2PwAicNdkg1CmW6TARxQeUbgC7nAQenJts4YoG3KMiqcjsjgeMvwLc43w6C"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd_prime(&node, 2); - ck_assert_int_eq(fingerprint, 0xe7072187); - ck_assert_mem_eq(node.chain_code, fromhex("04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"), 32); - ck_assert_mem_eq(node.private_key, fromhex("cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3pYtkZK168vgrU38gXkUSjHQ2LGpEUzQ9fXrR8fGUR59YviSnm6U82XjQYhpJEUPnVcC9bguJBQU5xVM4VFcDHu9BgScGPA6mQMH4bn5Cth"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZGLz7gsJAWzUksvtw3opxx5eeLq5fRaUMDABA3bdUVfnGUk5fiS5Cc3kZGTjWtYr3jrEavQQnAF6jv2WCpZtFX4uFgifXqev6ED1TM9rTCB"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'/2] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 2); - ck_assert_int_eq(fingerprint, 0xbcbbc1c4); - ck_assert_mem_eq(node.chain_code, fromhex("cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3r7zqYFjT3NiNzdnwGxGpYh6S1TJCp1zA6mSEGaqLBJFnCB94cRMp7YYLR49aTZHZ7ya1CXwQJ6rodKeU9NgQTxkPSK7pzgZRgjYkQ7rgJh"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZHv6Cfp2XRSWHQXZBo1dLmVM421Zdkc4MePkyBXCLFttVkCmwZkxth4ZV9PzkFP3DtD5xcVq2CPSYpJMWMaoxu1ixz4GNZFVcE2xnHP6chJ"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0'/1/2'/2/1000000000] - fingerprint = hdnode_fingerprint(&node); - hdnode_private_ckd(&node, 1000000000); - ck_assert_int_eq(fingerprint, 0xe58b52e4); - ck_assert_mem_eq(node.chain_code, fromhex("c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"), 32); - ck_assert_mem_eq(node.private_key, fromhex("471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3tJXnTDSb3uE6Euo6WvvhFKfBMNfxuJt5smqyPoHEoomoBMQyhYoQSKJAHWtWxmuqdUVb8q9J2NaTkF6rYm6XDrSotkJ55bM21fffa7VV97"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZL6d9amjfRy1zeoZM2zHDU7uoMvwPqtxHRQAiJjeEtQQWjP3retQV1qKJyzUd6ZJNgbJGXjtc5pdoBcTTYTLoxQzvV9JJCzCjB2eCWpRf8T"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); +// test vector 1 from +// https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go +START_TEST(test_bip32_decred_vector_1) { + HDNode node, node2, node3; + uint32_t fingerprint; + char str[112]; + int r; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + SECP256K1_NAME, &node); + + // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in + // hdnode_from_seed + node.curve = &secp256k1_decred_info; + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3hCznBesA6jBtmoyVFPfyMSZ1qYZ3WdjdebquvkEfmRfxC9VFEFi2YD" + "aJqHnx7uGe75eGSa3Mn3oHK11hBW7KZUrPxwbCPBmuCi1nwm182s"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZ9169KDAEUnyoBhjjmT2VaEodr6pUTDoqCEAeqgbfr2JfkB88BbK77j" + "bTYbcYXb2FVz7DKBdW4P618yd51MwF8DjKVopSbS7Lkgi6bowX5w"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 0); + ck_assert_int_eq(fingerprint, 0xbc495588); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3kUQDBztdyjKuwnaL3hfKYpT7W6X2huYH5d61YSWFBebSYwEBHAXJkC" + "pQ7rvMAxPzKqxVCGLvBqWvGxXjAyMJsV1XwKkfnQCM9KctC8k8bk"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZCGVaKZBiMo7pMgLaZm1qmchjWenTeVcUdFQkTNsFGFEA6xs4EW8PKi" + "qYqP7HBAitt9Hw16VQkQ1tjsZQSHNWFc6bEK6bLqrbco24FzBTY4"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1); + ck_assert_int_eq(fingerprint, 0xc67bc2ef); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3nRtCZ5VAoHW4RUwQgRafSNRPUDFrmsgyY71A5eoZceVfuyL9SbZe2r" + "cbwDW2UwpkEniE4urffgbypegscNchPajWzy9QS4cRxF8QYXsZtq"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZEDyZgdnFBMHxqNhfCUwBfAg1UmXHiTmB5jKtzbAZhF8PTzy2PwAicN" + "dkg1CmW6TARxQeUbgC7nAQenJts4YoG3KMiqcjsjgeMvwLc43w6C"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd_prime(&node, 2); + ck_assert_int_eq(fingerprint, 0xe7072187); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3pYtkZK168vgrU38gXkUSjHQ2LGpEUzQ9fXrR8fGUR59YviSnm6U82X" + "jQYhpJEUPnVcC9bguJBQU5xVM4VFcDHu9BgScGPA6mQMH4bn5Cth"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZGLz7gsJAWzUksvtw3opxx5eeLq5fRaUMDABA3bdUVfnGUk5fiS5Cc3" + "kZGTjWtYr3jrEavQQnAF6jv2WCpZtFX4uFgifXqev6ED1TM9rTCB"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'/2] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 2); + ck_assert_int_eq(fingerprint, 0xbcbbc1c4); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3r7zqYFjT3NiNzdnwGxGpYh6S1TJCp1zA6mSEGaqLBJFnCB94cRMp7Y" + "YLR49aTZHZ7ya1CXwQJ6rodKeU9NgQTxkPSK7pzgZRgjYkQ7rgJh"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZHv6Cfp2XRSWHQXZBo1dLmVM421Zdkc4MePkyBXCLFttVkCmwZkxth4" + "ZV9PzkFP3DtD5xcVq2CPSYpJMWMaoxu1ixz4GNZFVcE2xnHP6chJ"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0'/1/2'/2/1000000000] + fingerprint = hdnode_fingerprint(&node); + hdnode_private_ckd(&node, 1000000000); + ck_assert_int_eq(fingerprint, 0xe58b52e4); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3tJXnTDSb3uE6Euo6WvvhFKfBMNfxuJt5smqyPoHEoomoBMQyhYoQSK" + "JAHWtWxmuqdUVb8q9J2NaTkF6rYm6XDrSotkJ55bM21fffa7VV97"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZL6d9amjfRy1zeoZM2zHDU7uoMvwPqtxHRQAiJjeEtQQWjP3retQV1q" + "KJyzUd6ZJNgbJGXjtc5pdoBcTTYTLoxQzvV9JJCzCjB2eCWpRf8T"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); } END_TEST -// test vector 2 from https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go -START_TEST(test_bip32_decred_vector_2) -{ - HDNode node, node2, node3; - uint32_t fingerprint; - char str[112]; - int r; - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, SECP256K1_NAME, &node); - - // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in hdnode_from_seed - node.curve = &secp256k1_decred_info; - - // [Chain m] - fingerprint = 0; - ck_assert_int_eq(fingerprint, 0x00000000); - ck_assert_mem_eq(node.chain_code, fromhex("60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"), 32); - ck_assert_mem_eq(node.private_key, fromhex("4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3hCznBesA6jBtPKJbQTxRZAKG2gyj8tZKEPaCsV4e9YYFBAgRP2eTSPAeu4r8dTMt9q51j2Vdt5zNqj7jbtovvocrP1qLj6WUTLF9xYQt4y"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZ9169KDAEUnynoD4qvXJwmxZt3FFA5UdWn1twnRReE9AxjCKJLNFY1uBoegbFmwzA4Du7yqnu8tLivhrCCH6P3DgBS1HH5vmf8MpNXvvYT9"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x2524c9d3); - ck_assert_mem_eq(node.chain_code, fromhex("f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3jMy45BuuDETfxi59P8NTSjHPrNVq4wPRfLgRd57923L2hosj5NUEqiLYQ4i7fJtUpiXZLr2wUeToJY2Tm5sCpAJdajEHDmieVJiPQNXwu9"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZBA4RCkCybJFaNbqPuBiyfXY1rvmG1XTdCy1AY1U96dxkFqWc2i5KREMh7NYPpy7ZPMhdpFMAesex3JdFDfX4J5FEW3HjSacqEYPfwb9Cj7"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483647); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x6035c6ad); - ck_assert_mem_eq(node.chain_code, fromhex("be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"), 32); - ck_assert_mem_eq(node.private_key, fromhex("877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3mgHPRgK838mLK6T1p6WeBoJoJtXA1pGTHjqFuyHekcM7UTuER8fGweRRsoLqSuHa98uskVPnJnfWZEBUC1AVmXnSCPDvUFKydXNnnPHTuQ"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZDUNkZEcCRCZEizDGL9sAQbZRKSnaxQLeqN9zpueeqCyq2VY7NUGMXASacsK96S8XzNjq3YgFgwLtj8MJBToW6To9U5zxuazEyh89bjR1xA"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 1); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x36fc7080); - ck_assert_mem_eq(node.chain_code, fromhex("f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"), 32); - ck_assert_mem_eq(node.private_key, fromhex("704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3oFqwZZ9bJcUmhAeJyyshvrTWtrAsHfcRYQbEzNiiH5nGvM6wVTDn6woQEz92b2EHTYZBtLi82jKEnxSouA3cVaW8YWBsw5c3f4mwAhA3d2"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZF3wJh7SfggGg74QZW3EE9ei8uQSJEFgd62uyuK5iMgQzUNjpSnprgTpYz3d6Q3fXXtEEXQqpzWcP4LUVuXFsgA8JKt1Hot5kyUk4pPRhDz"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1/2147483646'] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd_prime(&node, 2147483646); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x45309b4c); - ck_assert_mem_eq(node.chain_code, fromhex("637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"), 32); - ck_assert_mem_eq(node.private_key, fromhex("f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3qF3177i87wMirg6sraDvqty8yZg6THpXFPSXuM5AShBiiUQbq8FhSZDGkYmBNR3RKfBrxzkKDBpsRFJfTnQfLsvpPPqRnakat6hHQA43X9"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZH38NEg1CW19dGZs8NdaT4hDkz7wXPstio1mGpHSAXHpSGW3UnTrn25ERT1Mp8ae5GMoQHMbgQiPrChMXQMdx3UqS8YqFkT1pqait8fY92u"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // [Chain m/0/2147483647'/1/2147483646'/2] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_private_ckd(&node, 2); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x3491a5e6); - ck_assert_mem_eq(node.chain_code, fromhex("9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"), 32); - ck_assert_mem_eq(node.private_key, fromhex("bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key, fromhex("024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"), 33); - hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, sizeof(str)); - ck_assert_str_eq(str, "dprv3s15tfqzxhw8Kmo7RBEqMeyvC7uGekLniSmvbs3bckpxQ6ks1KKqfmH144Jgh3PLxkyZRcS367kp7DrtUmnG16NpnsoNhxSXRgKbJJ7MUQR"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - hdnode_fill_public_key(&node2); - ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZJoBFoQJ35zvEBgsfhJBssnAp8TY5gvruzQFLmyxcqRb7enVtGfSkLo2CkAZJMpa6T2fx6fUtvTgXtUvSVgAZ56bEwGxQsToeZfFV8VadE1"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - memcpy(&node3, &node, sizeof(HDNode)); - memzero(&node3.private_key, 32); - ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); - - // init m - hdnode_deserialize("dpubZF4LSCdF9YKZfNzTVYhz4RBxsjYXqms8AQnMBHXZ8GUKoRSigG7kQnKiJt5pzk93Q8FxcdVBEkQZruSXduGtWnkwXzGnjbSovQ97dCxqaXc", DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node, NULL); - - // test public derivation - // [Chain m/0] - fingerprint = hdnode_fingerprint(&node); - r = hdnode_public_ckd(&node, 0); - ck_assert_int_eq(r, 1); - ck_assert_int_eq(fingerprint, 0x6a19cfb3); - ck_assert_mem_eq(node.chain_code, fromhex("dcfe00831741a3a4803955147cdfc7053d69b167b1d03b5f9e63934217a005fd"), 32); - ck_assert_mem_eq(node.public_key, fromhex("029555ea7bde276cd2c42c4502f40b5d16469fb310ae3aeee2a9000455f41b0866"), 33); - hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, sizeof(str)); - ck_assert_str_eq(str, "dpubZHJs2Z3PtHbbpaXQCi5wBKPhU8tC5ztBKUYBCYNGKk8eZ1EmBs3MhnLJbxHFMAahGnDnZT7qZxC7AXKP8PB6BDNUZgkG77moNMRmXyQ6s6s"); - r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, &node2, NULL); ck_assert_int_eq(r, 0); - ck_assert_mem_eq(&node2, &node, sizeof(HDNode)); +// test vector 2 from +// https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go +START_TEST(test_bip32_decred_vector_2) { + HDNode node, node2, node3; + uint32_t fingerprint; + char str[112]; + int r; + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, SECP256K1_NAME, &node); + + // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in + // hdnode_from_seed + node.curve = &secp256k1_decred_info; + + // [Chain m] + fingerprint = 0; + ck_assert_int_eq(fingerprint, 0x00000000); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3hCznBesA6jBtPKJbQTxRZAKG2gyj8tZKEPaCsV4e9YYFBAgRP2eTSP" + "Aeu4r8dTMt9q51j2Vdt5zNqj7jbtovvocrP1qLj6WUTLF9xYQt4y"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZ9169KDAEUnynoD4qvXJwmxZt3FFA5UdWn1twnRReE9AxjCKJLNFY1u" + "BoegbFmwzA4Du7yqnu8tLivhrCCH6P3DgBS1HH5vmf8MpNXvvYT9"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x2524c9d3); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3jMy45BuuDETfxi59P8NTSjHPrNVq4wPRfLgRd57923L2hosj5NUEqi" + "LYQ4i7fJtUpiXZLr2wUeToJY2Tm5sCpAJdajEHDmieVJiPQNXwu9"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZBA4RCkCybJFaNbqPuBiyfXY1rvmG1XTdCy1AY1U96dxkFqWc2i5KRE" + "Mh7NYPpy7ZPMhdpFMAesex3JdFDfX4J5FEW3HjSacqEYPfwb9Cj7"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483647); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x6035c6ad); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3mgHPRgK838mLK6T1p6WeBoJoJtXA1pGTHjqFuyHekcM7UTuER8fGwe" + "RRsoLqSuHa98uskVPnJnfWZEBUC1AVmXnSCPDvUFKydXNnnPHTuQ"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZDUNkZEcCRCZEizDGL9sAQbZRKSnaxQLeqN9zpueeqCyq2VY7NUGMXA" + "SacsK96S8XzNjq3YgFgwLtj8MJBToW6To9U5zxuazEyh89bjR1xA"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 1); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x36fc7080); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3oFqwZZ9bJcUmhAeJyyshvrTWtrAsHfcRYQbEzNiiH5nGvM6wVTDn6w" + "oQEz92b2EHTYZBtLi82jKEnxSouA3cVaW8YWBsw5c3f4mwAhA3d2"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZF3wJh7SfggGg74QZW3EE9ei8uQSJEFgd62uyuK5iMgQzUNjpSnprgT" + "pYz3d6Q3fXXtEEXQqpzWcP4LUVuXFsgA8JKt1Hot5kyUk4pPRhDz"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1/2147483646'] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd_prime(&node, 2147483646); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x45309b4c); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3qF3177i87wMirg6sraDvqty8yZg6THpXFPSXuM5AShBiiUQbq8FhSZ" + "DGkYmBNR3RKfBrxzkKDBpsRFJfTnQfLsvpPPqRnakat6hHQA43X9"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZH38NEg1CW19dGZs8NdaT4hDkz7wXPstio1mGpHSAXHpSGW3UnTrn25" + "ERT1Mp8ae5GMoQHMbgQiPrChMXQMdx3UqS8YqFkT1pqait8fY92u"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // [Chain m/0/2147483647'/1/2147483646'/2] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_private_ckd(&node, 2); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x3491a5e6); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key, + fromhex( + "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"), + 33); + hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str, + sizeof(str)); + ck_assert_str_eq(str, + "dprv3s15tfqzxhw8Kmo7RBEqMeyvC7uGekLniSmvbs3bckpxQ6ks1KKqfmH" + "144Jgh3PLxkyZRcS367kp7DrtUmnG16NpnsoNhxSXRgKbJJ7MUQR"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + hdnode_fill_public_key(&node2); + ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZJoBFoQJ35zvEBgsfhJBssnAp8TY5gvruzQFLmyxcqRb7enVtGfSkLo" + "2CkAZJMpa6T2fx6fUtvTgXtUvSVgAZ56bEwGxQsToeZfFV8VadE1"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + memcpy(&node3, &node, sizeof(HDNode)); + memzero(&node3.private_key, 32); + ck_assert_mem_eq(&node2, &node3, sizeof(HDNode)); + + // init m + hdnode_deserialize( + "dpubZF4LSCdF9YKZfNzTVYhz4RBxsjYXqms8AQnMBHXZ8GUKoRSigG7kQnKiJt5pzk93Q8Fx" + "cdVBEkQZruSXduGtWnkwXzGnjbSovQ97dCxqaXc", + DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, SECP256K1_DECRED_NAME, + &node, NULL); + + // test public derivation + // [Chain m/0] + fingerprint = hdnode_fingerprint(&node); + r = hdnode_public_ckd(&node, 0); + ck_assert_int_eq(r, 1); + ck_assert_int_eq(fingerprint, 0x6a19cfb3); + ck_assert_mem_eq( + node.chain_code, + fromhex( + "dcfe00831741a3a4803955147cdfc7053d69b167b1d03b5f9e63934217a005fd"), + 32); + ck_assert_mem_eq( + node.public_key, + fromhex( + "029555ea7bde276cd2c42c4502f40b5d16469fb310ae3aeee2a9000455f41b0866"), + 33); + hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str, + sizeof(str)); + ck_assert_str_eq(str, + "dpubZHJs2Z3PtHbbpaXQCi5wBKPhU8tC5ztBKUYBCYNGKk8eZ1EmBs3MhnL" + "JbxHFMAahGnDnZT7qZxC7AXKP8PB6BDNUZgkG77moNMRmXyQ6s6s"); + r = hdnode_deserialize(str, DECRED_VERSION_PUBLIC, DECRED_VERSION_PRIVATE, + SECP256K1_DECRED_NAME, &node2, NULL); + ck_assert_int_eq(r, 0); + ck_assert_mem_eq(&node2, &node, sizeof(HDNode)); } END_TEST -START_TEST(test_ecdsa_signature) -{ - int res; - uint8_t digest[32]; - 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 - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000020123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 0); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("043fc5bf5fec35b6ffe6fd246226d312742a8c296bfa57dd22da509a2e348529b7ddb9faf8afe1ecda3c05e7b2bda47ee1f5a87e952742b22afca560b29d972fcf"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000020123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 1); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("0456d8089137b1fd0d890f8c7d4a04d0fd4520a30b19518ee87bd168ea12ed8090329274c4c6c0d9df04515776f2741eeffc30235d596065d718c3973e19711ad0"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000020123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 2); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("04cee0e740f41aab39156844afef0182dea2a8026885b10454a2d539df6f6df9023abfcb0f01c50bef3c0fa8e59a998d07441e18b1c60583ef75cc8b912fb21a15"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000020123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 3); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("0490d2bd2e9a564d6e1d8324fc6ad00aa4ae597684ecf4abea58bdfe7287ea4fa72968c2e5b0b40999ede3d7898d94e82c3f8dc4536a567a4bd45998c826a4c4b2"), 65); - - memcpy(digest, fromhex("0000000000000000000000000000000000000000000000000000000000000000"), 32); - // r = 7: No point P with P.x = 7, but P.x = (order + 7) exists - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000070123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 2); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b040de78f8dbda700f4d3cd7ee21b3651a74c7661809699d2be7ea0992b0d39797"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000070123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 3); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b0bf21870724258ff0b2c32811de4c9ae58b3899e7f69662d41815f66c4f2c6498"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000070123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 0); - ck_assert_int_eq(res, 1); - - memcpy(digest, fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 32); - // r = 1: Two points P with P.x = 1, but P.x = (order + 7) doesn't exist - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000010123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 0); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("045d330b2f89dbfca149828277bae852dd4aebfe136982cb531a88e9e7a89463fe71519f34ea8feb9490c707f14bc38c9ece51762bfd034ea014719b7c85d2871b"), 65); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000010123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 1); - ck_assert_int_eq(res, 0); - ck_assert_mem_eq(pubkey, fromhex("049e609c3950e70d6f3e3f3c81a473b1d5ca72739d51debdd80230ae80cab05134a94285375c834a417e8115c546c41da83a263087b79ef1cae25c7b3c738daa2b"), 65); - - // r = 0 is always invalid - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000010123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 2); - ck_assert_int_eq(res, 1); - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000000123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 0); - ck_assert_int_eq(res, 1); - // r >= order is always invalid - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 0); - ck_assert_int_eq(res, 1); - // check that overflow of r is handled - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("000000000000000000000000000000014551231950B75FC4402DA1722FC9BAEE0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), digest, 2); - ck_assert_int_eq(res, 1); - // s = 0 is always invalid - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), digest, 0); - ck_assert_int_eq(res, 1); - // s >= order is always invalid - res = ecdsa_recover_pub_from_sig (curve, pubkey, fromhex ("0000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"), digest, 0); - ck_assert_int_eq(res, 1); +START_TEST(test_ecdsa_signature) { + int res; + uint8_t digest[32]; + 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 + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000020123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 0); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "043fc5bf5fec35b6ffe6fd246226d312742a8c296bfa57dd22da509a2e348529b7dd" + "b9faf8afe1ecda3c05e7b2bda47ee1f5a87e952742b22afca560b29d972fcf"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000020123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 1); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "0456d8089137b1fd0d890f8c7d4a04d0fd4520a30b19518ee87bd168ea12ed809032" + "9274c4c6c0d9df04515776f2741eeffc30235d596065d718c3973e19711ad0"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000020123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 2); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "04cee0e740f41aab39156844afef0182dea2a8026885b10454a2d539df6f6df9023a" + "bfcb0f01c50bef3c0fa8e59a998d07441e18b1c60583ef75cc8b912fb21a15"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000020123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 3); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "0490d2bd2e9a564d6e1d8324fc6ad00aa4ae597684ecf4abea58bdfe7287ea4fa729" + "68c2e5b0b40999ede3d7898d94e82c3f8dc4536a567a4bd45998c826a4c4b2"), + 65); + + memcpy( + digest, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000000"), + 32); + // r = 7: No point P with P.x = 7, but P.x = (order + 7) exists + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000070123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 2); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b040" + "de78f8dbda700f4d3cd7ee21b3651a74c7661809699d2be7ea0992b0d39797"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000070123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 3); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b0bf" + "21870724258ff0b2c32811de4c9ae58b3899e7f69662d41815f66c4f2c6498"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000070123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 0); + ck_assert_int_eq(res, 1); + + memcpy( + digest, + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + 32); + // r = 1: Two points P with P.x = 1, but P.x = (order + 7) doesn't exist + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000010123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 0); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "045d330b2f89dbfca149828277bae852dd4aebfe136982cb531a88e9e7a89463fe71" + "519f34ea8feb9490c707f14bc38c9ece51762bfd034ea014719b7c85d2871b"), + 65); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000010123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 1); + ck_assert_int_eq(res, 0); + ck_assert_mem_eq( + pubkey, + fromhex( + "049e609c3950e70d6f3e3f3c81a473b1d5ca72739d51debdd80230ae80cab05134a9" + "4285375c834a417e8115c546c41da83a263087b79ef1cae25c7b3c738daa2b"), + 65); + + // r = 0 is always invalid + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000010123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 2); + ck_assert_int_eq(res, 1); + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000000123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 0); + ck_assert_int_eq(res, 1); + // r >= order is always invalid + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 0); + ck_assert_int_eq(res, 1); + // check that overflow of r is handled + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "000000000000000000000000000000014551231950B75FC4402DA1722FC9BAEE0123" + "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), + digest, 2); + ck_assert_int_eq(res, 1); + // s = 0 is always invalid + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000020000" + "000000000000000000000000000000000000000000000000000000000000"), + digest, 0); + ck_assert_int_eq(res, 1); + // s >= order is always invalid + res = ecdsa_recover_pub_from_sig( + curve, pubkey, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000002ffff" + "fffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"), + digest, 0); + ck_assert_int_eq(res, 1); } END_TEST -#define test_deterministic(KEY, MSG, K) do { \ - sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \ - init_rfc6979(fromhex(KEY), buf, &rng); \ - generate_k_rfc6979(&k, &rng); \ - bn_write_be(&k, buf); \ - ck_assert_mem_eq(buf, fromhex(K), 32); \ -} while (0) - -START_TEST(test_rfc6979) -{ - bignum256 k; - uint8_t buf[32]; - rfc6979_state rng; - - test_deterministic("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", "sample", "a6e3c57dd01abe90086538398355dd4c3b17aa873382b0f24d6129493d8aad60"); - test_deterministic("cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", "sample", "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3"); - test_deterministic("0000000000000000000000000000000000000000000000000000000000000001", "Satoshi Nakamoto", "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15"); - test_deterministic("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "Satoshi Nakamoto", "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90"); - test_deterministic("f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", "Alan Turing", "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1"); - test_deterministic("0000000000000000000000000000000000000000000000000000000000000001", "All those moments will be lost in time, like tears in rain. Time to die...", "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3"); - test_deterministic("e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!", "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d"); +#define test_deterministic(KEY, MSG, K) \ + do { \ + sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \ + init_rfc6979(fromhex(KEY), buf, &rng); \ + generate_k_rfc6979(&k, &rng); \ + bn_write_be(&k, buf); \ + ck_assert_mem_eq(buf, fromhex(K), 32); \ + } while (0) + +START_TEST(test_rfc6979) { + bignum256 k; + uint8_t buf[32]; + rfc6979_state rng; + + test_deterministic( + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "sample", + "a6e3c57dd01abe90086538398355dd4c3b17aa873382b0f24d6129493d8aad60"); + test_deterministic( + "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", + "sample", + "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3"); + test_deterministic( + "0000000000000000000000000000000000000000000000000000000000000001", + "Satoshi Nakamoto", + "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15"); + test_deterministic( + "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "Satoshi Nakamoto", + "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90"); + test_deterministic( + "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", + "Alan Turing", + "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1"); + test_deterministic( + "0000000000000000000000000000000000000000000000000000000000000001", + "All those moments will be lost in time, like tears in rain. Time to " + "die...", + "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3"); + test_deterministic( + "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", + "There is a computer disease that anybody who works with computers knows " + "about. It's a very serious disease and it interferes completely with " + "the work. The trouble with computers is that you 'play' with them!", + "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d"); } END_TEST -// test vectors from http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors -START_TEST(test_aes) -{ - aes_encrypt_ctx ctxe; - aes_decrypt_ctx ctxd; - uint8_t ibuf[16], obuf[16], iv[16], cbuf[16]; - const char **ivp, **plainp, **cipherp; - - // ECB - static const char *ecb_vector[] = { - // plain cipher - "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8", - "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870", - "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d", - "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7", - 0, 0, - }; - plainp = ecb_vector; - cipherp = ecb_vector + 1; - while (*plainp && *cipherp) { - // encrypt - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(ibuf, fromhex(*plainp), 16); - aes_ecb_encrypt(ibuf, obuf, 16, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); - // decrypt - aes_decrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxd); - memcpy(ibuf, fromhex(*cipherp), 16); - aes_ecb_decrypt(ibuf, obuf, 16, &ctxd); - ck_assert_mem_eq(obuf, fromhex(*plainp), 16); - plainp += 2; cipherp += 2; - } - - // CBC - static const char *cbc_vector[] = { - // iv plain cipher - "000102030405060708090A0B0C0D0E0F", "6bc1bee22e409f96e93d7e117393172a", "f58c4c04d6e5f1ba779eabfb5f7bfbd6", - "F58C4C04D6E5F1BA779EABFB5F7BFBD6", "ae2d8a571e03ac9c9eb76fac45af8e51", "9cfc4e967edb808d679f777bc6702c7d", - "9CFC4E967EDB808D679F777BC6702C7D", "30c81c46a35ce411e5fbc1191a0a52ef", "39f23369a9d9bacfa530e26304231461", - "39F23369A9D9BACFA530E26304231461", "f69f2445df4f9b17ad2b417be66c3710", "b2eb05e2c39be9fcda6c19078c6a9d1b", - 0, 0, 0, - }; - ivp = cbc_vector; - plainp = cbc_vector + 1; - cipherp = cbc_vector + 2; - while (*plainp && *cipherp) { - // encrypt - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*plainp), 16); - aes_cbc_encrypt(ibuf, obuf, 16, iv, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); - // decrypt - aes_decrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxd); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*cipherp), 16); - aes_cbc_decrypt(ibuf, obuf, 16, iv, &ctxd); - ck_assert_mem_eq(obuf, fromhex(*plainp), 16); - ivp += 3; plainp += 3; cipherp += 3; - } - - // CFB - static const char *cfb_vector[] = { - "000102030405060708090A0B0C0D0E0F", "6bc1bee22e409f96e93d7e117393172a", "DC7E84BFDA79164B7ECD8486985D3860", - "DC7E84BFDA79164B7ECD8486985D3860", "ae2d8a571e03ac9c9eb76fac45af8e51", "39ffed143b28b1c832113c6331e5407b", - "39FFED143B28B1C832113C6331E5407B", "30c81c46a35ce411e5fbc1191a0a52ef", "df10132415e54b92a13ed0a8267ae2f9", - "DF10132415E54B92A13ED0A8267AE2F9", "f69f2445df4f9b17ad2b417be66c3710", "75a385741ab9cef82031623d55b1e471", - 0, 0, 0, - }; - ivp = cfb_vector; - plainp = cfb_vector + 1; - cipherp = cfb_vector + 2; - while (*plainp && *cipherp) { - // encrypt - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*plainp), 16); - aes_cfb_encrypt(ibuf, obuf, 16, iv, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); - // decrypt (uses encryption) - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*cipherp), 16); - aes_cfb_decrypt(ibuf, obuf, 16, iv, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*plainp), 16); - ivp += 3; plainp += 3; cipherp += 3; - } - - // OFB - static const char *ofb_vector[] = { - "000102030405060708090A0B0C0D0E0F", "6bc1bee22e409f96e93d7e117393172a", "dc7e84bfda79164b7ecd8486985d3860", - "B7BF3A5DF43989DD97F0FA97EBCE2F4A", "ae2d8a571e03ac9c9eb76fac45af8e51", "4febdc6740d20b3ac88f6ad82a4fb08d", - "E1C656305ED1A7A6563805746FE03EDC", "30c81c46a35ce411e5fbc1191a0a52ef", "71ab47a086e86eedf39d1c5bba97c408", - "41635BE625B48AFC1666DD42A09D96E7", "f69f2445df4f9b17ad2b417be66c3710", "0126141d67f37be8538f5a8be740e484", - 0, 0, 0, - }; - ivp = ofb_vector; - plainp = ofb_vector + 1; - cipherp = ofb_vector + 2; - while (*plainp && *cipherp) { - // encrypt - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*plainp), 16); - aes_ofb_encrypt(ibuf, obuf, 16, iv, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); - // decrypt (uses encryption) - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - memcpy(iv, fromhex(*ivp), 16); - memcpy(ibuf, fromhex(*cipherp), 16); - aes_ofb_decrypt(ibuf, obuf, 16, iv, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*plainp), 16); - ivp += 3; plainp += 3; cipherp += 3; - } - - // CTR - static const char *ctr_vector[] = { - // plain cipher - "6bc1bee22e409f96e93d7e117393172a", "601ec313775789a5b7a7f504bbf3d228", - "ae2d8a571e03ac9c9eb76fac45af8e51", "f443e3ca4d62b59aca84e990cacaf5c5", - "30c81c46a35ce411e5fbc1191a0a52ef", "2b0930daa23de94ce87017ba2d84988d", - "f69f2445df4f9b17ad2b417be66c3710", "dfc9c58db67aada613c2dd08457941a6", - 0, 0, - }; - // encrypt - plainp = ctr_vector; - cipherp = ctr_vector + 1; - memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16); - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - while (*plainp && *cipherp) { - memcpy(ibuf, fromhex(*plainp), 16); - aes_ctr_encrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); - plainp += 2; cipherp += 2; - } - // decrypt (uses encryption) - plainp = ctr_vector; - cipherp = ctr_vector + 1; - memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16); - aes_encrypt_key256(fromhex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), &ctxe); - while (*plainp && *cipherp) { - memcpy(ibuf, fromhex(*cipherp), 16); - aes_ctr_decrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe); - ck_assert_mem_eq(obuf, fromhex(*plainp), 16); - plainp += 2; cipherp += 2; - } +// test vectors from +// http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors +START_TEST(test_aes) { + aes_encrypt_ctx ctxe; + aes_decrypt_ctx ctxd; + uint8_t ibuf[16], obuf[16], iv[16], cbuf[16]; + const char **ivp, **plainp, **cipherp; + + // ECB + static const char *ecb_vector[] = { + // plain cipher + "6bc1bee22e409f96e93d7e117393172a", + "f3eed1bdb5d2a03c064b5a7e3db181f8", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "591ccb10d410ed26dc5ba74a31362870", + "30c81c46a35ce411e5fbc1191a0a52ef", + "b6ed21b99ca6f4f9f153e7b1beafed1d", + "f69f2445df4f9b17ad2b417be66c3710", + "23304b7a39f9f3ff067d8d8f9e24ecc7", + 0, + 0, + }; + plainp = ecb_vector; + cipherp = ecb_vector + 1; + while (*plainp && *cipherp) { + // encrypt + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(ibuf, fromhex(*plainp), 16); + aes_ecb_encrypt(ibuf, obuf, 16, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); + // decrypt + aes_decrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxd); + memcpy(ibuf, fromhex(*cipherp), 16); + aes_ecb_decrypt(ibuf, obuf, 16, &ctxd); + ck_assert_mem_eq(obuf, fromhex(*plainp), 16); + plainp += 2; + cipherp += 2; + } + + // CBC + static const char *cbc_vector[] = { + // iv plain cipher + "000102030405060708090A0B0C0D0E0F", + "6bc1bee22e409f96e93d7e117393172a", + "f58c4c04d6e5f1ba779eabfb5f7bfbd6", + "F58C4C04D6E5F1BA779EABFB5F7BFBD6", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "9cfc4e967edb808d679f777bc6702c7d", + "9CFC4E967EDB808D679F777BC6702C7D", + "30c81c46a35ce411e5fbc1191a0a52ef", + "39f23369a9d9bacfa530e26304231461", + "39F23369A9D9BACFA530E26304231461", + "f69f2445df4f9b17ad2b417be66c3710", + "b2eb05e2c39be9fcda6c19078c6a9d1b", + 0, + 0, + 0, + }; + ivp = cbc_vector; + plainp = cbc_vector + 1; + cipherp = cbc_vector + 2; + while (*plainp && *cipherp) { + // encrypt + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*plainp), 16); + aes_cbc_encrypt(ibuf, obuf, 16, iv, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); + // decrypt + aes_decrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxd); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*cipherp), 16); + aes_cbc_decrypt(ibuf, obuf, 16, iv, &ctxd); + ck_assert_mem_eq(obuf, fromhex(*plainp), 16); + ivp += 3; + plainp += 3; + cipherp += 3; + } + + // CFB + static const char *cfb_vector[] = { + "000102030405060708090A0B0C0D0E0F", + "6bc1bee22e409f96e93d7e117393172a", + "DC7E84BFDA79164B7ECD8486985D3860", + "DC7E84BFDA79164B7ECD8486985D3860", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "39ffed143b28b1c832113c6331e5407b", + "39FFED143B28B1C832113C6331E5407B", + "30c81c46a35ce411e5fbc1191a0a52ef", + "df10132415e54b92a13ed0a8267ae2f9", + "DF10132415E54B92A13ED0A8267AE2F9", + "f69f2445df4f9b17ad2b417be66c3710", + "75a385741ab9cef82031623d55b1e471", + 0, + 0, + 0, + }; + ivp = cfb_vector; + plainp = cfb_vector + 1; + cipherp = cfb_vector + 2; + while (*plainp && *cipherp) { + // encrypt + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*plainp), 16); + aes_cfb_encrypt(ibuf, obuf, 16, iv, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); + // decrypt (uses encryption) + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*cipherp), 16); + aes_cfb_decrypt(ibuf, obuf, 16, iv, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*plainp), 16); + ivp += 3; + plainp += 3; + cipherp += 3; + } + + // OFB + static const char *ofb_vector[] = { + "000102030405060708090A0B0C0D0E0F", + "6bc1bee22e409f96e93d7e117393172a", + "dc7e84bfda79164b7ecd8486985d3860", + "B7BF3A5DF43989DD97F0FA97EBCE2F4A", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "4febdc6740d20b3ac88f6ad82a4fb08d", + "E1C656305ED1A7A6563805746FE03EDC", + "30c81c46a35ce411e5fbc1191a0a52ef", + "71ab47a086e86eedf39d1c5bba97c408", + "41635BE625B48AFC1666DD42A09D96E7", + "f69f2445df4f9b17ad2b417be66c3710", + "0126141d67f37be8538f5a8be740e484", + 0, + 0, + 0, + }; + ivp = ofb_vector; + plainp = ofb_vector + 1; + cipherp = ofb_vector + 2; + while (*plainp && *cipherp) { + // encrypt + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*plainp), 16); + aes_ofb_encrypt(ibuf, obuf, 16, iv, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); + // decrypt (uses encryption) + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + memcpy(iv, fromhex(*ivp), 16); + memcpy(ibuf, fromhex(*cipherp), 16); + aes_ofb_decrypt(ibuf, obuf, 16, iv, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*plainp), 16); + ivp += 3; + plainp += 3; + cipherp += 3; + } + + // CTR + static const char *ctr_vector[] = { + // plain cipher + "6bc1bee22e409f96e93d7e117393172a", + "601ec313775789a5b7a7f504bbf3d228", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "f443e3ca4d62b59aca84e990cacaf5c5", + "30c81c46a35ce411e5fbc1191a0a52ef", + "2b0930daa23de94ce87017ba2d84988d", + "f69f2445df4f9b17ad2b417be66c3710", + "dfc9c58db67aada613c2dd08457941a6", + 0, + 0, + }; + // encrypt + plainp = ctr_vector; + cipherp = ctr_vector + 1; + memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16); + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + while (*plainp && *cipherp) { + memcpy(ibuf, fromhex(*plainp), 16); + aes_ctr_encrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*cipherp), 16); + plainp += 2; + cipherp += 2; + } + // decrypt (uses encryption) + plainp = ctr_vector; + cipherp = ctr_vector + 1; + memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16); + aes_encrypt_key256( + fromhex( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + &ctxe); + while (*plainp && *cipherp) { + memcpy(ibuf, fromhex(*cipherp), 16); + aes_ctr_decrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe); + ck_assert_mem_eq(obuf, fromhex(*plainp), 16); + plainp += 2; + cipherp += 2; + } } END_TEST -#define TEST1 "abc" -#define TEST2_1 \ - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -#define TEST2_2a \ - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" -#define TEST2_2b \ - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" -#define TEST2_2 TEST2_2a TEST2_2b -#define TEST3 "a" /* times 1000000 */ -#define TEST4a "01234567012345670123456701234567" -#define TEST4b "01234567012345670123456701234567" - /* an exact multiple of 512 bits */ -#define TEST4 TEST4a TEST4b /* times 10 */ - -#define TEST7_1 \ - "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8" +#define TEST1 "abc" +#define TEST2_1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +#define TEST2_2a "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +#define TEST2_2b "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +#define TEST2_2 TEST2_2a TEST2_2b +#define TEST3 "a" /* times 1000000 */ +#define TEST4a "01234567012345670123456701234567" +#define TEST4b "01234567012345670123456701234567" +/* an exact multiple of 512 bits */ +#define TEST4 TEST4a TEST4b /* times 10 */ + +#define TEST7_1 "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8" #define TEST8_1 \ "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46" -#define TEST9_1 \ +#define TEST9_1 \ "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \ "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \ "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \ "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \ "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a" -#define TEST10_1 \ +#define TEST10_1 \ "\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \ "\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \ "\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \ @@ -2200,68 +3750,69 @@ END_TEST "\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \ "\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \ "\xcd\xbb\xfb" -#define length(x) (sizeof(x)-1) +#define length(x) (sizeof(x) - 1) // test vectors from rfc-4634 -START_TEST(test_sha1) -{ - struct { - const char* test; - int length; - int repeatcount; - int extrabits; - int numberExtrabits; - const char* result; - } tests[] = { - /* 1 */ { TEST1, length(TEST1), 1, 0, 0, - "A9993E364706816ABA3E25717850C26C9CD0D89D" }, - /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, - "84983E441C3BD26EBAAE4AA1F95129E5E54670F1" }, - /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, - "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" }, - /* 4 */ { TEST4, length(TEST4), 10, 0, 0, - "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452" }, - /* 5 */ { "", 0, 0, 0x98, 5, - "29826B003B906E660EFF4027CE98AF3531AC75BA" }, - /* 6 */ { "\x5e", 1, 1, 0, 0, - "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2" }, - /* 7 */ { TEST7_1, length(TEST7_1), 1, 0x80, 3, - "6239781E03729919C01955B3FFA8ACB60B988340" }, - /* 8 */ { TEST8_1, length(TEST8_1), 1, 0, 0, - "82ABFF6605DBE1C17DEF12A394FA22A82B544A35" }, - /* 9 */ { TEST9_1, length(TEST9_1), 1, 0xE0, 3, - "8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4" }, - /* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0, - "CB0082C8F197D260991BA6A460E76E202BAD27B3" } - }; - - for (int i = 0; i < 10; i++) { - SHA1_CTX ctx; - uint8_t digest[SHA1_DIGEST_LENGTH]; - sha1_Init(&ctx); - /* extra bits are not supported */ - if (tests[i].numberExtrabits) - continue; - for (int j = 0; j < tests[i].repeatcount; j++) { - sha1_Update(&ctx, (const uint8_t*) tests[i].test, tests[i].length); - } - sha1_Final(&ctx, digest); - ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA1_DIGEST_LENGTH); - } +START_TEST(test_sha1) { + struct { + const char *test; + int length; + int repeatcount; + int extrabits; + int numberExtrabits; + const char *result; + } tests[] = { + /* 1 */ {TEST1, length(TEST1), 1, 0, 0, + "A9993E364706816ABA3E25717850C26C9CD0D89D"}, + /* 2 */ + {TEST2_1, length(TEST2_1), 1, 0, 0, + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"}, + /* 3 */ + {TEST3, length(TEST3), 1000000, 0, 0, + "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"}, + /* 4 */ + {TEST4, length(TEST4), 10, 0, 0, + "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"}, + /* 5 */ {"", 0, 0, 0x98, 5, "29826B003B906E660EFF4027CE98AF3531AC75BA"}, + /* 6 */ {"\x5e", 1, 1, 0, 0, "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2"}, + /* 7 */ + {TEST7_1, length(TEST7_1), 1, 0x80, 3, + "6239781E03729919C01955B3FFA8ACB60B988340"}, + /* 8 */ + {TEST8_1, length(TEST8_1), 1, 0, 0, + "82ABFF6605DBE1C17DEF12A394FA22A82B544A35"}, + /* 9 */ + {TEST9_1, length(TEST9_1), 1, 0xE0, 3, + "8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4"}, + /* 10 */ + {TEST10_1, length(TEST10_1), 1, 0, 0, + "CB0082C8F197D260991BA6A460E76E202BAD27B3"}}; + + for (int i = 0; i < 10; i++) { + SHA1_CTX ctx; + uint8_t digest[SHA1_DIGEST_LENGTH]; + sha1_Init(&ctx); + /* extra bits are not supported */ + if (tests[i].numberExtrabits) continue; + for (int j = 0; j < tests[i].repeatcount; j++) { + sha1_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length); + } + sha1_Final(&ctx, digest); + ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA1_DIGEST_LENGTH); + } } END_TEST -#define TEST7_256 \ - "\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73" +#define TEST7_256 "\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73" #define TEST8_256 \ "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52" -#define TEST9_256 \ +#define TEST9_256 \ "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \ "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \ "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \ "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \ "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3" -#define TEST10_256 \ +#define TEST10_256 \ "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \ "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \ "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \ @@ -2275,59 +3826,75 @@ END_TEST "\x3d\x54\xd6" // test vectors from rfc-4634 -START_TEST(test_sha256) -{ - struct { - const char* test; - int length; - int repeatcount; - int extrabits; - int numberExtrabits; - const char* result; - } tests[] = { - /* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141" - "40DE5DAE2223B00361A396177A9CB410FF61F20015AD" }, - /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, "248D6A61D20638B8" - "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1" }, - /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, "CDC76E5C9914FB92" - "81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0" }, - /* 4 */ { TEST4, length(TEST4), 10, 0, 0, "594847328451BDFA" - "85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5" }, - /* 5 */ { "", 0, 0, 0x68, 5, "D6D3E02A31A84A8CAA9718ED6C2057BE" - "09DB45E7823EB5079CE7A573A3760F95" }, - /* 6 */ { "\x19", 1, 1, 0, 0, "68AA2E2EE5DFF96E3355E6C7EE373E3D" - "6A4E17F75F9518D843709C0C9BC3E3D4" }, - /* 7 */ { TEST7_256, length(TEST7_256), 1, 0x60, 3, "77EC1DC8" - "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" }, - /* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA" - "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" }, - /* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646" - "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" }, - /* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D" - "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" }, - }; - - for (int i = 0; i < 10; i++) { - SHA256_CTX ctx; - uint8_t digest[SHA256_DIGEST_LENGTH]; - sha256_Init(&ctx); - /* extra bits are not supported */ - if (tests[i].numberExtrabits) - continue; - for (int j = 0; j < tests[i].repeatcount; j++) { - sha256_Update(&ctx, (const uint8_t*) tests[i].test, tests[i].length); - } - sha256_Final(&ctx, digest); - ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA256_DIGEST_LENGTH); - } +START_TEST(test_sha256) { + struct { + const char *test; + int length; + int repeatcount; + int extrabits; + int numberExtrabits; + const char *result; + } tests[] = { + /* 1 */ {TEST1, length(TEST1), 1, 0, 0, + "BA7816BF8F01CFEA4141" + "40DE5DAE2223B00361A396177A9CB410FF61F20015AD"}, + /* 2 */ + {TEST2_1, length(TEST2_1), 1, 0, 0, + "248D6A61D20638B8" + "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1"}, + /* 3 */ + {TEST3, length(TEST3), 1000000, 0, 0, + "CDC76E5C9914FB92" + "81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0"}, + /* 4 */ + {TEST4, length(TEST4), 10, 0, 0, + "594847328451BDFA" + "85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5"}, + /* 5 */ + {"", 0, 0, 0x68, 5, + "D6D3E02A31A84A8CAA9718ED6C2057BE" + "09DB45E7823EB5079CE7A573A3760F95"}, + /* 6 */ + {"\x19", 1, 1, 0, 0, + "68AA2E2EE5DFF96E3355E6C7EE373E3D" + "6A4E17F75F9518D843709C0C9BC3E3D4"}, + /* 7 */ + {TEST7_256, length(TEST7_256), 1, 0x60, 3, + "77EC1DC8" + "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972"}, + /* 8 */ + {TEST8_256, length(TEST8_256), 1, 0, 0, + "175EE69B02BA" + "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8"}, + /* 9 */ + {TEST9_256, length(TEST9_256), 1, 0xA0, 3, + "3E9AD646" + "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9"}, + /* 10 */ + {TEST10_256, length(TEST10_256), 1, 0, 0, + "97DBCA7D" + "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC"}, + }; + + for (int i = 0; i < 10; i++) { + SHA256_CTX ctx; + uint8_t digest[SHA256_DIGEST_LENGTH]; + sha256_Init(&ctx); + /* extra bits are not supported */ + if (tests[i].numberExtrabits) continue; + for (int j = 0; j < tests[i].repeatcount; j++) { + sha256_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length); + } + sha256_Final(&ctx, digest); + ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA256_DIGEST_LENGTH); + } } END_TEST -#define TEST7_512 \ - "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70" +#define TEST7_512 "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70" #define TEST8_512 \ "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0" -#define TEST9_512 \ +#define TEST9_512 \ "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \ "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \ "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \ @@ -2337,7 +3904,7 @@ END_TEST "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \ "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \ "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06" -#define TEST10_512 \ +#define TEST10_512 \ "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \ "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \ "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \ @@ -2355,2456 +3922,4408 @@ END_TEST "\xfb\x40\xd2" // test vectors from rfc-4634 -START_TEST(test_sha512) -{ - struct { - const char* test; - int length; - int repeatcount; - int extrabits; - int numberExtrabits; - const char* result; - } tests[] = { - /* 1 */ { TEST1, length(TEST1), 1, 0, 0, - "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" - "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" - "454D4423643CE80E2A9AC94FA54CA49F" }, - /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, - "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" - "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" - "C7D329EEB6DD26545E96E55B874BE909" }, - /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, - "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428" - "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B" - "EB009C5C2C49AA2E4EADB217AD8CC09B" }, - /* 4 */ { TEST4, length(TEST4), 10, 0, 0, - "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024" - "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51" - "0813A39CD5A84C4ACAA64D3F3FB7BAE9" }, - /* 5 */ { "", 0, 0, 0xB0, 5, - "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0" - "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2" - "1B22A84CC03BF8CE4845F34DD5BDBAD4" }, - /* 6 */ { "\xD0", 1, 1, 0, 0, - "9992202938E882E73E20F6B69E68A0A7149090423D93C81B" - "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A" - "D6E74CECE9631BFA8A549B4AB3FBBA15" }, - /* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3, - "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71" - "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B" - "7359B43E64F8BEC3C1F237119986BBB6" }, - /* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0, - "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD" - "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398" - "8213EB1B16F517AD0DE4B2F0C95C90F8" }, - /* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3, - "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6" - "82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2" - "526F8A0A510E5E53CAFED4355FE7C2F1" }, - /* 10 */ { TEST10_512, length(TEST10_512), 1, 0, 0, - "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909" - "C1A16A270D48719377966B957A878E720584779A62825C18" - "DA26415E49A7176A894E7510FD1451F5" } - }; - - for (int i = 0; i < 10; i++) { - SHA512_CTX ctx; - uint8_t digest[SHA512_DIGEST_LENGTH]; - sha512_Init(&ctx); - /* extra bits are not supported */ - if (tests[i].numberExtrabits) - continue; - for (int j = 0; j < tests[i].repeatcount; j++) { - sha512_Update(&ctx, (const uint8_t*) tests[i].test, tests[i].length); - } - sha512_Final(&ctx, digest); - ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA512_DIGEST_LENGTH); - } +START_TEST(test_sha512) { + struct { + const char *test; + int length; + int repeatcount; + int extrabits; + int numberExtrabits; + const char *result; + } tests[] = {/* 1 */ {TEST1, length(TEST1), 1, 0, 0, + "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" + "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" + "454D4423643CE80E2A9AC94FA54CA49F"}, + /* 2 */ + {TEST2_2, length(TEST2_2), 1, 0, 0, + "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" + "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" + "C7D329EEB6DD26545E96E55B874BE909"}, + /* 3 */ + {TEST3, length(TEST3), 1000000, 0, 0, + "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428" + "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B" + "EB009C5C2C49AA2E4EADB217AD8CC09B"}, + /* 4 */ + {TEST4, length(TEST4), 10, 0, 0, + "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024" + "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51" + "0813A39CD5A84C4ACAA64D3F3FB7BAE9"}, + /* 5 */ + {"", 0, 0, 0xB0, 5, + "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0" + "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2" + "1B22A84CC03BF8CE4845F34DD5BDBAD4"}, + /* 6 */ + {"\xD0", 1, 1, 0, 0, + "9992202938E882E73E20F6B69E68A0A7149090423D93C81B" + "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A" + "D6E74CECE9631BFA8A549B4AB3FBBA15"}, + /* 7 */ + {TEST7_512, length(TEST7_512), 1, 0x80, 3, + "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71" + "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B" + "7359B43E64F8BEC3C1F237119986BBB6"}, + /* 8 */ + {TEST8_512, length(TEST8_512), 1, 0, 0, + "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD" + "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398" + "8213EB1B16F517AD0DE4B2F0C95C90F8"}, + /* 9 */ + {TEST9_512, length(TEST9_512), 1, 0x80, 3, + "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6" + "82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2" + "526F8A0A510E5E53CAFED4355FE7C2F1"}, + /* 10 */ + {TEST10_512, length(TEST10_512), 1, 0, 0, + "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909" + "C1A16A270D48719377966B957A878E720584779A62825C18" + "DA26415E49A7176A894E7510FD1451F5"}}; + + for (int i = 0; i < 10; i++) { + SHA512_CTX ctx; + uint8_t digest[SHA512_DIGEST_LENGTH]; + sha512_Init(&ctx); + /* extra bits are not supported */ + if (tests[i].numberExtrabits) continue; + for (int j = 0; j < tests[i].repeatcount; j++) { + sha512_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length); + } + sha512_Final(&ctx, digest); + ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA512_DIGEST_LENGTH); + } } END_TEST // test vectors from http://www.di-mgt.com.au/sha_testvectors.html -START_TEST(test_sha3_256) -{ - uint8_t digest[SHA3_256_DIGEST_LENGTH]; - - sha3_256((uint8_t *)"", 0, digest); - ck_assert_mem_eq(digest, fromhex("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"), SHA3_256_DIGEST_LENGTH); - - sha3_256((uint8_t *)"abc", 3, digest); - ck_assert_mem_eq(digest, fromhex("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"), SHA3_256_DIGEST_LENGTH); - - sha3_256((uint8_t *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, digest); - ck_assert_mem_eq(digest, fromhex("41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"), SHA3_256_DIGEST_LENGTH); - - sha3_256((uint8_t *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, digest); - ck_assert_mem_eq(digest, fromhex("916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18"), SHA3_256_DIGEST_LENGTH); +START_TEST(test_sha3_256) { + uint8_t digest[SHA3_256_DIGEST_LENGTH]; + + sha3_256((uint8_t *)"", 0, digest); + ck_assert_mem_eq( + digest, + fromhex( + "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"), + SHA3_256_DIGEST_LENGTH); + + sha3_256((uint8_t *)"abc", 3, digest); + ck_assert_mem_eq( + digest, + fromhex( + "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"), + SHA3_256_DIGEST_LENGTH); + + sha3_256( + (uint8_t *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + digest); + ck_assert_mem_eq( + digest, + fromhex( + "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"), + SHA3_256_DIGEST_LENGTH); + + sha3_256((uint8_t *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, digest); + ck_assert_mem_eq( + digest, + fromhex( + "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18"), + SHA3_256_DIGEST_LENGTH); } END_TEST // test vectors from http://www.di-mgt.com.au/sha_testvectors.html -START_TEST(test_sha3_512) -{ - uint8_t digest[SHA3_512_DIGEST_LENGTH]; - - sha3_512((uint8_t *)"", 0, digest); - ck_assert_mem_eq(digest, fromhex("a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"), SHA3_512_DIGEST_LENGTH); - - sha3_512((uint8_t *)"abc", 3, digest); - ck_assert_mem_eq(digest, fromhex("b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"), SHA3_512_DIGEST_LENGTH); - - sha3_512((uint8_t *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, digest); - ck_assert_mem_eq(digest, fromhex("04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e"), SHA3_512_DIGEST_LENGTH); - - sha3_512((uint8_t *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, digest); - ck_assert_mem_eq(digest, fromhex("afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"), SHA3_512_DIGEST_LENGTH); +START_TEST(test_sha3_512) { + uint8_t digest[SHA3_512_DIGEST_LENGTH]; + + sha3_512((uint8_t *)"", 0, digest); + ck_assert_mem_eq( + digest, + fromhex( + "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2" + "123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"), + SHA3_512_DIGEST_LENGTH); + + sha3_512((uint8_t *)"abc", 3, digest); + ck_assert_mem_eq( + digest, + fromhex( + "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e1" + "16e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"), + SHA3_512_DIGEST_LENGTH); + + sha3_512( + (uint8_t *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + digest); + ck_assert_mem_eq( + digest, + fromhex( + "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee69" + "1fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e"), + SHA3_512_DIGEST_LENGTH); + + sha3_512((uint8_t *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, digest); + ck_assert_mem_eq( + digest, + fromhex( + "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3" + "261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"), + SHA3_512_DIGEST_LENGTH); } END_TEST -// test vectors from https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/0.test-sha3-256.dat -START_TEST(test_keccak_256) -{ - static const struct { - const char *hash; - size_t length; - const char *data; - } tests[] = { - { "4e9e79ab7434f6c7401fb3305d55052ee829b9e46d5d05d43b59fefb32e9a619", 293, "a6151d4904e18ec288243028ceda30556e6c42096af7150d6a7232ca5dba52bd2192e23daa5fa2bea3d4bd95efa2389cd193fcd3376e70a5c097b32c1c62c80af9d710211545f7cdddf63747420281d64529477c61e721273cfd78f8890abb4070e97baa52ac8ff61c26d195fc54c077def7a3f6f79b36e046c1a83ce9674ba1983ec2fb58947de616dd797d6499b0385d5e8a213db9ad5078a8e0c940ff0cb6bf92357ea5609f778c3d1fb1e7e36c35db873361e2be5c125ea7148eff4a035b0cce880a41190b2e22924ad9d1b82433d9c023924f2311315f07b88bfd42850047bf3be785c4ce11c09d7e02065d30f6324365f93c5e7e423a07d754eb314b5fe9db4614275be4be26af017abdc9c338d01368226fe9af1fb1f815e7317bdbb30a0f36dc69", }, - { "c1268babc42d00c3463dc388222100f7e525a74a64665c39f112f788ddb5da42", 376, "9db801077952c2324e0044a4994edfb09b3edfcf669bfdd029f4bf42d5b0eab3056b0bf82708ca7bfadba43c9de806b10a19d0f00c2351ef1086b6b108f306e035c6b61b2e70fd7087ba848601c8a3f626a66666423717ef305a1068bfa3a1f7ffc1e5a78cb6182ffc8a577ca2a821630bf900d0fbba848bdf94b77c5946771b6c3f8c02269bc772ca56098f724536d96be68c284ee1d81697989d40029b8ea63ac1fd85f8b3cae8b194f6834ff65a5858f9498ddbb467995eb2d49cdfc6c05d92038c6e9aaeee85f8222b3784165f12a2c3df4c7a142e26dddfd831d07e22dfecc0eded48a69c8a9e1b97f1a4e0efcd4edd310de0edf82af38a6e4d5ab2a19da586e61210d4f75e7a07e2201f9c8154ca52a414a70d2eb2ac1c5b9a2900b4d871f62fa56f70d03b3dd3704bd644808c45a13231918ea884645b8ec054e8bab2935a66811fe590ddc119ae901dfeb54fc2a87c1e0a236778baab2fa8843709c6676d3c1888ba19d75ec52d73a7d035c143179b93823726b7", }, - { "e83b50e8c83cb676a7dd64c055f53e5110d5a4c62245ceb8f683fd87b2b3ec77", 166, "c070a957550b7b34113ee6543a1918d96d241f27123425db7f7b9004e047ffbe05612e7fa8c54b23c83ea427e625e97b7a28b09a70bf6d91e478eeed01d7907931c29ea86e70f2cdcfb243ccf7f24a1619abf4b5b9e6f75cbf63fc02baf4a820a9790a6b053e50fd94e0ed57037cfc2bab4d95472b97d3c25f434f1cc0b1ede5ba7f15907a42a223933e5e2dfcb518c3531975268c326d60fa911fbb7997eee3ba87656c4fe7", }, - { "8ebd2c9d4ff00e285a9b6b140bfc3cef672016f0098100e1f6f250220af7ce1a", 224, "b502fbdce4045e49e147eff5463d4b3f37f43461518868368e2c78008c84c2db79d12b58107034f67e7d0abfee67add0342dd23dce623f26b9156def87b1d7ac15a6e07301f832610fe869ada13a2b0e3d60aa6bb81bc04487e2e800f5106b0402ee0331df745e021b5ea5e32faf1c7fc1322041d221a54191c0af19948b5f34411937182e30d5cd39b5a6c959d77d92d21bb1de51f1b3411cb6eec00600429916227fb62d2c88e69576f4ac8e5efcde8efa512cc80ce7fb0dfaa6c74d26e898cefe9d4f7dce232a69f2a6a9477aa08366efcdfca117c89cb79eba15a23755e0", }, - { "db3961fdddd0c314289efed5d57363459a6700a7bd015e7a03d3e1d03f046401", 262, "22e203a98ba2c43d8bc3658f0a48a35766df356d6a5e98b0c7222d16d85a00b317207d4aef3fc7cabb67b9d8f5838de0b733e1fd59c31f0667e53286972d7090421ad90d54db2ea40047d0d1700c86f53dbf48da532396307e68edad877dcae481848801b0a5db44dbdba6fc7c63b5cd15281d57ca9e6be96f530b209b59d6127ad2bd8750f3f80798f62521f0d5b42633c2f5a9aaefbed38779b7aded2338d66850b0bb0e33c48e040c99f2dcee7a7ebb3d7416e1c5bf038c19d09682dab67c96dbbfad472e45980aa27d1b301b15f7de4d4f549bad2501931c9d4f1a3b1692dcb4b1b834ddd4a636126702307ddaeec61841693b21887d56e76cc2069dafb557fd6682160f", }, - { "25dd3acacd6bf688c0eace8d33eb7cc550271969142deb769a05b4012f7bb722", 122, "99e7f6e0ed46ec866c43a1ab494998d47e9309a79fde2a629eb63bb2160a5ffd0f2206de9c32dd20e9b23e57ab7422cf82971cc2873ec0e173fe93281c7b33e1c76ac79223a6f435f230bdd30260c00d00986c72a399d3ba70f6e783d834bbf8a6127844def559b8b6db742b2cfd715f7ff29e7b42bf7d567beb", }, - { "00d747c9045c093484290afc161437f11c2ddf5f8a9fc2acae9c7ef5fcf511e5", 440, "50c392f97f8788377f0ab2e2aab196cb017ad157c6f9d022673d39072cc198b06622a5cbd269d1516089fa59e28c3373a92bd54b2ebf1a79811c7e40fdd7bce200e80983fda6e77fc44c44c1b5f87e01cef2f41e1141103f73364e9c2f25a4597e6517ef31b316300b770c69595e0fa6d011df1566a8676a88c7698562273bbfa217cc69d4b5c89a8907b902f7dc14481fefc7da4a810c15a60f5641aae854d2f8cc50cbc393015560f01c94e0d0c075dbcb150ad6eba29dc747919edcaf0231dba3eb3f2b1a87e136a1f0fd4b3d8ee61bad2729e9526a32884f7bcfa41e361add1b4c51dc81463528372b4ec321244de0c541ba00df22b8773cdf4cf898510c867829fa6b4ff11f9627338b9686d905cb7bcdf085080ab842146e0035c808be58cce97827d8926a98bd1ff7c529be3bc14f68c91b2ca4d2f6fc748f56bcf14853b7f8b9aa6d388f0fd82f53fdc4bacf9d9ba10a165f404cf427e199f51bf6773b7c82531e17933f6d8b8d9181e22f8921a2dbb20fc7c8023a87e716e245017c399d0942934f5e085219b3f8d26a196bf8b239438b8e561c28a61ff08872ecb052c5fcb19e2fdbc09565924a50ebee1461c4b414219d4257", }, - { "dadcde7c3603ef419d319ba3d50cf00ad57f3e81566fd11b9b6f461cbb9dcb0f", 338, "18e1df97abccc91e07dc7b7ffab5ee8919d5610721453176aa2089fb96d9a477e1476f507fa1129f04304e960e8017ff41246cacc0153055fc4b1dc6168a74067ebb077cb5aa80a9df6e8b5b821e906531159668c4c164b9e511d8724aedbe17c1f41da8809417d3c30b79ea5a2e3c961f6bac5436d9af6be24a36eebcb17863fed82c0eb8962339eb612d58659dddd2ea06a120b3a2d8a17050be2de367db25a5bef4290c209bdb4c16c4df5a1fe1ead635169a1c35f0a56bc07bcf6ef0e4c2d8573ed7a3b58030fa268c1a5974b097288f01f34d5a1087946410688016882c6c7621aad680d9a25c7a3e5dbcbb07ffdb7243b91031c08a121b40785e96b7ee46770c760f84aca8f36b7c7da64d25c8f73b4d88ff3acb7eeefc0b75144dffea66d2d1f6b42b905b61929ab3f38538393ba5ca9d3c62c61f46fa63789cac14e4e1d8722bf03cceef6e3de91f783b0072616c", }, - { "d184e84a2507fc0f187b640dd5b849a366c0383d9cbdbc6fa30904f054111255", 141, "13b8df9c1bcfddd0aa39b3055f52e2bc36562b6677535994b173f07041d141699db42589d6091ef0e71b645b41ab57577f58c98da966562d24823158f8e1d43b54edea4e61dd66fe8c59ad8405f5a0d9a3eb509a77ae3d8ae4adf926fd3d8d31c3dcccfc140814541010937024cc554e1daaee1b333a66316e7fbebb07ac8dfb134a918b9090b14168012c4824", }, - { "20c19635364a00b151d0168fe5ae03bac6dd7d06030475b40d2e8c577a192f53", 84, "e1e96da4b7d8dcc2b316006503a990ea26a5b200cb7a7edfc14f5ce827f06d8d232ec95b1acdc1422ffc16da11d258f0c7b378f026d64c74b2fb41df8bfd3cd30066caecdc6f76c8163de9309d9fd0cf33d54a29", }, - { "86cc2c428d469e43fb4ee8d38dffbf5128d20d1659dbc45edf4a855399ca730e", 319, "30391840ad14e66c53e1a5aaa03989ff059940b60c44c3b21295a93d023f2e6c7cdcf60208b7d87a7605fb5cee94630d94cad90bc6955328357fa37fea47c09f9cee759c31537187321c7d572e3554eeb90f441a9494575454dfbf8cfd86128da15de9418821ca158856eb84ff6a29a2c8380711e9e6d4955388374fcd3c1ca45b49e0679fc7157f96bc6e4f86ce20a89c12d4449b1ca7056e0b7296fc646f68f6ddbfa6a48e384d63ab68bc75fd69a2add59b8e41c4a0f753935df9a703d7df82a430798b0a67710a78061485a9d15de16f154582082459b4462485ce8a82d35ac6b9498ae40df3a23d5f00e0e86661cb02c52f677fd374c32969ec63028b5dd2c1d4bce67a6d9f79ba5e7eeb5a2763dc9fe2a05aa2ebaad36aaec2541e343a677fb4e6b6a180eff33c93744a4624f6a79f054c6c9e9c5b6928dbe7ba5fca", }, - { "e80eee72a76e6957f7cb7f68c41b92f0ad9aac6e58aa8fc272c1e7364af11c70", 108, "3c210ed15889ae938781d2cebd49d4a8007f163ffba1f7669bccdccf6ad5a1418299d5f4348f5cd03b0ba9e6999ab154e46836c3546feb395d17bcc60f23d7ba0e8efe6aa616c00b6bf552fe1cb5e28e3e7bc39dfc20c63ae3901035e91ddd110e43fe59ed744beeedb6bc1e", }, - { "f971bbae97dd8a034835269fb246867de358a889de6de13672e771d6fb4c89b7", 468, "64e9a3a99c021df8bea59368cfe1cd3b0a4aca33ffcd5cf6028d9307c0b904b8037d056a3c12803f196f74c4d360a3132452d365922b1157e5b0d76f91fb94bebfdcb4d50fa23ed5be3d3c5712219e8666debc8abcd5e6c69a542761a6cbbd1b3c0f0524875204b64d2788465f90cb19b6f6da9f8bec6d6e684196e713549ec83e47cbaeff77838ac4936b312562e2de17c970449d49d214ec2597c6d4f642e6c94a613a0c53285abccd7794a3d72241808594fb4e6e4d5d2c310ef1cdcbfd34805ca2408f554797a6cfd49d0f25ed8927f206acb127e6436e1234902489ec2e7f3058e26c0eba80341bc7ad0da8b8bd80bd1b43c9099269e3f8b68445c69b79d8cf5693d4a0d47a44f9e9114dbb33992d2ea9d3b5b86e4ea57a44a638848de4ac365bb6bb7855305ade62b07ebf0954d70b7c2fb5e6fcc154c7a36fb1756df5f20a84d35696627ebf22d44f40f805c0878ad110bc17dcd66821084ca87902e05bc0afa61161086956b85a6ea900d35c7784d4c361a43fe294e267d5762408be58962cdb4f45a9c0efd7d2335916df3acb98ccfbcf5ee39530540e5f3d3c5f3326a9a536d7bfa37aae2b143e2499b81bf0670e3a418c26c7dc82b293d9bd182dd6435670514237df88d8286e19ce93e0a0db2790", }, - { "b97fd51f4e4eaa40c7a2853010fc46be5be2f43b9520ea0c533b68f728c978a2", 214, "ced3a43193caceb269d2517f4ecb892bb7d57d7201869e28e669b0b17d1c44d286e02734e2210ea9009565832975cc6303b9b6008fe1165b99ae5f1b29962ef042ebad8b676d7433ed2fe0d0d6f4f32b2cb4c519da61552328c2caea799bb2fd907308173a1cd2b798fb0df7d2eaf2ff0be733af74f42889e211843fc80b09952ae7eb246725b91d31c1f7a5503fdf3bc9c269c76519cf2dc3225e862436b587bb74adbad88c773056cfea3bddb1f6533c01125eeae0986e5c817359912c9d0472bf8320b824ee097f82a8e05b9f53a5be7d153225de", }, - { "f0fecf766e4f7522568b3be71843cce3e5fcb10ea96b1a236c8c0a71c9ad55c9", 159, "8aca4de41275f5c4102f66266d70cff1a2d56f58df8d12061c64cb6cd8f616a5bf19c2bb3c91585c695326f561a2d0eb4eef2e202d82dcc9089e4bee82b62a199a11963cd08987d3abd5914def2cdd3c1e4748d46b654f338e3959121e869c18d5327e88090d0ba0ac6762a2b14514cc505af7499f1a22f421dbe978494f9ffe1e88f1c59228f21da5bc9fcc911d022300a443bca17258bdd6cfbbf52fde61", }, - { "5c4f16043c0084bf98499fc7dc4d674ce9c730b7135210acdbf5e41d3dcf317b", 87, "01bbc193d0ee2396a7d8267ad63f18149667b31d8f7f48c8bb0c634755febc9ef1a79e93c475f6cd137ee37d4dc243ea2fdcdc0d098844af2208337b7bbf6930e39e74e23952ac1a19b4d38b83810a10c3b069e4fafb06", }, - { "14b61fc981f7d9449b7b6a2d57eb48cc8f7896f4dced2005291b2a2f38cb4a63", 358, "cbc1709a531438d5ead32cea20a9e4ddc0101ec555ab42b2e378145013cc05a97b9e2c43c89bfa63ae5e9e9ce1fc022035c6b68f0a906ee1f53396d9dbe41cb2bc4bfeb144b005b0f40e0fec872d9c4aca9929ba3cbacd84c58ab43c26f10d345a24692bbd55a76506876768e8e32a461bf160cee953da88920d36ad4aff6eea7126aa6f44a7a6fce770ce43f0f90a20590bdaad3ffcda30ca8e3700f832c62caa5df030c16bcf74aff492466f781eb69863a80663535fc154abd7cfdd02eef1019221cf608b9780f807e507fbbf559b1dfe4e971b4d08fe45263a3c697ba90f9f71bec97e12438b4b12f6a84ab66872b888097089d76c9c2502d9ed2eece6bef8eee1d439782e218f5cc75d38f9886012cdcb4bbe6caf812e97c5a336bcceae38b1109e3243a291ce23d097aaee7d9a711de6886749a7a6d15d7e7cbc4a51b1b4da9fcf139e4a6fd7dc0bc017db624b17fc9b8f847592ed42467c25ad9fe96acbf20c0ffd18", }, - { "47ec7f3a362becbb110867995a0f066a66152603c4d433f11bf51870c67e2864", 354, "0636983353c9ea3f75256ed00b70e8b7cfc6f4e4c0ba3aa9a8da59b6e6ad9dfb5bc2c49f48cc0b4237f87dedf34b888e54ecebf1d435bcd4aab72eb4ce39e5262fb68c6f86423dac123bf59e903989eda7df4a982822d0831521403cedcfe9a5bbea648bb2e7ef8cd81442ea5abe468b3ee8b06376ef8099447255c2fdc1b73af37fe0e0b852ffbc9339868db756680db99e6e9837dbd28c39a69f229044ad7ec772524a6e01f679d25fdc2e736a2418e5dfd7c2ab1348d0f821b777c975244c6cfc2fca5c36ccae7cf1d07b190a9d17a088a1276bd096250b92f53b29b6ef88ef69d744b56fb2ec5078cc0b68a9106943ef242b466097b9e29df11eb5cb0c06c29d7917410ba1097215d6aa4dafd90adff0c3e7221b9e8832613bd9aca8bcc6b2aa7b43acedcbc11aee1b5ba56f77a210be7cf3485ee813e1126c3eeccd8419bbf22c412cad32cc0fc7a73aca4e379651caac3d13d6cf5ca05508fd2d96f3ad94e7", }, - { "73778e7f1943646a89d3c78909e0afbe584071ba5230546a39cd73e44e36d78a", 91, "6217504a26b3395855eab6ddeb79f2e3490d74b80eff343721150ee0c1c02b07186743589f93c22a03dc5ed29fb5bf592de0a089763e83e5b95f9dd524d66c8da3e04c1814e65e68b2810c1b517648aabc266ad62896c51864a7f4", }, - { "35ef6868e750cf0c1d5285992c231d93ec644670fb79cf85324067a9f77fde78", 185, "0118b7fb15f927a977e0b330b4fa351aeeec299d6ba090eb16e5114fc4a6749e5915434a123c112697390c96ea2c26dc613eb5c75f5ecfb6c419317426367e34da0ddc6d7b7612cefa70a22fea0025f5186593b22449dab71f90a49f7de7352e54e0c0bd8837e661ca2127c3313a7268cafdd5ccfbf3bdd7c974b0e7551a2d96766579ef8d2e1f376af74cd1ab62162fc2dc61a8b7ed4163c1caccf20ed73e284da2ed257ec974eee96b502acb2c60a04886465e44debb0317", }, - }; - - uint8_t hash[SHA3_256_DIGEST_LENGTH]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - keccak_256(fromhex(tests[i].data), tests[i].length, hash); - ck_assert_mem_eq(hash, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH); - } +// test vectors from +// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/0.test-sha3-256.dat +START_TEST(test_keccak_256) { + static const struct { + const char *hash; + size_t length; + const char *data; + } tests[] = { + { + "4e9e79ab7434f6c7401fb3305d55052ee829b9e46d5d05d43b59fefb32e9a619", + 293, + "a6151d4904e18ec288243028ceda30556e6c42096af7150d6a7232ca5dba52bd2192" + "e23daa5fa2bea3d4bd95efa2389cd193fcd3376e70a5c097b32c1c62c80af9d71021" + "1545f7cdddf63747420281d64529477c61e721273cfd78f8890abb4070e97baa52ac" + "8ff61c26d195fc54c077def7a3f6f79b36e046c1a83ce9674ba1983ec2fb58947de6" + "16dd797d6499b0385d5e8a213db9ad5078a8e0c940ff0cb6bf92357ea5609f778c3d" + "1fb1e7e36c35db873361e2be5c125ea7148eff4a035b0cce880a41190b2e22924ad9" + "d1b82433d9c023924f2311315f07b88bfd42850047bf3be785c4ce11c09d7e02065d" + "30f6324365f93c5e7e423a07d754eb314b5fe9db4614275be4be26af017abdc9c338" + "d01368226fe9af1fb1f815e7317bdbb30a0f36dc69", + }, + { + "c1268babc42d00c3463dc388222100f7e525a74a64665c39f112f788ddb5da42", + 376, + "9db801077952c2324e0044a4994edfb09b3edfcf669bfdd029f4bf42d5b0eab3056b" + "0bf82708ca7bfadba43c9de806b10a19d0f00c2351ef1086b6b108f306e035c6b61b" + "2e70fd7087ba848601c8a3f626a66666423717ef305a1068bfa3a1f7ffc1e5a78cb6" + "182ffc8a577ca2a821630bf900d0fbba848bdf94b77c5946771b6c3f8c02269bc772" + "ca56098f724536d96be68c284ee1d81697989d40029b8ea63ac1fd85f8b3cae8b194" + "f6834ff65a5858f9498ddbb467995eb2d49cdfc6c05d92038c6e9aaeee85f8222b37" + "84165f12a2c3df4c7a142e26dddfd831d07e22dfecc0eded48a69c8a9e1b97f1a4e0" + "efcd4edd310de0edf82af38a6e4d5ab2a19da586e61210d4f75e7a07e2201f9c8154" + "ca52a414a70d2eb2ac1c5b9a2900b4d871f62fa56f70d03b3dd3704bd644808c45a1" + "3231918ea884645b8ec054e8bab2935a66811fe590ddc119ae901dfeb54fc2a87c1e" + "0a236778baab2fa8843709c6676d3c1888ba19d75ec52d73a7d035c143179b938237" + "26b7", + }, + { + "e83b50e8c83cb676a7dd64c055f53e5110d5a4c62245ceb8f683fd87b2b3ec77", + 166, + "c070a957550b7b34113ee6543a1918d96d241f27123425db7f7b9004e047ffbe0561" + "2e7fa8c54b23c83ea427e625e97b7a28b09a70bf6d91e478eeed01d7907931c29ea8" + "6e70f2cdcfb243ccf7f24a1619abf4b5b9e6f75cbf63fc02baf4a820a9790a6b053e" + "50fd94e0ed57037cfc2bab4d95472b97d3c25f434f1cc0b1ede5ba7f15907a42a223" + "933e5e2dfcb518c3531975268c326d60fa911fbb7997eee3ba87656c4fe7", + }, + { + "8ebd2c9d4ff00e285a9b6b140bfc3cef672016f0098100e1f6f250220af7ce1a", + 224, + "b502fbdce4045e49e147eff5463d4b3f37f43461518868368e2c78008c84c2db79d1" + "2b58107034f67e7d0abfee67add0342dd23dce623f26b9156def87b1d7ac15a6e073" + "01f832610fe869ada13a2b0e3d60aa6bb81bc04487e2e800f5106b0402ee0331df74" + "5e021b5ea5e32faf1c7fc1322041d221a54191c0af19948b5f34411937182e30d5cd" + "39b5a6c959d77d92d21bb1de51f1b3411cb6eec00600429916227fb62d2c88e69576" + "f4ac8e5efcde8efa512cc80ce7fb0dfaa6c74d26e898cefe9d4f7dce232a69f2a6a9" + "477aa08366efcdfca117c89cb79eba15a23755e0", + }, + { + "db3961fdddd0c314289efed5d57363459a6700a7bd015e7a03d3e1d03f046401", + 262, + "22e203a98ba2c43d8bc3658f0a48a35766df356d6a5e98b0c7222d16d85a00b31720" + "7d4aef3fc7cabb67b9d8f5838de0b733e1fd59c31f0667e53286972d7090421ad90d" + "54db2ea40047d0d1700c86f53dbf48da532396307e68edad877dcae481848801b0a5" + "db44dbdba6fc7c63b5cd15281d57ca9e6be96f530b209b59d6127ad2bd8750f3f807" + "98f62521f0d5b42633c2f5a9aaefbed38779b7aded2338d66850b0bb0e33c48e040c" + "99f2dcee7a7ebb3d7416e1c5bf038c19d09682dab67c96dbbfad472e45980aa27d1b" + "301b15f7de4d4f549bad2501931c9d4f1a3b1692dcb4b1b834ddd4a636126702307d" + "daeec61841693b21887d56e76cc2069dafb557fd6682160f", + }, + { + "25dd3acacd6bf688c0eace8d33eb7cc550271969142deb769a05b4012f7bb722", + 122, + "99e7f6e0ed46ec866c43a1ab494998d47e9309a79fde2a629eb63bb2160a5ffd0f22" + "06de9c32dd20e9b23e57ab7422cf82971cc2873ec0e173fe93281c7b33e1c76ac792" + "23a6f435f230bdd30260c00d00986c72a399d3ba70f6e783d834bbf8a6127844def5" + "59b8b6db742b2cfd715f7ff29e7b42bf7d567beb", + }, + { + "00d747c9045c093484290afc161437f11c2ddf5f8a9fc2acae9c7ef5fcf511e5", + 440, + "50c392f97f8788377f0ab2e2aab196cb017ad157c6f9d022673d39072cc198b06622" + "a5cbd269d1516089fa59e28c3373a92bd54b2ebf1a79811c7e40fdd7bce200e80983" + "fda6e77fc44c44c1b5f87e01cef2f41e1141103f73364e9c2f25a4597e6517ef31b3" + "16300b770c69595e0fa6d011df1566a8676a88c7698562273bbfa217cc69d4b5c89a" + "8907b902f7dc14481fefc7da4a810c15a60f5641aae854d2f8cc50cbc393015560f0" + "1c94e0d0c075dbcb150ad6eba29dc747919edcaf0231dba3eb3f2b1a87e136a1f0fd" + "4b3d8ee61bad2729e9526a32884f7bcfa41e361add1b4c51dc81463528372b4ec321" + "244de0c541ba00df22b8773cdf4cf898510c867829fa6b4ff11f9627338b9686d905" + "cb7bcdf085080ab842146e0035c808be58cce97827d8926a98bd1ff7c529be3bc14f" + "68c91b2ca4d2f6fc748f56bcf14853b7f8b9aa6d388f0fd82f53fdc4bacf9d9ba10a" + "165f404cf427e199f51bf6773b7c82531e17933f6d8b8d9181e22f8921a2dbb20fc7" + "c8023a87e716e245017c399d0942934f5e085219b3f8d26a196bf8b239438b8e561c" + "28a61ff08872ecb052c5fcb19e2fdbc09565924a50ebee1461c4b414219d4257", + }, + { + "dadcde7c3603ef419d319ba3d50cf00ad57f3e81566fd11b9b6f461cbb9dcb0f", + 338, + "18e1df97abccc91e07dc7b7ffab5ee8919d5610721453176aa2089fb96d9a477e147" + "6f507fa1129f04304e960e8017ff41246cacc0153055fc4b1dc6168a74067ebb077c" + "b5aa80a9df6e8b5b821e906531159668c4c164b9e511d8724aedbe17c1f41da88094" + "17d3c30b79ea5a2e3c961f6bac5436d9af6be24a36eebcb17863fed82c0eb8962339" + "eb612d58659dddd2ea06a120b3a2d8a17050be2de367db25a5bef4290c209bdb4c16" + "c4df5a1fe1ead635169a1c35f0a56bc07bcf6ef0e4c2d8573ed7a3b58030fa268c1a" + "5974b097288f01f34d5a1087946410688016882c6c7621aad680d9a25c7a3e5dbcbb" + "07ffdb7243b91031c08a121b40785e96b7ee46770c760f84aca8f36b7c7da64d25c8" + "f73b4d88ff3acb7eeefc0b75144dffea66d2d1f6b42b905b61929ab3f38538393ba5" + "ca9d3c62c61f46fa63789cac14e4e1d8722bf03cceef6e3de91f783b0072616c", + }, + { + "d184e84a2507fc0f187b640dd5b849a366c0383d9cbdbc6fa30904f054111255", + 141, + "13b8df9c1bcfddd0aa39b3055f52e2bc36562b6677535994b173f07041d141699db4" + "2589d6091ef0e71b645b41ab57577f58c98da966562d24823158f8e1d43b54edea4e" + "61dd66fe8c59ad8405f5a0d9a3eb509a77ae3d8ae4adf926fd3d8d31c3dcccfc1408" + "14541010937024cc554e1daaee1b333a66316e7fbebb07ac8dfb134a918b9090b141" + "68012c4824", + }, + { + "20c19635364a00b151d0168fe5ae03bac6dd7d06030475b40d2e8c577a192f53", + 84, + "e1e96da4b7d8dcc2b316006503a990ea26a5b200cb7a7edfc14f5ce827f06d8d232e" + "c95b1acdc1422ffc16da11d258f0c7b378f026d64c74b2fb41df8bfd3cd30066caec" + "dc6f76c8163de9309d9fd0cf33d54a29", + }, + { + "86cc2c428d469e43fb4ee8d38dffbf5128d20d1659dbc45edf4a855399ca730e", + 319, + "30391840ad14e66c53e1a5aaa03989ff059940b60c44c3b21295a93d023f2e6c7cdc" + "f60208b7d87a7605fb5cee94630d94cad90bc6955328357fa37fea47c09f9cee759c" + "31537187321c7d572e3554eeb90f441a9494575454dfbf8cfd86128da15de9418821" + "ca158856eb84ff6a29a2c8380711e9e6d4955388374fcd3c1ca45b49e0679fc7157f" + "96bc6e4f86ce20a89c12d4449b1ca7056e0b7296fc646f68f6ddbfa6a48e384d63ab" + "68bc75fd69a2add59b8e41c4a0f753935df9a703d7df82a430798b0a67710a780614" + "85a9d15de16f154582082459b4462485ce8a82d35ac6b9498ae40df3a23d5f00e0e8" + "6661cb02c52f677fd374c32969ec63028b5dd2c1d4bce67a6d9f79ba5e7eeb5a2763" + "dc9fe2a05aa2ebaad36aaec2541e343a677fb4e6b6a180eff33c93744a4624f6a79f" + "054c6c9e9c5b6928dbe7ba5fca", + }, + { + "e80eee72a76e6957f7cb7f68c41b92f0ad9aac6e58aa8fc272c1e7364af11c70", + 108, + "3c210ed15889ae938781d2cebd49d4a8007f163ffba1f7669bccdccf6ad5a1418299" + "d5f4348f5cd03b0ba9e6999ab154e46836c3546feb395d17bcc60f23d7ba0e8efe6a" + "a616c00b6bf552fe1cb5e28e3e7bc39dfc20c63ae3901035e91ddd110e43fe59ed74" + "4beeedb6bc1e", + }, + { + "f971bbae97dd8a034835269fb246867de358a889de6de13672e771d6fb4c89b7", + 468, + "64e9a3a99c021df8bea59368cfe1cd3b0a4aca33ffcd5cf6028d9307c0b904b8037d" + "056a3c12803f196f74c4d360a3132452d365922b1157e5b0d76f91fb94bebfdcb4d5" + "0fa23ed5be3d3c5712219e8666debc8abcd5e6c69a542761a6cbbd1b3c0f05248752" + "04b64d2788465f90cb19b6f6da9f8bec6d6e684196e713549ec83e47cbaeff77838a" + "c4936b312562e2de17c970449d49d214ec2597c6d4f642e6c94a613a0c53285abccd" + "7794a3d72241808594fb4e6e4d5d2c310ef1cdcbfd34805ca2408f554797a6cfd49d" + "0f25ed8927f206acb127e6436e1234902489ec2e7f3058e26c0eba80341bc7ad0da8" + "b8bd80bd1b43c9099269e3f8b68445c69b79d8cf5693d4a0d47a44f9e9114dbb3399" + "2d2ea9d3b5b86e4ea57a44a638848de4ac365bb6bb7855305ade62b07ebf0954d70b" + "7c2fb5e6fcc154c7a36fb1756df5f20a84d35696627ebf22d44f40f805c0878ad110" + "bc17dcd66821084ca87902e05bc0afa61161086956b85a6ea900d35c7784d4c361a4" + "3fe294e267d5762408be58962cdb4f45a9c0efd7d2335916df3acb98ccfbcf5ee395" + "30540e5f3d3c5f3326a9a536d7bfa37aae2b143e2499b81bf0670e3a418c26c7dc82" + "b293d9bd182dd6435670514237df88d8286e19ce93e0a0db2790", + }, + { + "b97fd51f4e4eaa40c7a2853010fc46be5be2f43b9520ea0c533b68f728c978a2", + 214, + "ced3a43193caceb269d2517f4ecb892bb7d57d7201869e28e669b0b17d1c44d286e0" + "2734e2210ea9009565832975cc6303b9b6008fe1165b99ae5f1b29962ef042ebad8b" + "676d7433ed2fe0d0d6f4f32b2cb4c519da61552328c2caea799bb2fd907308173a1c" + "d2b798fb0df7d2eaf2ff0be733af74f42889e211843fc80b09952ae7eb246725b91d" + "31c1f7a5503fdf3bc9c269c76519cf2dc3225e862436b587bb74adbad88c773056cf" + "ea3bddb1f6533c01125eeae0986e5c817359912c9d0472bf8320b824ee097f82a8e0" + "5b9f53a5be7d153225de", + }, + { + "f0fecf766e4f7522568b3be71843cce3e5fcb10ea96b1a236c8c0a71c9ad55c9", + 159, + "8aca4de41275f5c4102f66266d70cff1a2d56f58df8d12061c64cb6cd8f616a5bf19" + "c2bb3c91585c695326f561a2d0eb4eef2e202d82dcc9089e4bee82b62a199a11963c" + "d08987d3abd5914def2cdd3c1e4748d46b654f338e3959121e869c18d5327e88090d" + "0ba0ac6762a2b14514cc505af7499f1a22f421dbe978494f9ffe1e88f1c59228f21d" + "a5bc9fcc911d022300a443bca17258bdd6cfbbf52fde61", + }, + { + "5c4f16043c0084bf98499fc7dc4d674ce9c730b7135210acdbf5e41d3dcf317b", + 87, + "01bbc193d0ee2396a7d8267ad63f18149667b31d8f7f48c8bb0c634755febc9ef1a7" + "9e93c475f6cd137ee37d4dc243ea2fdcdc0d098844af2208337b7bbf6930e39e74e2" + "3952ac1a19b4d38b83810a10c3b069e4fafb06", + }, + { + "14b61fc981f7d9449b7b6a2d57eb48cc8f7896f4dced2005291b2a2f38cb4a63", + 358, + "cbc1709a531438d5ead32cea20a9e4ddc0101ec555ab42b2e378145013cc05a97b9e" + "2c43c89bfa63ae5e9e9ce1fc022035c6b68f0a906ee1f53396d9dbe41cb2bc4bfeb1" + "44b005b0f40e0fec872d9c4aca9929ba3cbacd84c58ab43c26f10d345a24692bbd55" + "a76506876768e8e32a461bf160cee953da88920d36ad4aff6eea7126aa6f44a7a6fc" + "e770ce43f0f90a20590bdaad3ffcda30ca8e3700f832c62caa5df030c16bcf74aff4" + "92466f781eb69863a80663535fc154abd7cfdd02eef1019221cf608b9780f807e507" + "fbbf559b1dfe4e971b4d08fe45263a3c697ba90f9f71bec97e12438b4b12f6a84ab6" + "6872b888097089d76c9c2502d9ed2eece6bef8eee1d439782e218f5cc75d38f98860" + "12cdcb4bbe6caf812e97c5a336bcceae38b1109e3243a291ce23d097aaee7d9a711d" + "e6886749a7a6d15d7e7cbc4a51b1b4da9fcf139e4a6fd7dc0bc017db624b17fc9b8f" + "847592ed42467c25ad9fe96acbf20c0ffd18", + }, + { + "47ec7f3a362becbb110867995a0f066a66152603c4d433f11bf51870c67e2864", + 354, + "0636983353c9ea3f75256ed00b70e8b7cfc6f4e4c0ba3aa9a8da59b6e6ad9dfb5bc2" + "c49f48cc0b4237f87dedf34b888e54ecebf1d435bcd4aab72eb4ce39e5262fb68c6f" + "86423dac123bf59e903989eda7df4a982822d0831521403cedcfe9a5bbea648bb2e7" + "ef8cd81442ea5abe468b3ee8b06376ef8099447255c2fdc1b73af37fe0e0b852ffbc" + "9339868db756680db99e6e9837dbd28c39a69f229044ad7ec772524a6e01f679d25f" + "dc2e736a2418e5dfd7c2ab1348d0f821b777c975244c6cfc2fca5c36ccae7cf1d07b" + "190a9d17a088a1276bd096250b92f53b29b6ef88ef69d744b56fb2ec5078cc0b68a9" + "106943ef242b466097b9e29df11eb5cb0c06c29d7917410ba1097215d6aa4dafd90a" + "dff0c3e7221b9e8832613bd9aca8bcc6b2aa7b43acedcbc11aee1b5ba56f77a210be" + "7cf3485ee813e1126c3eeccd8419bbf22c412cad32cc0fc7a73aca4e379651caac3d" + "13d6cf5ca05508fd2d96f3ad94e7", + }, + { + "73778e7f1943646a89d3c78909e0afbe584071ba5230546a39cd73e44e36d78a", + 91, + "6217504a26b3395855eab6ddeb79f2e3490d74b80eff343721150ee0c1c02b071867" + "43589f93c22a03dc5ed29fb5bf592de0a089763e83e5b95f9dd524d66c8da3e04c18" + "14e65e68b2810c1b517648aabc266ad62896c51864a7f4", + }, + { + "35ef6868e750cf0c1d5285992c231d93ec644670fb79cf85324067a9f77fde78", + 185, + "0118b7fb15f927a977e0b330b4fa351aeeec299d6ba090eb16e5114fc4a6749e5915" + "434a123c112697390c96ea2c26dc613eb5c75f5ecfb6c419317426367e34da0ddc6d" + "7b7612cefa70a22fea0025f5186593b22449dab71f90a49f7de7352e54e0c0bd8837" + "e661ca2127c3313a7268cafdd5ccfbf3bdd7c974b0e7551a2d96766579ef8d2e1f37" + "6af74cd1ab62162fc2dc61a8b7ed4163c1caccf20ed73e284da2ed257ec974eee96b" + "502acb2c60a04886465e44debb0317", + }, + }; + + uint8_t hash[SHA3_256_DIGEST_LENGTH]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + keccak_256(fromhex(tests[i].data), tests[i].length, hash); + ck_assert_mem_eq(hash, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH); + } } END_TEST -// test vectors from https://raw.githubusercontent.com/monero-project/monero/master/tests/hash/tests-extra-blake.txt -START_TEST(test_blake256) -{ - struct { - const char *hash; - const char *data; - } tests[] = { - { "716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a", "", }, - { "e104256a2bc501f459d03fac96b9014f593e22d30f4de525fa680c3aa189eb4f", "cc", }, - { "8f341148be7e354fdf38b693d8c6b4e0bd57301a734f6fd35cd85b8491c3ddcd", "41fb", }, - { "bc334d1069099f10c601883ac6f3e7e9787c6aa53171f76a21923cc5ad3ab937", "1f877c", }, - { "b672a16f53982bab1e77685b71c0a5f6703ffd46a1c834be69f614bd128d658e", "c1ecfdfc", }, - { "d9134b2899057a7d8d320cc99e3e116982bc99d3c69d260a7f1ed3da8be68d99", "21f134ac57", }, - { "637923bd29a35aa3ecbbd2a50549fc32c14cf0fdcaf41c3194dd7414fd224815", "c6f50bb74e29", }, - { "70c092fd5c8c21e9ef4bbc82a5c7819e262a530a748caf285ff0cba891954f1e", "119713cc83eeef", }, - { "fdf092993edbb7a0dc7ca67f04051bbd14481639da0808947aff8bfab5abed4b", "4a4f202484512526", }, - { "6f6fc234bf35beae1a366c44c520c59ad5aa70351b5f5085e21e1fe2bfcee709", "1f66ab4185ed9b6375", }, - { "4fdaf89e2a0e78c000061b59455e0ea93a4445b440e7562c8f0cfa165c93de2e", "eed7422227613b6f53c9", }, - { "d6b780eee9c811f664393dc2c58b5a68c92b3c9fe9ceb70371d33ece63b5787e", "eaeed5cdffd89dece455f1", }, - { "d0015071d3e7ed048c764850d76406eceae52b8e2e6e5a2c3aa92ae880485b34", "5be43c90f22902e4fe8ed2d3", }, - { "9b0207902f9932f7a85c24722e93e31f6ed2c75c406509aa0f2f6d1cab046ce4", "a746273228122f381c3b46e4f1", }, - { "258020d5b04a814f2b72c1c661e1f5a5c395d9799e5eee8b8519cf7300e90cb1", "3c5871cd619c69a63b540eb5a625", }, - { "4adae3b55baa907fefc253365fdd99d8398befd0551ed6bf9a2a2784d3c304d1", "fa22874bcc068879e8ef11a69f0722", }, - { "6dd10d772f8d5b4a96c3c5d30878cd9a1073fa835bfe6d2b924fa64a1fab1711", "52a608ab21ccdd8a4457a57ede782176", }, - { "0b8741ddf2259d3af2901eb1ae354f22836442c965556f5c1eb89501191cb46a", "82e192e4043ddcd12ecf52969d0f807eed", }, - { "f48a754ca8193a82643150ab94038b5dd170b4ebd1e0751b78cfb0a98fa5076a", "75683dcb556140c522543bb6e9098b21a21e", }, - { "5698409ab856b74d9fa5e9b259dfa46001f89041752da424e56e491577b88c86", "06e4efe45035e61faaf4287b4d8d1f12ca97e5", }, - }; - - uint8_t hash[BLAKE256_DIGEST_LENGTH]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - blake256(fromhex(tests[i].data), i, hash); - ck_assert_mem_eq(hash, fromhex(tests[i].hash), BLAKE256_DIGEST_LENGTH); - } +// test vectors from +// https://raw.githubusercontent.com/monero-project/monero/master/tests/hash/tests-extra-blake.txt +START_TEST(test_blake256) { + struct { + const char *hash; + const char *data; + } tests[] = { + { + "716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a", + "", + }, + { + "e104256a2bc501f459d03fac96b9014f593e22d30f4de525fa680c3aa189eb4f", + "cc", + }, + { + "8f341148be7e354fdf38b693d8c6b4e0bd57301a734f6fd35cd85b8491c3ddcd", + "41fb", + }, + { + "bc334d1069099f10c601883ac6f3e7e9787c6aa53171f76a21923cc5ad3ab937", + "1f877c", + }, + { + "b672a16f53982bab1e77685b71c0a5f6703ffd46a1c834be69f614bd128d658e", + "c1ecfdfc", + }, + { + "d9134b2899057a7d8d320cc99e3e116982bc99d3c69d260a7f1ed3da8be68d99", + "21f134ac57", + }, + { + "637923bd29a35aa3ecbbd2a50549fc32c14cf0fdcaf41c3194dd7414fd224815", + "c6f50bb74e29", + }, + { + "70c092fd5c8c21e9ef4bbc82a5c7819e262a530a748caf285ff0cba891954f1e", + "119713cc83eeef", + }, + { + "fdf092993edbb7a0dc7ca67f04051bbd14481639da0808947aff8bfab5abed4b", + "4a4f202484512526", + }, + { + "6f6fc234bf35beae1a366c44c520c59ad5aa70351b5f5085e21e1fe2bfcee709", + "1f66ab4185ed9b6375", + }, + { + "4fdaf89e2a0e78c000061b59455e0ea93a4445b440e7562c8f0cfa165c93de2e", + "eed7422227613b6f53c9", + }, + { + "d6b780eee9c811f664393dc2c58b5a68c92b3c9fe9ceb70371d33ece63b5787e", + "eaeed5cdffd89dece455f1", + }, + { + "d0015071d3e7ed048c764850d76406eceae52b8e2e6e5a2c3aa92ae880485b34", + "5be43c90f22902e4fe8ed2d3", + }, + { + "9b0207902f9932f7a85c24722e93e31f6ed2c75c406509aa0f2f6d1cab046ce4", + "a746273228122f381c3b46e4f1", + }, + { + "258020d5b04a814f2b72c1c661e1f5a5c395d9799e5eee8b8519cf7300e90cb1", + "3c5871cd619c69a63b540eb5a625", + }, + { + "4adae3b55baa907fefc253365fdd99d8398befd0551ed6bf9a2a2784d3c304d1", + "fa22874bcc068879e8ef11a69f0722", + }, + { + "6dd10d772f8d5b4a96c3c5d30878cd9a1073fa835bfe6d2b924fa64a1fab1711", + "52a608ab21ccdd8a4457a57ede782176", + }, + { + "0b8741ddf2259d3af2901eb1ae354f22836442c965556f5c1eb89501191cb46a", + "82e192e4043ddcd12ecf52969d0f807eed", + }, + { + "f48a754ca8193a82643150ab94038b5dd170b4ebd1e0751b78cfb0a98fa5076a", + "75683dcb556140c522543bb6e9098b21a21e", + }, + { + "5698409ab856b74d9fa5e9b259dfa46001f89041752da424e56e491577b88c86", + "06e4efe45035e61faaf4287b4d8d1f12ca97e5", + }, + }; + + uint8_t hash[BLAKE256_DIGEST_LENGTH]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + blake256(fromhex(tests[i].data), i, hash); + ck_assert_mem_eq(hash, fromhex(tests[i].hash), BLAKE256_DIGEST_LENGTH); + } } END_TEST -// test vectors from https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2b-kat.txt -START_TEST(test_blake2b) -{ - uint8_t key[BLAKE2B_KEY_LENGTH]; - memcpy(key, fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), BLAKE2B_KEY_LENGTH); - - uint8_t digest[BLAKE2B_DIGEST_LENGTH]; - - blake2b_Key((uint8_t *)"", 0, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568"), BLAKE2B_DIGEST_LENGTH); - - blake2b_Key(fromhex("000102"), 3, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1"), BLAKE2B_DIGEST_LENGTH); - - blake2b_Key(fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"), 56, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2"), BLAKE2B_DIGEST_LENGTH); - - blake2b_Key(fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f"), 112, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f"), BLAKE2B_DIGEST_LENGTH); +// test vectors from +// https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2b-kat.txt +START_TEST(test_blake2b) { + uint8_t key[BLAKE2B_KEY_LENGTH]; + memcpy(key, + fromhex( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2" + "02122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + BLAKE2B_KEY_LENGTH); + + uint8_t digest[BLAKE2B_DIGEST_LENGTH]; + + blake2b_Key((uint8_t *)"", 0, key, BLAKE2B_KEY_LENGTH, digest, + BLAKE2B_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e9" + "96e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568"), + BLAKE2B_DIGEST_LENGTH); + + blake2b_Key(fromhex("000102"), 3, key, BLAKE2B_KEY_LENGTH, digest, + BLAKE2B_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e" + "364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1"), + BLAKE2B_DIGEST_LENGTH); + + blake2b_Key( + fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f3031323334353637"), + 56, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e7684" + "2d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2"), + BLAKE2B_DIGEST_LENGTH); + + blake2b_Key( + fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f"), + 112, key, BLAKE2B_KEY_LENGTH, digest, BLAKE2B_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c5" + "28fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f"), + BLAKE2B_DIGEST_LENGTH); } END_TEST -// test vectors from https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2s-kat.txt -START_TEST(test_blake2s) -{ - uint8_t key[BLAKE2S_KEY_LENGTH]; - memcpy(key, fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), BLAKE2S_KEY_LENGTH); - - uint8_t digest[BLAKE2S_DIGEST_LENGTH]; - - blake2s_Key((uint8_t *)"", 0, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49"), BLAKE2S_DIGEST_LENGTH); - - blake2s_Key(fromhex("000102"), 3, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b"), BLAKE2S_DIGEST_LENGTH); - - blake2s_Key(fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"), 56, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806"), BLAKE2S_DIGEST_LENGTH); - - blake2s_Key(fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f"), 112, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); - ck_assert_mem_eq(digest, fromhex("90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c"), BLAKE2S_DIGEST_LENGTH); +// test vectors from +// https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2s-kat.txt +START_TEST(test_blake2s) { + uint8_t key[BLAKE2S_KEY_LENGTH]; + memcpy( + key, + fromhex( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + BLAKE2S_KEY_LENGTH); + + uint8_t digest[BLAKE2S_DIGEST_LENGTH]; + + blake2s_Key((uint8_t *)"", 0, key, BLAKE2S_KEY_LENGTH, digest, + BLAKE2S_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49"), + BLAKE2S_DIGEST_LENGTH); + + blake2s_Key(fromhex("000102"), 3, key, BLAKE2S_KEY_LENGTH, digest, + BLAKE2S_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b"), + BLAKE2S_DIGEST_LENGTH); + + blake2s_Key( + fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f3031323334353637"), + 56, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806"), + BLAKE2S_DIGEST_LENGTH); + + blake2s_Key( + fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f"), + 112, key, BLAKE2S_KEY_LENGTH, digest, BLAKE2S_DIGEST_LENGTH); + ck_assert_mem_eq( + digest, + fromhex( + "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c"), + BLAKE2S_DIGEST_LENGTH); } END_TEST -START_TEST(test_pbkdf2_hmac_sha256) -{ - uint8_t k[64]; - - // test vectors from https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors - pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 1, k, 32); - ck_assert_mem_eq(k, fromhex("120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"), 32); - - pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 2, k, 32); - ck_assert_mem_eq(k, fromhex("ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"), 32); - - pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 4096, k, 32); - ck_assert_mem_eq(k, fromhex("c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"), 32); - - pbkdf2_hmac_sha256((const uint8_t *)"passwordPASSWORDpassword", 3 * 8, (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 9 * 4, 4096, k, 40); - ck_assert_mem_eq(k, fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9"), 40); - - pbkdf2_hmac_sha256((const uint8_t *)"pass\x00word", 9, (const uint8_t *)"sa\x00lt", 5, 4096, k, 16); - ck_assert_mem_eq(k, fromhex("89b69d0516f829893c696226650a8687"), 16); - - // test vector from https://tools.ietf.org/html/rfc7914.html#section-11 - pbkdf2_hmac_sha256((const uint8_t *)"passwd", 6, (const uint8_t *)"salt", 4, 1, k, 64); - ck_assert_mem_eq(k, fromhex("55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"), 64); +START_TEST(test_pbkdf2_hmac_sha256) { + uint8_t k[64]; + + // test vectors from + // https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors + pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, + 1, k, 32); + ck_assert_mem_eq( + k, + fromhex( + "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"), + 32); + + pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, + 2, k, 32); + ck_assert_mem_eq( + k, + fromhex( + "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"), + 32); + + pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4, + 4096, k, 32); + ck_assert_mem_eq( + k, + fromhex( + "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"), + 32); + + pbkdf2_hmac_sha256((const uint8_t *)"passwordPASSWORDpassword", 3 * 8, + (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", + 9 * 4, 4096, k, 40); + ck_assert_mem_eq(k, + fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4" + "e2a1fb8dd53e1c635518c7dac47e9"), + 40); + + pbkdf2_hmac_sha256((const uint8_t *)"pass\x00word", 9, + (const uint8_t *)"sa\x00lt", 5, 4096, k, 16); + ck_assert_mem_eq(k, fromhex("89b69d0516f829893c696226650a8687"), 16); + + // test vector from https://tools.ietf.org/html/rfc7914.html#section-11 + pbkdf2_hmac_sha256((const uint8_t *)"passwd", 6, (const uint8_t *)"salt", 4, + 1, k, 64); + ck_assert_mem_eq( + k, + fromhex( + "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca" + "9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"), + 64); } END_TEST -// test vectors from http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors -START_TEST(test_pbkdf2_hmac_sha512) -{ - uint8_t k[64]; - - pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 1, k, 64); - ck_assert_mem_eq(k, fromhex("867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"), 64); - - pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 2, k, 64); - ck_assert_mem_eq(k, fromhex("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"), 64); - - pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 4096, k, 64); - ck_assert_mem_eq(k, fromhex("d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"), 64); - - pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3 * 8, (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 9 * 4, 4096, k, 64); - ck_assert_mem_eq(k, fromhex("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"), 64); +// test vectors from +// http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors +START_TEST(test_pbkdf2_hmac_sha512) { + uint8_t k[64]; + + pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 1, k, + 64); + ck_assert_mem_eq( + k, + fromhex( + "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d" + "470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"), + 64); + + pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 2, k, + 64); + ck_assert_mem_eq( + k, + fromhex( + "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76c" + "ab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"), + 64); + + pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 4096, + k, 64); + ck_assert_mem_eq( + k, + fromhex( + "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f" + "30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"), + 64); + + pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3 * 8, + (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", + 9 * 4, 4096, k, 64); + ck_assert_mem_eq( + k, + fromhex( + "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b" + "59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"), + 64); } END_TEST -START_TEST(test_mnemonic) -{ - static const char *vectors[] = { - "00000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank yellow", - "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607", - "80808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage above", - "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8", - "ffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", - "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069", - "000000000000000000000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", - "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", - "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c392d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd", - "808080808080808080808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ffb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65", - "ffffffffffffffffffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", - "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528", - "0000000000000000000000000000000000000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87", - "8080808080808080808080808080808080808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad", - "77c2b00716cec7213839159e404db50d", - "jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge", - "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f672a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff", - "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", - "renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", - "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5", - "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", - "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", - "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67", - "0460ef47585604c5660618db2e6a7e7f", - "afford alter spike radar gate glance object seek swamp infant panel yellow", - "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4", - "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", - "indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", - "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba", - "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", - "clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", - "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449", - "eaebabb2383351fd31d703840b32e9e2", - "turtle front uncle idea crush write shrug there lottery flower risk shell", - "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c404f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c", - "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", - "kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", - "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79", - "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", - "exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", - "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c", - "18ab19a9f54a9274f03e5209a2ac8a91", - "board flee heavy tunnel powder denial science ski answer betray cargo cat", - "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe005831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8", - "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", - "board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", - "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9", - "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", - "beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", - "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd", - 0, - 0, - 0, - }; - - const char **a, **b, **c, *m; - uint8_t seed[64]; - - a = vectors; - b = vectors + 1; - c = vectors + 2; - while (*a && *b && *c) { - m = mnemonic_from_data(fromhex(*a), strlen(*a) / 2); - ck_assert_str_eq(m, *b); - mnemonic_to_seed(m, "TREZOR", seed, 0); - ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2); +START_TEST(test_mnemonic) { + static const char *vectors[] = { + "00000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon about", + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a698" + "7599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "yellow", + "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe12" + "96106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607", + "80808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage above", + "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12" + "eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8", + "ffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a1333257291" + "7f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069", + "000000000000000000000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon agent", + "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a" + "565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal will", + "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c39" + "2d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd", + "808080808080808080808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter always", + "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ff" + "b796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65", + "ffffffffffffffffffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "when", + "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b433" + "48d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528", + "0000000000000000000000000000000000000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon art", + "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d" + "73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal winner thank year wave sausage " + "worth title", + "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad" + "717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87", + "8080808080808080808080808080808080808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter advice cage absurd " + "amount doctor acoustic bless", + "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af" + "0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "zoo zoo zoo zoo zoo vote", + "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a" + "5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad", + "77c2b00716cec7213839159e404db50d", + "jelly better achieve collect unaware mountain thought cargo oxygen act " + "hood bridge", + "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f67" + "2a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff", + "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", + "renew stay biology evidence goat welcome casual join adapt armor " + "shuffle fault little machine walk stumble urge swap", + "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c" + "69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5", + "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", + "dignity pass list indicate nasty swamp pool script soccer toe leaf " + "photo multiply desk host tomato cradle drill spread actor shine dismiss " + "champion exotic", + "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20" + "af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67", + "0460ef47585604c5660618db2e6a7e7f", + "afford alter spike radar gate glance object seek swamp infant panel " + "yellow", + "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f" + "8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4", + "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", + "indicate race push merry suffer human cruise dwarf pole review arch " + "keep canvas theme poem divorce alter left", + "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe" + "2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba", + "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", + "clutch control vehicle tonight unusual clog visa ice plunge glimpse " + "recipe series open hour vintage deposit universe tip job dress radar " + "refuse motion taste", + "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f8" + "6360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449", + "eaebabb2383351fd31d703840b32e9e2", + "turtle front uncle idea crush write shrug there lottery flower risk " + "shell", + "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c40" + "4f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c", + "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", + "kiss carry display unusual confirm curtain upgrade antique rotate hello " + "void custom frequent obey nut hole price segment", + "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b0794" + "03485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79", + "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", + "exile ask congress lamp submit jacket era scheme attend cousin alcohol " + "catch course end lucky hurt sentence oven short ball bird grab wing top", + "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b1" + "4d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c", + "18ab19a9f54a9274f03e5209a2ac8a91", + "board flee heavy tunnel powder denial science ski answer betray cargo " + "cat", + "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe00" + "5831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8", + "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", + "board blade invite damage undo sun mimic interest slam gaze truly " + "inherit resist great inject rocket museum chief", + "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07" + "c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9", + "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", + "beyond stage sleep clip because twist token leaf atom beauty genius " + "food business side grid unable middle armed observe pair crouch tonight " + "away coconut", + "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb8" + "6a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd", + 0, + 0, + 0, + }; + + const char **a, **b, **c, *m; + uint8_t seed[64]; + + a = vectors; + b = vectors + 1; + c = vectors + 2; + while (*a && *b && *c) { + m = mnemonic_from_data(fromhex(*a), strlen(*a) / 2); + ck_assert_str_eq(m, *b); + mnemonic_to_seed(m, "TREZOR", seed, 0); + ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2); #if USE_BIP39_CACHE - // try second time to check whether caching results work - mnemonic_to_seed(m, "TREZOR", seed, 0); - ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2); + // try second time to check whether caching results work + mnemonic_to_seed(m, "TREZOR", seed, 0); + ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2); #endif - a += 3; b += 3; c += 3; - } + a += 3; + b += 3; + c += 3; + } } END_TEST -START_TEST(test_mnemonic_check) -{ - static const char *vectors_ok[] = { - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "legal winner thank year wave sausage worth useful legal winner thank yellow", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage above", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - "jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge", - "renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", - "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", - "afford alter spike radar gate glance object seek swamp infant panel yellow", - "indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", - "clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", - "turtle front uncle idea crush write shrug there lottery flower risk shell", - "kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", - "exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", - "board flee heavy tunnel powder denial science ski answer betray cargo cat", - "board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", - "beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", - 0, - }; - static const char *vectors_fail[] = { - "above abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "above winner thank year wave sausage worth useful legal winner thank yellow", - "above advice cage absurd amount doctor acoustic avoid letter advice cage above", - "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", - "above abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", - "above winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", - "above advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", - "above abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - "above winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - "above advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - "above better achieve collect unaware mountain thought cargo oxygen act hood bridge", - "above stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", - "above pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", - "above alter spike radar gate glance object seek swamp infant panel yellow", - "above race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", - "above control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", - "above front uncle idea crush write shrug there lottery flower risk shell", - "above carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", - "above ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", - "above flee heavy tunnel powder denial science ski answer betray cargo cat", - "above blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", - "above stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "winner thank year wave sausage worth useful legal winner thank yellow", - "advice cage absurd amount doctor acoustic avoid letter advice cage above", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", - "winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", - "advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - "winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - "advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - "better achieve collect unaware mountain thought cargo oxygen act hood bridge", - "stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", - "pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", - "alter spike radar gate glance object seek swamp infant panel yellow", - "race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", - "control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", - "front uncle idea crush write shrug there lottery flower risk shell", - "carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", - "ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", - "flee heavy tunnel powder denial science ski answer betray cargo cat", - "blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", - "stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", - 0, - }; - - const char **m; - int r; - m = vectors_ok; - while (*m) { - r = mnemonic_check(*m); - ck_assert_int_eq(r, 1); - m++; - } - m = vectors_fail; - while (*m) { - r = mnemonic_check(*m); - ck_assert_int_eq(r, 0); - m++; - } +START_TEST(test_mnemonic_check) { + static const char *vectors_ok[] = { + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon about", + "legal winner thank year wave sausage worth useful legal winner thank " + "yellow", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage above", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon agent", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal will", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter always", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "when", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon art", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal winner thank year wave sausage " + "worth title", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter advice cage absurd " + "amount doctor acoustic bless", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "zoo zoo zoo zoo zoo vote", + "jelly better achieve collect unaware mountain thought cargo oxygen act " + "hood bridge", + "renew stay biology evidence goat welcome casual join adapt armor " + "shuffle fault little machine walk stumble urge swap", + "dignity pass list indicate nasty swamp pool script soccer toe leaf " + "photo multiply desk host tomato cradle drill spread actor shine dismiss " + "champion exotic", + "afford alter spike radar gate glance object seek swamp infant panel " + "yellow", + "indicate race push merry suffer human cruise dwarf pole review arch " + "keep canvas theme poem divorce alter left", + "clutch control vehicle tonight unusual clog visa ice plunge glimpse " + "recipe series open hour vintage deposit universe tip job dress radar " + "refuse motion taste", + "turtle front uncle idea crush write shrug there lottery flower risk " + "shell", + "kiss carry display unusual confirm curtain upgrade antique rotate hello " + "void custom frequent obey nut hole price segment", + "exile ask congress lamp submit jacket era scheme attend cousin alcohol " + "catch course end lucky hurt sentence oven short ball bird grab wing top", + "board flee heavy tunnel powder denial science ski answer betray cargo " + "cat", + "board blade invite damage undo sun mimic interest slam gaze truly " + "inherit resist great inject rocket museum chief", + "beyond stage sleep clip because twist token leaf atom beauty genius " + "food business side grid unable middle armed observe pair crouch tonight " + "away coconut", + 0, + }; + static const char *vectors_fail[] = { + "above abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon about", + "above winner thank year wave sausage worth useful legal winner thank " + "yellow", + "above advice cage absurd amount doctor acoustic avoid letter advice " + "cage above", + "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "above abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon agent", + "above winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal will", + "above advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter always", + "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "when", + "above abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon art", + "above winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal winner thank year wave sausage " + "worth title", + "above advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter advice cage absurd " + "amount doctor acoustic bless", + "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "zoo zoo zoo zoo zoo zoo vote", + "above better achieve collect unaware mountain thought cargo oxygen act " + "hood bridge", + "above stay biology evidence goat welcome casual join adapt armor " + "shuffle fault little machine walk stumble urge swap", + "above pass list indicate nasty swamp pool script soccer toe leaf photo " + "multiply desk host tomato cradle drill spread actor shine dismiss " + "champion exotic", + "above alter spike radar gate glance object seek swamp infant panel " + "yellow", + "above race push merry suffer human cruise dwarf pole review arch keep " + "canvas theme poem divorce alter left", + "above control vehicle tonight unusual clog visa ice plunge glimpse " + "recipe series open hour vintage deposit universe tip job dress radar " + "refuse motion taste", + "above front uncle idea crush write shrug there lottery flower risk " + "shell", + "above carry display unusual confirm curtain upgrade antique rotate " + "hello void custom frequent obey nut hole price segment", + "above ask congress lamp submit jacket era scheme attend cousin alcohol " + "catch course end lucky hurt sentence oven short ball bird grab wing top", + "above flee heavy tunnel powder denial science ski answer betray cargo " + "cat", + "above blade invite damage undo sun mimic interest slam gaze truly " + "inherit resist great inject rocket museum chief", + "above stage sleep clip because twist token leaf atom beauty genius food " + "business side grid unable middle armed observe pair crouch tonight away " + "coconut", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon about", + "winner thank year wave sausage worth useful legal winner thank yellow", + "advice cage absurd amount doctor acoustic avoid letter advice cage " + "above", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon agent", + "winner thank year wave sausage worth useful legal winner thank year " + "wave sausage worth useful legal will", + "advice cage absurd amount doctor acoustic avoid letter advice cage " + "absurd amount doctor acoustic avoid letter always", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon art", + "winner thank year wave sausage worth useful legal winner thank year " + "wave sausage worth useful legal winner thank year wave sausage worth " + "title", + "advice cage absurd amount doctor acoustic avoid letter advice cage " + "absurd amount doctor acoustic avoid letter advice cage absurd amount " + "doctor acoustic bless", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "zoo zoo zoo zoo vote", + "better achieve collect unaware mountain thought cargo oxygen act hood " + "bridge", + "stay biology evidence goat welcome casual join adapt armor shuffle " + "fault little machine walk stumble urge swap", + "pass list indicate nasty swamp pool script soccer toe leaf photo " + "multiply desk host tomato cradle drill spread actor shine dismiss " + "champion exotic", + "alter spike radar gate glance object seek swamp infant panel yellow", + "race push merry suffer human cruise dwarf pole review arch keep canvas " + "theme poem divorce alter left", + "control vehicle tonight unusual clog visa ice plunge glimpse recipe " + "series open hour vintage deposit universe tip job dress radar refuse " + "motion taste", + "front uncle idea crush write shrug there lottery flower risk shell", + "carry display unusual confirm curtain upgrade antique rotate hello void " + "custom frequent obey nut hole price segment", + "ask congress lamp submit jacket era scheme attend cousin alcohol catch " + "course end lucky hurt sentence oven short ball bird grab wing top", + "flee heavy tunnel powder denial science ski answer betray cargo cat", + "blade invite damage undo sun mimic interest slam gaze truly inherit " + "resist great inject rocket museum chief", + "stage sleep clip because twist token leaf atom beauty genius food " + "business side grid unable middle armed observe pair crouch tonight away " + "coconut", + 0, + }; + + const char **m; + int r; + m = vectors_ok; + while (*m) { + r = mnemonic_check(*m); + ck_assert_int_eq(r, 1); + m++; + } + m = vectors_fail; + while (*m) { + r = mnemonic_check(*m); + ck_assert_int_eq(r, 0); + m++; + } } END_TEST -START_TEST(test_mnemonic_to_entropy) -{ - static const char *vectors[] = { - "00000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank yellow", - "80808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage above", - "ffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", - "000000000000000000000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", - "808080808080808080808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - "ffffffffffffffffffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", - "0000000000000000000000000000000000000000000000000000000000000000", - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - "8080808080808080808080808080808080808080808080808080808080808080", - "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - "77c2b00716cec7213839159e404db50d", - "jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge", - "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", - "renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", - "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", - "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", - "0460ef47585604c5660618db2e6a7e7f", - "afford alter spike radar gate glance object seek swamp infant panel yellow", - "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", - "indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", - "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", - "clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", - "eaebabb2383351fd31d703840b32e9e2", - "turtle front uncle idea crush write shrug there lottery flower risk shell", - "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", - "kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", - "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", - "exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", - "18ab19a9f54a9274f03e5209a2ac8a91", - "board flee heavy tunnel powder denial science ski answer betray cargo cat", - "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", - "board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", - "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", - "beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", - 0, - 0, - }; - - const char **a, **b; - uint8_t entropy[64]; - - a = vectors; - b = vectors + 1; - while (*a && *b) { - 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; - } +START_TEST(test_mnemonic_to_entropy) { + static const char *vectors[] = { + "00000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon about", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "yellow", + "80808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage above", + "ffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "000000000000000000000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon agent", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal will", + "808080808080808080808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter always", + "ffffffffffffffffffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "when", + "0000000000000000000000000000000000000000000000000000000000000000", + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon art", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "legal winner thank year wave sausage worth useful legal winner thank " + "year wave sausage worth useful legal winner thank year wave sausage " + "worth title", + "8080808080808080808080808080808080808080808080808080808080808080", + "letter advice cage absurd amount doctor acoustic avoid letter advice " + "cage absurd amount doctor acoustic avoid letter advice cage absurd " + "amount doctor acoustic bless", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo " + "zoo zoo zoo zoo zoo vote", + "77c2b00716cec7213839159e404db50d", + "jelly better achieve collect unaware mountain thought cargo oxygen act " + "hood bridge", + "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", + "renew stay biology evidence goat welcome casual join adapt armor " + "shuffle fault little machine walk stumble urge swap", + "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", + "dignity pass list indicate nasty swamp pool script soccer toe leaf " + "photo multiply desk host tomato cradle drill spread actor shine dismiss " + "champion exotic", + "0460ef47585604c5660618db2e6a7e7f", + "afford alter spike radar gate glance object seek swamp infant panel " + "yellow", + "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", + "indicate race push merry suffer human cruise dwarf pole review arch " + "keep canvas theme poem divorce alter left", + "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", + "clutch control vehicle tonight unusual clog visa ice plunge glimpse " + "recipe series open hour vintage deposit universe tip job dress radar " + "refuse motion taste", + "eaebabb2383351fd31d703840b32e9e2", + "turtle front uncle idea crush write shrug there lottery flower risk " + "shell", + "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", + "kiss carry display unusual confirm curtain upgrade antique rotate hello " + "void custom frequent obey nut hole price segment", + "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", + "exile ask congress lamp submit jacket era scheme attend cousin alcohol " + "catch course end lucky hurt sentence oven short ball bird grab wing top", + "18ab19a9f54a9274f03e5209a2ac8a91", + "board flee heavy tunnel powder denial science ski answer betray cargo " + "cat", + "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", + "board blade invite damage undo sun mimic interest slam gaze truly " + "inherit resist great inject rocket museum chief", + "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", + "beyond stage sleep clip because twist token leaf atom beauty genius " + "food business side grid unable middle armed observe pair crouch tonight " + "away coconut", + 0, + 0, + }; + + const char **a, **b; + uint8_t entropy[64]; + + a = vectors; + b = vectors + 1; + while (*a && *b) { + 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; + } } END_TEST -START_TEST(test_address) -{ - char address[36]; - uint8_t pub_key[65]; - - memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "139MaMHp3Vjo8o4x8N1ZLWEtovLGvBsg6s"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mhfJsQNnrXB3uuYZqvywARTDfuvyjg4RBh"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "MxiimznnxsqMfLKTQBL8Z2PoY9jKpjgkCu"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LMNJqZbe89yrPbm7JVzrcXJf28hZ1rKPaH"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FXK52G2BbzRLaQ651U12o23DU5cEQdhvU6"); - ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "34PyTHn74syS796eTgsyoLfwoBC3cwLn6p"); - - memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "19Ywfm3witp6C1yBMy4NRYHY2347WCRBfQ"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mp4txp8vXvFLy8So5Y2kFTVrt2epN6YzdP"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "N58JsQYveGueiZDgdnNwe4SSkGTAToutAY"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LTmtvyMmoZ49SpfLY73fhZMJEFRPdyohKh"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "Fdif7fnKHPVddczJF53qt45rgCL51yWN6x"); - ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "35trq6eeuHf6VL9L8pQv46x3vegHnHoTuB"); - - memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "1FWE2bn3MWhc4QidcF6AvEWpK77sSi2cAP"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mv2BKes2AY8rqXCFKp4Yk9j9B6iaMfWRLN"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "NB5bEFH2GtoAawy8t4Qk8kfj3LWvQs3MhB"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LZjBHp5sSAwfKDQnnP5UCFaaXKV9YheGxQ"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FjfwUWWQv1P9W1jkVM5eNkK8yGPq5XyZZy"); - ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "3456DYaKUWuY6RWWw8Hp5CftHLcQN29h9Y"); - - memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "1yrZb8dhdevoqpUEGi2tUccUEeiMKeLcs"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mgVoreDcWf6BaxJ5wqgQiPpwLEFRLSr8U8"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "MwZDmEdcd1kVLP4yW62c6zmXCU3mNbveDo"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LLCopoSTnHtz4eWdQQhLAVgNgT1zTi4QBK"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FW9a1Vs1G8LUFSqb7NhWLzQw8PvfwAxmxA"); - ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "3DBU4tJ9tkMR9fnmCtjW48kjvseoNLQZXd"); - - memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "194SZbL75xCCGBbKtMsyWLE5r9s2V6mhVM"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "moaPreR5tydT3J4wbvrMLFSQi9TjPCiZc6"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "N4domEq61LHkniqqABCYirNzaPG5NRU8GH"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LTHPpodwAcSFWzHV4VsGnMHr4NEJajMnKX"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FdEA1W4UeSsjhncSmTsSxr2QWK8z2xGkjc"); - - memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "1A2WfBD4BJFwYHFPc5KgktqtbdJLBuVKc4"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mpYTxEJ2zKhCKPj1KeJ4ap4DTcu39T3uzD"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "N5bsrpi36gMW4pVtsteFyQzoKrhPE7nkxK"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LUFTvPWtFxVzo5wYnDJz2uueoqfcMYiuxH"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FeCE75wRjnwUytGWVBKADQeDFnaHpJ8t3B"); - - memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "19J81hrPnQxg9UGx45ibTieCkb2ttm8CLL"); - ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "mop5JkwNbSPvvakZmegyHdrXcadbjLazww"); - ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "N4sVDMMNho4Eg1XTKu3AgEo7UpRwq3aNbn"); - ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "LTX5GvADs5CjQGy7EDhtjjhxxoQB2Uhicd"); - ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, address, sizeof(address)); ck_assert_str_eq(address, "FdTqTcamLueDb5J4wBi4vESXQkJrS54H6k"); +START_TEST(test_address) { + char address[36]; + uint8_t pub_key[65]; + + memcpy( + pub_key, + fromhex( + "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), + 33); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "139MaMHp3Vjo8o4x8N1ZLWEtovLGvBsg6s"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mhfJsQNnrXB3uuYZqvywARTDfuvyjg4RBh"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "MxiimznnxsqMfLKTQBL8Z2PoY9jKpjgkCu"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LMNJqZbe89yrPbm7JVzrcXJf28hZ1rKPaH"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FXK52G2BbzRLaQ651U12o23DU5cEQdhvU6"); + ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "34PyTHn74syS796eTgsyoLfwoBC3cwLn6p"); + + memcpy( + pub_key, + fromhex( + "025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), + 33); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "19Ywfm3witp6C1yBMy4NRYHY2347WCRBfQ"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mp4txp8vXvFLy8So5Y2kFTVrt2epN6YzdP"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "N58JsQYveGueiZDgdnNwe4SSkGTAToutAY"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LTmtvyMmoZ49SpfLY73fhZMJEFRPdyohKh"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "Fdif7fnKHPVddczJF53qt45rgCL51yWN6x"); + ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "35trq6eeuHf6VL9L8pQv46x3vegHnHoTuB"); + + memcpy( + pub_key, + fromhex( + "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), + 33); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "1FWE2bn3MWhc4QidcF6AvEWpK77sSi2cAP"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mv2BKes2AY8rqXCFKp4Yk9j9B6iaMfWRLN"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "NB5bEFH2GtoAawy8t4Qk8kfj3LWvQs3MhB"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LZjBHp5sSAwfKDQnnP5UCFaaXKV9YheGxQ"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FjfwUWWQv1P9W1jkVM5eNkK8yGPq5XyZZy"); + ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "3456DYaKUWuY6RWWw8Hp5CftHLcQN29h9Y"); + + memcpy( + pub_key, + fromhex( + "03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), + 33); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "1yrZb8dhdevoqpUEGi2tUccUEeiMKeLcs"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mgVoreDcWf6BaxJ5wqgQiPpwLEFRLSr8U8"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "MwZDmEdcd1kVLP4yW62c6zmXCU3mNbveDo"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LLCopoSTnHtz4eWdQQhLAVgNgT1zTi4QBK"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FW9a1Vs1G8LUFSqb7NhWLzQw8PvfwAxmxA"); + ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "3DBU4tJ9tkMR9fnmCtjW48kjvseoNLQZXd"); + + memcpy( + pub_key, + fromhex( + "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054" + "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), + 65); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "194SZbL75xCCGBbKtMsyWLE5r9s2V6mhVM"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "moaPreR5tydT3J4wbvrMLFSQi9TjPCiZc6"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "N4domEq61LHkniqqABCYirNzaPG5NRU8GH"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LTHPpodwAcSFWzHV4VsGnMHr4NEJajMnKX"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FdEA1W4UeSsjhncSmTsSxr2QWK8z2xGkjc"); + + memcpy( + pub_key, + fromhex( + "0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3" + "961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), + 65); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "1A2WfBD4BJFwYHFPc5KgktqtbdJLBuVKc4"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mpYTxEJ2zKhCKPj1KeJ4ap4DTcu39T3uzD"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "N5bsrpi36gMW4pVtsteFyQzoKrhPE7nkxK"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LUFTvPWtFxVzo5wYnDJz2uueoqfcMYiuxH"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FeCE75wRjnwUytGWVBKADQeDFnaHpJ8t3B"); + + memcpy( + pub_key, + fromhex( + "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2" + "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), + 65); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "19J81hrPnQxg9UGx45ibTieCkb2ttm8CLL"); + ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "mop5JkwNbSPvvakZmegyHdrXcadbjLazww"); + ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "N4sVDMMNho4Eg1XTKu3AgEo7UpRwq3aNbn"); + ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "LTX5GvADs5CjQGy7EDhtjjhxxoQB2Uhicd"); + ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC, + address, sizeof(address)); + ck_assert_str_eq(address, "FdTqTcamLueDb5J4wBi4vESXQkJrS54H6k"); } END_TEST -START_TEST(test_pubkey_validity) -{ - uint8_t pub_key[65]; - curve_point pub; - int res; - const ecdsa_curve *curve = &secp256k1; - - memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 1); - - memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf00000000"), 65); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 0); - - memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b8211111111111111111111111111111111"), 65); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 0); - - memcpy(pub_key, fromhex("00"), 1); - res = ecdsa_read_pubkey(curve, pub_key, &pub); - ck_assert_int_eq(res, 0); +START_TEST(test_pubkey_validity) { + uint8_t pub_key[65]; + curve_point pub; + int res; + const ecdsa_curve *curve = &secp256k1; + + memcpy( + pub_key, + fromhex( + "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), + 33); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), + 33); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), + 33); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), + 33); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054" + "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), + 65); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3" + "961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), + 65); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2" + "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), + 65); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 1); + + memcpy( + pub_key, + fromhex( + "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2" + "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf00000000"), + 65); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 0); + + memcpy( + pub_key, + fromhex( + "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2" + "a59ebddbdac9e87b816307a7ed5b8211111111111111111111111111111111"), + 65); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 0); + + memcpy(pub_key, fromhex("00"), 1); + res = ecdsa_read_pubkey(curve, pub_key, &pub); + ck_assert_int_eq(res, 0); } END_TEST -START_TEST(test_pubkey_uncompress) -{ - uint8_t pub_key[65]; - uint8_t uncompressed[65]; - int res; - const ecdsa_curve *curve = &secp256k1; - - memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33); - res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(uncompressed, fromhex("0426659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37b3cfbad6b39a8ce8cb3a675f53b7b57e120fe067b8035d771fd99e3eba7cf4de"), 65); - - memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33); - res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(uncompressed, fromhex("04433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7feeb4c25bcb840f720a16e8857a011e6b91e0ab2d03dbb5f9762844bb21a7b8ca7"), 65); - - memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); - res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(uncompressed, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); - - memcpy(pub_key, fromhex("00"), 1); - res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); - ck_assert_int_eq(res, 0); +START_TEST(test_pubkey_uncompress) { + uint8_t pub_key[65]; + uint8_t uncompressed[65]; + int res; + const ecdsa_curve *curve = &secp256k1; + + memcpy( + pub_key, + fromhex( + "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), + 33); + res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + uncompressed, + fromhex( + "0426659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37b3" + "cfbad6b39a8ce8cb3a675f53b7b57e120fe067b8035d771fd99e3eba7cf4de"), + 65); + + memcpy( + pub_key, + fromhex( + "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), + 33); + res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + uncompressed, + fromhex( + "04433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7feeb" + "4c25bcb840f720a16e8857a011e6b91e0ab2d03dbb5f9762844bb21a7b8ca7"), + 65); + + memcpy( + pub_key, + fromhex( + "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054" + "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), + 65); + res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + uncompressed, + fromhex( + "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054" + "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), + 65); + + memcpy(pub_key, fromhex("00"), 1); + res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed); + ck_assert_int_eq(res, 0); } END_TEST -START_TEST(test_wif) -{ - uint8_t priv_key[32]; - char wif[53]; - - memcpy(priv_key, fromhex("1111111111111111111111111111111111111111111111111111111111111111"), 32); - ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp"); - ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "cN9spWsvaxA8taS7DFMxnk1yJD2gaF2PX1npuTpy3vuZFJdwavaw"); - - memcpy(priv_key, fromhex("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"), 32); - ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN"); - ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "cV1ysqy3XUVSsPeKeugH2Utm6ZC1EyeArAgvxE73SiJvfa6AJng7"); - - memcpy(priv_key, fromhex("47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"), 32); - ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq"); - ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "cPzbT6tbXyJNWY6oKeVabbXwSvsN6qhTHV8ZrtvoDBJV5BRY1G5Q"); +START_TEST(test_wif) { + uint8_t priv_key[32]; + char wif[53]; + + memcpy( + priv_key, + fromhex( + "1111111111111111111111111111111111111111111111111111111111111111"), + 32); + ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp"); + ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "cN9spWsvaxA8taS7DFMxnk1yJD2gaF2PX1npuTpy3vuZFJdwavaw"); + + memcpy( + priv_key, + fromhex( + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"), + 32); + ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN"); + ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "cV1ysqy3XUVSsPeKeugH2Utm6ZC1EyeArAgvxE73SiJvfa6AJng7"); + + memcpy( + priv_key, + fromhex( + "47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"), + 32); + ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq"); + ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "cPzbT6tbXyJNWY6oKeVabbXwSvsN6qhTHV8ZrtvoDBJV5BRY1G5Q"); } END_TEST -START_TEST(test_address_decode) -{ - int res; - uint8_t decode[MAX_ADDR_RAW_SIZE]; - - res = ecdsa_address_decode("1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("00c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); - - res = ecdsa_address_decode("myTPjxggahXyAzuMcYp5JTkbybANyLsYBW", 111, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("6fc4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); - - res = ecdsa_address_decode("NEWoeZ6gh4CGvRgFAoAGh4hBqpxizGT6gZ", 52, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("34c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); - - res = ecdsa_address_decode("LdAPi7uXrLLmeh7u57pzkZc3KovxEDYRJq", 48, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("30c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); - - res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21); - - res = ecdsa_address_decode("mrdwvWkma2D6n9mGsbtkazedQQuoksnqJV", 111, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("6f79fbfc3f34e7745860d76137da68f362380c606c"), 21); - - res = ecdsa_address_decode("N7hMq7AmgNsQXaYARrEwybbDGei9mcPNqr", 52, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("3479fbfc3f34e7745860d76137da68f362380c606c"), 21); - - res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 48, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("3079fbfc3f34e7745860d76137da68f362380c606c"), 21); - - // invalid char - res = ecdsa_address_decode("1JwSSubhmg6i000jtyqhUYYH7bZg3Lfy1T", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); - - // invalid address - res = ecdsa_address_decode("1111Subhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); - - // invalid version - res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); +START_TEST(test_address_decode) { + int res; + uint8_t decode[MAX_ADDR_RAW_SIZE]; + + res = ecdsa_address_decode("1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("00c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); + + res = ecdsa_address_decode("myTPjxggahXyAzuMcYp5JTkbybANyLsYBW", 111, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("6fc4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); + + res = ecdsa_address_decode("NEWoeZ6gh4CGvRgFAoAGh4hBqpxizGT6gZ", 52, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("34c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); + + res = ecdsa_address_decode("LdAPi7uXrLLmeh7u57pzkZc3KovxEDYRJq", 48, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("30c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21); + + res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21); + + res = ecdsa_address_decode("mrdwvWkma2D6n9mGsbtkazedQQuoksnqJV", 111, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("6f79fbfc3f34e7745860d76137da68f362380c606c"), 21); + + res = ecdsa_address_decode("N7hMq7AmgNsQXaYARrEwybbDGei9mcPNqr", 52, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("3479fbfc3f34e7745860d76137da68f362380c606c"), 21); + + res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 48, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("3079fbfc3f34e7745860d76137da68f362380c606c"), 21); + + // invalid char + res = ecdsa_address_decode("1JwSSubhmg6i000jtyqhUYYH7bZg3Lfy1T", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); + + // invalid address + res = ecdsa_address_decode("1111Subhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); + + // invalid version + res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); } END_TEST -START_TEST(test_ecdsa_der) -{ - uint8_t sig[64], der[72]; - int res; - - memcpy(sig, fromhex("9a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b70771"), 32); - memcpy(sig + 32, fromhex("2b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede781"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 71); - ck_assert_mem_eq(der, fromhex("30450221009a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b7077102202b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede781"), 71); - - memcpy(sig, fromhex("6666666666666666666666666666666666666666666666666666666666666666"), 32); - memcpy(sig + 32, fromhex("7777777777777777777777777777777777777777777777777777777777777777"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 70); - ck_assert_mem_eq(der, fromhex("30440220666666666666666666666666666666666666666666666666666666666666666602207777777777777777777777777777777777777777777777777777777777777777"), 70); - - memcpy(sig, fromhex("6666666666666666666666666666666666666666666666666666666666666666"), 32); - memcpy(sig + 32, fromhex("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 71); - ck_assert_mem_eq(der, fromhex("304502206666666666666666666666666666666666666666666666666666666666666666022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), 71); - - memcpy(sig, fromhex("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), 32); - memcpy(sig + 32, fromhex("7777777777777777777777777777777777777777777777777777777777777777"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 71); - ck_assert_mem_eq(der, fromhex("3045022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee02207777777777777777777777777777777777777777777777777777777777777777"), 71); - - memcpy(sig, fromhex("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), 32); - memcpy(sig + 32, fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 72); - ck_assert_mem_eq(der, fromhex("3046022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee022100ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 72); - - memcpy(sig, fromhex("0000000000000000000000000000000000000000000000000000000000000066"), 32); - memcpy(sig + 32, fromhex("0000000000000000000000000000000000000000000000000000000000000077"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 8); - ck_assert_mem_eq(der, fromhex("3006020166020177"), 8); - - memcpy(sig, fromhex("0000000000000000000000000000000000000000000000000000000000000066"), 32); - memcpy(sig + 32, fromhex("00000000000000000000000000000000000000000000000000000000000000ee"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 9); - ck_assert_mem_eq(der, fromhex("3007020166020200ee"), 9); - - memcpy(sig, fromhex("00000000000000000000000000000000000000000000000000000000000000ee"), 32); - memcpy(sig + 32, fromhex("0000000000000000000000000000000000000000000000000000000000000077"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 9); - ck_assert_mem_eq(der, fromhex("3007020200ee020177"), 9); - - memcpy(sig, fromhex("00000000000000000000000000000000000000000000000000000000000000ee"), 32); - memcpy(sig + 32, fromhex("00000000000000000000000000000000000000000000000000000000000000ff"), 32); - res = ecdsa_sig_to_der(sig, der); - ck_assert_int_eq(res, 10); - ck_assert_mem_eq(der, fromhex("3008020200ee020200ff"), 10); +START_TEST(test_ecdsa_der) { + uint8_t sig[64], der[72]; + int res; + + memcpy( + sig, + fromhex( + "9a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b70771"), + 32); + memcpy( + sig + 32, + fromhex( + "2b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede781"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 71); + ck_assert_mem_eq(der, + fromhex("30450221009a0b7be0d4ed3146ee262b42202841834698bb3ee" + "39c24e7437df208b8b7077102202b79ab1e7736219387dffe8d" + "615bbdba87e11477104b867ef47afed1a5ede781"), + 71); + + memcpy( + sig, + fromhex( + "6666666666666666666666666666666666666666666666666666666666666666"), + 32); + memcpy( + sig + 32, + fromhex( + "7777777777777777777777777777777777777777777777777777777777777777"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 70); + ck_assert_mem_eq(der, + fromhex("304402206666666666666666666666666666666666666666666" + "666666666666666666666022077777777777777777777777777" + "77777777777777777777777777777777777777"), + 70); + + memcpy( + sig, + fromhex( + "6666666666666666666666666666666666666666666666666666666666666666"), + 32); + memcpy( + sig + 32, + fromhex( + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 71); + ck_assert_mem_eq(der, + fromhex("304502206666666666666666666666666666666666666666666" + "666666666666666666666022100eeeeeeeeeeeeeeeeeeeeeeee" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), + 71); + + memcpy( + sig, + fromhex( + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), + 32); + memcpy( + sig + 32, + fromhex( + "7777777777777777777777777777777777777777777777777777777777777777"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 71); + ck_assert_mem_eq(der, + fromhex("3045022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + "eeeeeeeeeeeeeeeeeeeeeee0220777777777777777777777777" + "7777777777777777777777777777777777777777"), + 71); + + memcpy( + sig, + fromhex( + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), + 32); + memcpy( + sig + 32, + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 72); + ck_assert_mem_eq(der, + fromhex("3046022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + "eeeeeeeeeeeeeeeeeeeeeee022100ffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffff"), + 72); + + memcpy( + sig, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000066"), + 32); + memcpy( + sig + 32, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000077"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 8); + ck_assert_mem_eq(der, fromhex("3006020166020177"), 8); + + memcpy( + sig, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000066"), + 32); + memcpy( + sig + 32, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000ee"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 9); + ck_assert_mem_eq(der, fromhex("3007020166020200ee"), 9); + + memcpy( + sig, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000ee"), + 32); + memcpy( + sig + 32, + fromhex( + "0000000000000000000000000000000000000000000000000000000000000077"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 9); + ck_assert_mem_eq(der, fromhex("3007020200ee020177"), 9); + + memcpy( + sig, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000ee"), + 32); + memcpy( + sig + 32, + fromhex( + "00000000000000000000000000000000000000000000000000000000000000ff"), + 32); + res = ecdsa_sig_to_der(sig, der); + ck_assert_int_eq(res, 10); + ck_assert_mem_eq(der, fromhex("3008020200ee020200ff"), 10); } END_TEST static void test_codepoints_curve(const ecdsa_curve *curve) { - int i, j; - bignum256 a; - curve_point p, p1; - for (i = 0; i < 64; i++) { - for (j = 0; j < 8; j++) { - bn_zero(&a); - a.val[(4*i)/30] = (uint32_t) (2*j+1) << (4*i % 30); - bn_normalize(&a); - // note that this is not a trivial test. We add 64 curve - // points in the table to get that particular curve point. - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point)); - bn_zero(&p.y); // test that point_multiply curve, is not a noop - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point)); - // mul 2 test. this should catch bugs - bn_lshift(&a); - bn_mod(&a, &curve->order); - p1 = curve->cp[i][j]; - point_double(curve, &p1); - // note that this is not a trivial test. We add 64 curve - // points in the table to get that particular curve point. - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &p1, sizeof(curve_point)); - bn_zero(&p.y); // test that point_multiply curve, is not a noop - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &p1, sizeof(curve_point)); - } - } + int i, j; + bignum256 a; + curve_point p, p1; + for (i = 0; i < 64; i++) { + for (j = 0; j < 8; j++) { + bn_zero(&a); + a.val[(4 * i) / 30] = (uint32_t)(2 * j + 1) << (4 * i % 30); + bn_normalize(&a); + // note that this is not a trivial test. We add 64 curve + // points in the table to get that particular curve point. + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point)); + bn_zero(&p.y); // test that point_multiply curve, is not a noop + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point)); + // mul 2 test. this should catch bugs + bn_lshift(&a); + bn_mod(&a, &curve->order); + p1 = curve->cp[i][j]; + point_double(curve, &p1); + // note that this is not a trivial test. We add 64 curve + // points in the table to get that particular curve point. + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &p1, sizeof(curve_point)); + bn_zero(&p.y); // test that point_multiply curve, is not a noop + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &p1, sizeof(curve_point)); + } + } } -START_TEST(test_codepoints_secp256k1) { test_codepoints_curve(&secp256k1); } END_TEST -START_TEST(test_codepoints_nist256p1) { test_codepoints_curve(&nist256p1); } END_TEST +START_TEST(test_codepoints_secp256k1) { test_codepoints_curve(&secp256k1); } +END_TEST +START_TEST(test_codepoints_nist256p1) { test_codepoints_curve(&nist256p1); } +END_TEST static void test_mult_border_cases_curve(const ecdsa_curve *curve) { - bignum256 a; - curve_point p; - curve_point expected; - bn_zero(&a); // a == 0 - scalar_multiply(curve, &a, &p); - ck_assert(point_is_infinity(&p)); - point_multiply(curve, &a, &p, &p); - ck_assert(point_is_infinity(&p)); - point_multiply(curve, &a, &curve->G, &p); - ck_assert(point_is_infinity(&p)); - - bn_addi(&a, 1); // a == 1 - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point)); - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point)); - - bn_subtract(&curve->order, &a, &a); // a == -1 - expected = curve->G; - bn_subtract(&curve->prime, &expected.y, &expected.y); - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); - - bn_subtract(&curve->order, &a, &a); - bn_addi(&a, 1); // a == 2 - expected = curve->G; - point_add(curve, &expected, &expected); - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); - - bn_subtract(&curve->order, &a, &a); // a == -2 - expected = curve->G; - point_add(curve, &expected, &expected); - bn_subtract(&curve->prime, &expected.y, &expected.y); - scalar_multiply(curve, &a, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); - point_multiply(curve, &a, &curve->G, &p); - ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + bignum256 a; + curve_point p; + curve_point expected; + bn_zero(&a); // a == 0 + scalar_multiply(curve, &a, &p); + ck_assert(point_is_infinity(&p)); + point_multiply(curve, &a, &p, &p); + ck_assert(point_is_infinity(&p)); + point_multiply(curve, &a, &curve->G, &p); + ck_assert(point_is_infinity(&p)); + + bn_addi(&a, 1); // a == 1 + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point)); + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point)); + + bn_subtract(&curve->order, &a, &a); // a == -1 + expected = curve->G; + bn_subtract(&curve->prime, &expected.y, &expected.y); + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + + bn_subtract(&curve->order, &a, &a); + bn_addi(&a, 1); // a == 2 + expected = curve->G; + point_add(curve, &expected, &expected); + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + + bn_subtract(&curve->order, &a, &a); // a == -2 + expected = curve->G; + point_add(curve, &expected, &expected); + bn_subtract(&curve->prime, &expected.y, &expected.y); + scalar_multiply(curve, &a, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); + point_multiply(curve, &a, &curve->G, &p); + ck_assert_mem_eq(&p, &expected, sizeof(curve_point)); } -START_TEST(test_mult_border_cases_secp256k1) { test_mult_border_cases_curve(&secp256k1); } END_TEST -START_TEST(test_mult_border_cases_nist256p1) { test_mult_border_cases_curve(&nist256p1); } END_TEST +START_TEST(test_mult_border_cases_secp256k1) { + test_mult_border_cases_curve(&secp256k1); +} +END_TEST +START_TEST(test_mult_border_cases_nist256p1) { + test_mult_border_cases_curve(&nist256p1); +} +END_TEST static void test_scalar_mult_curve(const ecdsa_curve *curve) { - int i; - // get two "random" numbers - bignum256 a = curve->G.x; - bignum256 b = curve->G.y; - curve_point p1, p2, p3; - for (i = 0; i < 1000; i++) { - /* test distributivity: (a + b)G = aG + bG */ - bn_mod(&a, &curve->order); - bn_mod(&b, &curve->order); - scalar_multiply(curve, &a, &p1); - scalar_multiply(curve, &b, &p2); - bn_addmod(&a, &b, &curve->order); - bn_mod(&a, &curve->order); - scalar_multiply(curve, &a, &p3); - point_add(curve, &p1, &p2); - ck_assert_mem_eq(&p2, &p3, sizeof(curve_point)); - // new "random" numbers - a = p3.x; - b = p3.y; - } + int i; + // get two "random" numbers + bignum256 a = curve->G.x; + bignum256 b = curve->G.y; + curve_point p1, p2, p3; + for (i = 0; i < 1000; i++) { + /* test distributivity: (a + b)G = aG + bG */ + bn_mod(&a, &curve->order); + bn_mod(&b, &curve->order); + scalar_multiply(curve, &a, &p1); + scalar_multiply(curve, &b, &p2); + bn_addmod(&a, &b, &curve->order); + bn_mod(&a, &curve->order); + scalar_multiply(curve, &a, &p3); + point_add(curve, &p1, &p2); + ck_assert_mem_eq(&p2, &p3, sizeof(curve_point)); + // new "random" numbers + a = p3.x; + b = p3.y; + } } -START_TEST(test_scalar_mult_secp256k1) { test_scalar_mult_curve(&secp256k1); } END_TEST -START_TEST(test_scalar_mult_nist256p1) { test_scalar_mult_curve(&nist256p1); } END_TEST +START_TEST(test_scalar_mult_secp256k1) { test_scalar_mult_curve(&secp256k1); } +END_TEST +START_TEST(test_scalar_mult_nist256p1) { test_scalar_mult_curve(&nist256p1); } +END_TEST static void test_point_mult_curve(const ecdsa_curve *curve) { - int i; - // get two "random" numbers and a "random" point - bignum256 a = curve->G.x; - bignum256 b = curve->G.y; - curve_point p = curve->G; - curve_point p1, p2, p3; - for (i = 0; i < 200; i++) { - /* test distributivity: (a + b)P = aP + bP */ - bn_mod(&a, &curve->order); - bn_mod(&b, &curve->order); - point_multiply(curve, &a, &p, &p1); - point_multiply(curve, &b, &p, &p2); - bn_addmod(&a, &b, &curve->order); - bn_mod(&a, &curve->order); - point_multiply(curve, &a, &p, &p3); - point_add(curve, &p1, &p2); - ck_assert_mem_eq(&p2, &p3, sizeof(curve_point)); - // new "random" numbers and a "random" point - a = p1.x; - b = p1.y; - p = p3; - } + int i; + // get two "random" numbers and a "random" point + bignum256 a = curve->G.x; + bignum256 b = curve->G.y; + curve_point p = curve->G; + curve_point p1, p2, p3; + for (i = 0; i < 200; i++) { + /* test distributivity: (a + b)P = aP + bP */ + bn_mod(&a, &curve->order); + bn_mod(&b, &curve->order); + point_multiply(curve, &a, &p, &p1); + point_multiply(curve, &b, &p, &p2); + bn_addmod(&a, &b, &curve->order); + bn_mod(&a, &curve->order); + point_multiply(curve, &a, &p, &p3); + point_add(curve, &p1, &p2); + ck_assert_mem_eq(&p2, &p3, sizeof(curve_point)); + // new "random" numbers and a "random" point + a = p1.x; + b = p1.y; + p = p3; + } } -START_TEST(test_point_mult_secp256k1) { test_point_mult_curve(&secp256k1); } END_TEST -START_TEST(test_point_mult_nist256p1) { test_point_mult_curve(&nist256p1); } END_TEST +START_TEST(test_point_mult_secp256k1) { test_point_mult_curve(&secp256k1); } +END_TEST +START_TEST(test_point_mult_nist256p1) { test_point_mult_curve(&nist256p1); } +END_TEST static void test_scalar_point_mult_curve(const ecdsa_curve *curve) { - int i; - // get two "random" numbers - bignum256 a = curve->G.x; - bignum256 b = curve->G.y; - curve_point p1, p2; - for (i = 0; i < 200; i++) { - /* test commutativity and associativity: - * a(bG) = (ab)G = b(aG) - */ - bn_mod(&a, &curve->order); - bn_mod(&b, &curve->order); - scalar_multiply(curve, &a, &p1); - point_multiply(curve, &b, &p1, &p1); - - scalar_multiply(curve, &b, &p2); - point_multiply(curve, &a, &p2, &p2); - - ck_assert_mem_eq(&p1, &p2, sizeof(curve_point)); - - bn_multiply(&a, &b, &curve->order); - bn_mod(&b, &curve->order); - scalar_multiply(curve, &b, &p2); - - ck_assert_mem_eq(&p1, &p2, sizeof(curve_point)); - - // new "random" numbers - a = p1.x; - b = p1.y; - } + int i; + // get two "random" numbers + bignum256 a = curve->G.x; + bignum256 b = curve->G.y; + curve_point p1, p2; + for (i = 0; i < 200; i++) { + /* test commutativity and associativity: + * a(bG) = (ab)G = b(aG) + */ + bn_mod(&a, &curve->order); + bn_mod(&b, &curve->order); + scalar_multiply(curve, &a, &p1); + point_multiply(curve, &b, &p1, &p1); + + scalar_multiply(curve, &b, &p2); + point_multiply(curve, &a, &p2, &p2); + + ck_assert_mem_eq(&p1, &p2, sizeof(curve_point)); + + bn_multiply(&a, &b, &curve->order); + bn_mod(&b, &curve->order); + scalar_multiply(curve, &b, &p2); + + ck_assert_mem_eq(&p1, &p2, sizeof(curve_point)); + + // new "random" numbers + a = p1.x; + b = p1.y; + } } -START_TEST(test_scalar_point_mult_secp256k1) { test_scalar_point_mult_curve(&secp256k1); } END_TEST -START_TEST(test_scalar_point_mult_nist256p1) { test_scalar_point_mult_curve(&nist256p1); } END_TEST +START_TEST(test_scalar_point_mult_secp256k1) { + test_scalar_point_mult_curve(&secp256k1); +} +END_TEST +START_TEST(test_scalar_point_mult_nist256p1) { + test_scalar_point_mult_curve(&nist256p1); +} +END_TEST START_TEST(test_ed25519) { - // test vectors from https://github.com/torproject/tor/blob/master/src/test/ed25519_vectors.inc - static const char *vectors[] = { - "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36", // secret - "c2247870536a192d142d056abefca68d6193158e7c1a59c1654c954eccaff894", // public - "d23188eac3773a316d46006fa59c095060be8b1a23582a0dd99002a82a0662bd246d8449e172e04c5f46ac0d1404cebe4aabd8a75a1457aa06cae41f3334f104", // selfsig - "fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d", - "1519a3b15816a1aafab0b213892026ebf5c0dc232c58b21088d88cb90e9b940d", - "3a785ac1201c97ee5f6f0d99323960d5f264c7825e61aa7cc81262f15bef75eb4fa5723add9b9d45b12311b6d403eb3ac79ff8e4e631fc3cd51e4ad2185b200b", - "67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e", - "081faa81992e360ea22c06af1aba096e7a73f1c665bc8b3e4e531c46455fd1dd", - "cf431fd0416bfbd20c9d95ef9b723e2acddffb33900edc72195dea95965d52d888d30b7b8a677c0bd8ae1417b1e1a0ec6700deadd5d8b54b6689275e04a04509", - "d51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6", - "73cfa1189a723aad7966137cbffa35140bb40d7e16eae4c40b79b5f0360dd65a", - "2375380cd72d1a6c642aeddff862be8a5804b916acb72c02d9ed052c1561881aa658a5af856fcd6d43113e42f698cd6687c99efeef7f2ce045824440d26c5d00", - "5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433", - "66c1a77104d86461b6f98f73acf3cd229c80624495d2d74d6fda1e940080a96b", - "2385a472f599ca965bbe4d610e391cdeabeba9c336694b0d6249e551458280be122c2441dd9746a81bbfb9cd619364bab0df37ff4ceb7aefd24469c39d3bc508", - "eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86", - "d21c294db0e64cb2d8976625786ede1d9754186ae8197a64d72f68c792eecc19", - "e500cd0b8cfff35442f88008d894f3a2fa26ef7d3a0ca5714ae0d3e2d40caae58ba7cdf69dd126994dad6be536fcda846d89dd8138d1683cc144c8853dce7607", - "4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d", - "c4d58b4cf85a348ff3d410dd936fa460c4f18da962c01b1963792b9dcc8a6ea6", - "d187b9e334b0050154de10bf69b3e4208a584e1a65015ec28b14bcc252cf84b8baa9c94867daa60f2a82d09ba9652d41e8dde292b624afc8d2c26441b95e3c0e", - "c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b", - "95126f14d86494020665face03f2d42ee2b312a85bc729903eb17522954a1c4a", - "815213640a643d198bd056e02bba74e1c8d2d931643e84497adf3347eb485079c9afe0afce9284cdc084946b561abbb214f1304ca11228ff82702185cf28f60d", - 0, - 0, - 0, - }; - const char **ssk, **spk, **ssig; - ssk = vectors; - spk = vectors + 1; - ssig = vectors + 2; - ed25519_public_key pk; - ed25519_secret_key sk; - ed25519_signature sig; - while (*ssk && *spk && *ssig) { - memcpy(sk, fromhex(*ssk), 32); - MARK_SECRET_DATA(sk, sizeof(sk)); - - ed25519_publickey(sk, pk); - UNMARK_SECRET_DATA(pk, sizeof(pk)); - ck_assert_mem_eq(pk, fromhex(*spk), 32); - - ed25519_sign(pk, 32, sk, pk, sig); - UNMARK_SECRET_DATA(sig, sizeof(sig)); - ck_assert_mem_eq(sig, fromhex(*ssig), 64); - - ssk += 3; - spk += 3; - ssig += 3; - - UNMARK_SECRET_DATA(sk, sizeof(sk)); - } + // test vectors from + // https://github.com/torproject/tor/blob/master/src/test/ed25519_vectors.inc + static const char *vectors[] = { + "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d3" + "6", // secret + "c2247870536a192d142d056abefca68d6193158e7c1a59c1654c954eccaff89" + "4", // public + "d23188eac3773a316d46006fa59c095060be8b1a23582a0dd99002a82a0662bd" + "246d8449e172e04c5f46ac0d1404cebe4aabd8a75a1457aa06cae41f3334f10" + "4", // selfsig + "fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128" + "d", + "1519a3b15816a1aafab0b213892026ebf5c0dc232c58b21088d88cb90e9b940" + "d", + "3a785ac1201c97ee5f6f0d99323960d5f264c7825e61aa7cc81262f15bef75eb" + "4fa5723add9b9d45b12311b6d403eb3ac79ff8e4e631fc3cd51e4ad2185b200" + "b", + "67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0" + "e", + "081faa81992e360ea22c06af1aba096e7a73f1c665bc8b3e4e531c46455fd1d" + "d", + "cf431fd0416bfbd20c9d95ef9b723e2acddffb33900edc72195dea95965d52d8" + "88d30b7b8a677c0bd8ae1417b1e1a0ec6700deadd5d8b54b6689275e04a0450" + "9", + "d51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a" + "6", + "73cfa1189a723aad7966137cbffa35140bb40d7e16eae4c40b79b5f0360dd65" + "a", + "2375380cd72d1a6c642aeddff862be8a5804b916acb72c02d9ed052c1561881a" + "a658a5af856fcd6d43113e42f698cd6687c99efeef7f2ce045824440d26c5d0" + "0", + "5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb43" + "3", + "66c1a77104d86461b6f98f73acf3cd229c80624495d2d74d6fda1e940080a96" + "b", + "2385a472f599ca965bbe4d610e391cdeabeba9c336694b0d6249e551458280be" + "122c2441dd9746a81bbfb9cd619364bab0df37ff4ceb7aefd24469c39d3bc50" + "8", + "eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b8" + "6", + "d21c294db0e64cb2d8976625786ede1d9754186ae8197a64d72f68c792eecc1" + "9", + "e500cd0b8cfff35442f88008d894f3a2fa26ef7d3a0ca5714ae0d3e2d40caae5" + "8ba7cdf69dd126994dad6be536fcda846d89dd8138d1683cc144c8853dce760" + "7", + "4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533" + "d", + "c4d58b4cf85a348ff3d410dd936fa460c4f18da962c01b1963792b9dcc8a6ea" + "6", + "d187b9e334b0050154de10bf69b3e4208a584e1a65015ec28b14bcc252cf84b8" + "baa9c94867daa60f2a82d09ba9652d41e8dde292b624afc8d2c26441b95e3c0" + "e", + "c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290" + "b", + "95126f14d86494020665face03f2d42ee2b312a85bc729903eb17522954a1c4" + "a", + "815213640a643d198bd056e02bba74e1c8d2d931643e84497adf3347eb485079" + "c9afe0afce9284cdc084946b561abbb214f1304ca11228ff82702185cf28f60" + "d", + 0, + 0, + 0, + }; + const char **ssk, **spk, **ssig; + ssk = vectors; + spk = vectors + 1; + ssig = vectors + 2; + ed25519_public_key pk; + ed25519_secret_key sk; + ed25519_signature sig; + while (*ssk && *spk && *ssig) { + memcpy(sk, fromhex(*ssk), 32); + MARK_SECRET_DATA(sk, sizeof(sk)); + + ed25519_publickey(sk, pk); + UNMARK_SECRET_DATA(pk, sizeof(pk)); + ck_assert_mem_eq(pk, fromhex(*spk), 32); + + ed25519_sign(pk, 32, sk, pk, sig); + UNMARK_SECRET_DATA(sig, sizeof(sig)); + ck_assert_mem_eq(sig, fromhex(*ssig), 64); + + ssk += 3; + spk += 3; + ssig += 3; + + UNMARK_SECRET_DATA(sk, sizeof(sk)); + } } END_TEST -// test vectors from https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/2.test-sign.dat -START_TEST(test_ed25519_keccak) -{ - static const struct { - const char *private_key; - const char *public_key; - const char *signature; - size_t length; - const char *data; - } tests[] = { - { "abf4cf55a2b3f742d7543d9cc17f50447b969e6e06f5ea9195d428ab12b7318d", "8a558c728c21c126181e5e654b404a45b4f0137ce88177435a69978cc6bec1f4", "d9cec0cc0e3465fab229f8e1d6db68ab9cc99a18cb0435f70deb6100948576cd5c0aa1feb550bdd8693ef81eb10a556a622db1f9301986827b96716a7134230c", 41, "8ce03cd60514233b86789729102ea09e867fc6d964dea8c2018ef7d0a2e0e24bf7e348e917116690b9", }, - { "6aa6dad25d3acb3385d5643293133936cdddd7f7e11818771db1ff2f9d3f9215", "bbc8cbb43dda3ecf70a555981a351a064493f09658fffe884c6fab2a69c845c6", "98bca58b075d1748f1c3a7ae18f9341bc18e90d1beb8499e8a654c65d8a0b4fbd2e084661088d1e5069187a2811996ae31f59463668ef0f8cb0ac46a726e7902", 49, "e4a92208a6fc52282b620699191ee6fb9cf04daf48b48fd542c5e43daa9897763a199aaa4b6f10546109f47ac3564fade0", }, - { "8e32bc030a4c53de782ec75ba7d5e25e64a2a072a56e5170b77a4924ef3c32a9", "72d0e65f1ede79c4af0ba7ec14204e10f0f7ea09f2bc43259cd60ea8c3a087e2", "ef257d6e73706bb04878875c58aa385385bf439f7040ea8297f7798a0ea30c1c5eff5ddc05443f801849c68e98111ae65d088e726d1d9b7eeca2eb93b677860c", 40, "13ed795344c4448a3b256f23665336645a853c5c44dbff6db1b9224b5303b6447fbf8240a2249c55", }, - { "c83ce30fcb5b81a51ba58ff827ccbc0142d61c13e2ed39e78e876605da16d8d7", "3ec8923f9ea5ea14f8aaa7e7c2784653ed8c7de44e352ef9fc1dee81fc3fa1a3", "0c684e71b35fed4d92b222fc60561db34e0d8afe44bdd958aaf4ee965911bef5991236f3e1bced59fc44030693bcac37f34d29e5ae946669dc326e706e81b804", 49, "a2704638434e9f7340f22d08019c4c8e3dbee0df8dd4454a1d70844de11694f4c8ca67fdcb08fed0cec9abb2112b5e5f89", }, - { "2da2a0aae0f37235957b51d15843edde348a559692d8fa87b94848459899fc27", "d73d0b14a9754eec825fcb25ef1cfa9ae3b1370074eda53fc64c22334a26c254", "6f17f7b21ef9d6907a7ab104559f77d5a2532b557d95edffd6d88c073d87ac00fc838fc0d05282a0280368092a4bd67e95c20f3e14580be28d8b351968c65e03", 40, "d2488e854dbcdfdb2c9d16c8c0b2fdbc0abb6bac991bfe2b14d359a6bc99d66c00fd60d731ae06d0", }, - { "0c066261fb1b18ebf2a9bcdeda81eb47d5a3745438b3d0b9d19b75885ad0a154", "2e5773f0e725024bc0359ce93a44e15d6507e7b160b6c592200385fee4a269cf", "13b5d2dd1b04f62cc2ec1544fed256423684f2dbca4538ceddda1d15c59dc7196c87840ea303ea30f4f6914a6ec9167841980c1d717f47fd641225068de88507", 41, "f15cb706e29fcfbcb324e38cbac62bb355deddb845c142e970f0c029ea4d05e59fd6adf85573cf1775", }, - { "ef3d8e22a592f04c3a31aa736e10901757a821d053f1a49a525b4ec91eacdee3", "72a2b4910a502b30e13a96aba643c59c79328c1ba1462be6f254e817ef157fee", "95f2437a0210d2d2f125a3c377ed666c0d596cd104185e70204924a182a11a6eb3bdba4395bbfc3f4e827d38805752657ee52d1ce0f17e70f59bfd4999282509", 50, "6c3e4387345740b8d62cf0c9dec48f98c292539431b2b54020d8072d9cb55f0197f7d99ff066afcf9e41ea8b7aea78eb082d", }, - { "f7fb79743e9ba957d2a4f1bd95ceb1299552abecaf758bf840d2dc2c09f3e3cb", "8b7d7531280f76a8abac8293d87508e3953894087112ae01b6ad32485d4e9b67", "c868ecf31cee783fe8799ac7e6a662431c822967351d8b79687f4ddf608f79a080c4ff9eed4fdee8c99fe1be905f734cae2a172f1cfdb00771625c0695a5260e", 42, "55d8e60c307ee533b1af9ff677a2de40a6eace722bcc9eb5d79907b420e533bc06db674dafbd9f43d672", }, - { "8cc9a2469a77fad18b44b871b2b6932cd354641d2d1e84403f746c4fff829791", "aed5da202d4983dac560faf6704dc76ac111616318570e244043e82ed1bbcd2b", "aee9616db4135150818eaffa3e4503c2d7e9e834847a4c7d0a8856e952761d361a657104d36950c9b75770ded00d56a96e06f383fa2406bc935dcf51f272300e", 42, "d9b8be2f71b83261304e333d6e35563dc3c36c2eb5a23e1461b6e95aa7c6f381f9c3bd39deaa1b6df2f9", }, - { "a247abbef0c1affbf021d1aff128888550532fc0edd77bc39f6ef5312317ec47", "98ededbad1e5ad7a0d5a0cf4fcd7a794eb5c6900a65e7e921884a636f19b131d", "f8cc02933851432f0c5df0b70f2067f740ccb72de7d6fa1e9a9b0d6de1402b9c6c525fd848e45aaaac1423b52880ec3474a2f64b38db6fc8e008d95a310e6e0c", 47, "4a5f07eb713932532fc3132c96efdc45862fe7a954c1d2ae4640afdf4728fb58c65e8a4ebfe0d53d5797d5146442b9", }, - { "163d69079ddad1f16695c47d81c3b72f869b2fdd50e6e47113db6c85051a6ede", "93fe602642ee5773f4aaf6a3bc21e98e354035225353f419e78e43c3ec36c88a", "da747fa2cb47aae1effc1e4cfde0e39fa79937948592a712a7665bf948b8311e7f3f80f966301679520d5c2afa3eadd60e061f0d264887500d8d03a17e10fd02", 41, "65fe5c1a0214a59644892e5ac4216f09fbb4e191b89bfb63d6540177d25ef9e3714850b8453bd6b2b6", }, - { "7b061bf90eb760971b9ec66a96fd6609635ca4b531f33e3c126b9ae6fdb3d491", "cb392ebb6912df4111efeeb1278160daf9da396e9291b83979a5ac479f7276d2", "f6eebe86f7ea672e0707ee518e1798d6fbd118c11b2aa30be07d10e3882e3721f2030f9f044b77c3a7a9a2f1feba7e7ce75d1f7f3807a96a764fded35d341d02", 45, "a17f5ce39b9ba7b7cf1147e515d6aa84b22fd0e2d8323a91367198fc6c3aff04ebb21fc2bdbe7bc0364e8040a9", }, - { "c9f8ccbf761cec00ab236c52651e76b5f46d90f8936d44d40561ed5c277104de", "a3192641e343b669ffd43677c2e5cd4efaed174e876141f1d773bd6cfe30d875", "d44f884ec9eae2e99e74194b5acc769b7aa369aaad359e92ba6ff0fe629af2a9a7156c19b720e7de8c7f03c039563f160948073cab6f99b26a56a8bb1023ba08", 47, "3d7e33b0ecead8269966e9dcd192b73eb8a12573fc8a5fdfbe5753541026ef2e49f5280cba9bc2515a049b3a1c1b49", }, - { "ebfa409ac6f987df476858dd35310879bf564eeb62984a52115d2e6c24590124", "7bb1601fe7215f3f4da9c8ab5e804dc58f57ba41b03223f57ec80d9c9a2dd0e1", "f3e7c1abfcc9f35556cb1e4c5a2b34445177ac188312d9148f1d1d8467ea8411fa3cda031d023034e45bbe407ef7d1b937bfb098266138857d35cb4efe407306", 52, "0c37564f718eda683aa6f3e9ab2487620b1a8b5c8f20adb3b2d7550af0d635371e531f27cebe76a2abcc96de0875bdae987a45ac", }, - { "f993f61902b7da332f2bb001baa7accaf764d824eb0cd073315f7ec43158b8fb", "55fc8e0da1b454cab6ddefb235311db2b01504bf9ac3f71c7e3f3d0d1f09f80b", "178bd147673c0ca330e45da63cbd1f1811906bd5284bb44e4bb00f7d7163d1f396975610b6f71c1ae4686466fad4c5e7bb9685099e21ca4f1a45bb3fcf56ae0c", 42, "b7dd613bc9c364d9eeb9a52636d72bc881dfc81a836b6537bbb928bff5b73831358947ea9edea1570550", }, - { "05188c09c31b4bb63f0d49b47ccc1654c2aba907b8c6c0a82ee403e950169167", "e096d808dfabe8e44eb74950199dadcd586f9de6b141a0ce85ab94b3d97866eb", "669491c8eb7cedbbc0252f3eafb048b39a2a37f60ac87837777c72c879ac8b726c39e10060750c2f539102999b71889746111bc5f71ec8c158cc81cf566aef03", 44, "bb8e22469d1c7f1d5418563e8781f69eccb56678bd36d8919f358c2778562ff6b50de916c12d44f1a778a7f3", }, - { "eabe57e1a916ebbffa4ba7abc7f23e83d4deb1338816cc1784d7495d92e98d0b", "3aad275642f48a46ed1032f3de9f4053e0fd35cf217e065d2e4579c3683932f7", "b2e9dac2c83942ca374f29c8eff5a30c377c3db3c1c645e593e524d17484e7705b11f79573e2d63495fc3ce3bf216a209f0cb7bea477ae0f8bd297f193af8805", 44, "3f2c2d6682ee597f2a92d7e560ac53d5623550311a4939d68adfb904045ed8d215a9fdb757a2368ea4d89f5f", }, - { "fef7b893b4b517fab68ca12d36b603bc00826bf3c9b31a05149642ae10bb3f55", "b3fb891868708dfa5da5b9b5234058767ab42c117f12c3228c02a1976d1c0f83", "6243e289314b7c7587802909a9be6173a916b36f9de1e164954dfe5d1ebd57c869a79552d770e13b51855502be6b15e7be42a3675298a81284df58e609b06503", 47, "38c69f884045cdbeebe4478fdbd1ccc6cf00a08d8a3120c74e7167d3a2e26a67a043b8e5bd198f7b0ce0358cef7cf9", }, - { "16228bec9b724300a37e88e535fc1c58548d34d7148b57c226f2b3af974c1822", "3c92423a8360c9a5d9a093730d72831bec4601dcadfe84de19fc8c8f91fc3d4b", "6aebfa9a4294ec888d54bcb517fcb6821e4c16d2708a2afe701f431a28149ff4f139f9d16a52a63f1f91baf4c8dea37710c73f25c263a8035a39cc118ad0280f", 44, "a3d7b122cd4431b396b20d8cc46cc73ed4a5253a44a76fc83db62cdc845a2bf7081d069a857955a161cccf84", }, - { "2dc3f5f0a0bc32c6632534e1e8f27e59cbe0bf7617d31aff98098e974c828be7", "b998a416edc28ded988dcacb1caf2bd96c87354b0d1eeccb6980e54a3104f21f", "76a2ddfc4bea48c47e0c82bcbfee28a37c61ec626af39a468e643e0ef9f6533056a5a0b44e64d614ba3c641a40e5b003a99463445ae2c3c8e1e9882092d74b07", 42, "bdae276d738b9758ea3d322b54fd12fe82b767e8d817d8ef3d41f78705748e28d15e9c506962a1b85901", }, - }; - - ed25519_secret_key private_key; - ed25519_public_key public_key; - ed25519_signature signature; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - nem_private_key(tests[i].private_key, private_key); - MARK_SECRET_DATA(private_key, sizeof(private_key)); - - ed25519_publickey_keccak(private_key, public_key); - UNMARK_SECRET_DATA(public_key, sizeof(public_key)); - ck_assert_mem_eq(public_key, fromhex(tests[i].public_key), 32); - - ed25519_sign_keccak(fromhex(tests[i].data), tests[i].length, private_key, public_key, signature); - UNMARK_SECRET_DATA(signature, sizeof(signature)); - ck_assert_mem_eq(signature, fromhex(tests[i].signature), 64); - - UNMARK_SECRET_DATA(private_key, sizeof(private_key)); - } +// test vectors from +// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/2.test-sign.dat +START_TEST(test_ed25519_keccak) { + static const struct { + const char *private_key; + const char *public_key; + const char *signature; + size_t length; + const char *data; + } tests[] = { + { + "abf4cf55a2b3f742d7543d9cc17f50447b969e6e06f5ea9195d428ab12b7318d", + "8a558c728c21c126181e5e654b404a45b4f0137ce88177435a69978cc6bec1f4", + "d9cec0cc0e3465fab229f8e1d6db68ab9cc99a18cb0435f70deb6100948576cd5c0a" + "a1feb550bdd8693ef81eb10a556a622db1f9301986827b96716a7134230c", + 41, + "8ce03cd60514233b86789729102ea09e867fc6d964dea8c2018ef7d0a2e0e24bf7e3" + "48e917116690b9", + }, + { + "6aa6dad25d3acb3385d5643293133936cdddd7f7e11818771db1ff2f9d3f9215", + "bbc8cbb43dda3ecf70a555981a351a064493f09658fffe884c6fab2a69c845c6", + "98bca58b075d1748f1c3a7ae18f9341bc18e90d1beb8499e8a654c65d8a0b4fbd2e0" + "84661088d1e5069187a2811996ae31f59463668ef0f8cb0ac46a726e7902", + 49, + "e4a92208a6fc52282b620699191ee6fb9cf04daf48b48fd542c5e43daa9897763a19" + "9aaa4b6f10546109f47ac3564fade0", + }, + { + "8e32bc030a4c53de782ec75ba7d5e25e64a2a072a56e5170b77a4924ef3c32a9", + "72d0e65f1ede79c4af0ba7ec14204e10f0f7ea09f2bc43259cd60ea8c3a087e2", + "ef257d6e73706bb04878875c58aa385385bf439f7040ea8297f7798a0ea30c1c5eff" + "5ddc05443f801849c68e98111ae65d088e726d1d9b7eeca2eb93b677860c", + 40, + "13ed795344c4448a3b256f23665336645a853c5c44dbff6db1b9224b5303b6447fbf" + "8240a2249c55", + }, + { + "c83ce30fcb5b81a51ba58ff827ccbc0142d61c13e2ed39e78e876605da16d8d7", + "3ec8923f9ea5ea14f8aaa7e7c2784653ed8c7de44e352ef9fc1dee81fc3fa1a3", + "0c684e71b35fed4d92b222fc60561db34e0d8afe44bdd958aaf4ee965911bef59912" + "36f3e1bced59fc44030693bcac37f34d29e5ae946669dc326e706e81b804", + 49, + "a2704638434e9f7340f22d08019c4c8e3dbee0df8dd4454a1d70844de11694f4c8ca" + "67fdcb08fed0cec9abb2112b5e5f89", + }, + { + "2da2a0aae0f37235957b51d15843edde348a559692d8fa87b94848459899fc27", + "d73d0b14a9754eec825fcb25ef1cfa9ae3b1370074eda53fc64c22334a26c254", + "6f17f7b21ef9d6907a7ab104559f77d5a2532b557d95edffd6d88c073d87ac00fc83" + "8fc0d05282a0280368092a4bd67e95c20f3e14580be28d8b351968c65e03", + 40, + "d2488e854dbcdfdb2c9d16c8c0b2fdbc0abb6bac991bfe2b14d359a6bc99d66c00fd" + "60d731ae06d0", + }, + { + "0c066261fb1b18ebf2a9bcdeda81eb47d5a3745438b3d0b9d19b75885ad0a154", + "2e5773f0e725024bc0359ce93a44e15d6507e7b160b6c592200385fee4a269cf", + "13b5d2dd1b04f62cc2ec1544fed256423684f2dbca4538ceddda1d15c59dc7196c87" + "840ea303ea30f4f6914a6ec9167841980c1d717f47fd641225068de88507", + 41, + "f15cb706e29fcfbcb324e38cbac62bb355deddb845c142e970f0c029ea4d05e59fd6" + "adf85573cf1775", + }, + { + "ef3d8e22a592f04c3a31aa736e10901757a821d053f1a49a525b4ec91eacdee3", + "72a2b4910a502b30e13a96aba643c59c79328c1ba1462be6f254e817ef157fee", + "95f2437a0210d2d2f125a3c377ed666c0d596cd104185e70204924a182a11a6eb3bd" + "ba4395bbfc3f4e827d38805752657ee52d1ce0f17e70f59bfd4999282509", + 50, + "6c3e4387345740b8d62cf0c9dec48f98c292539431b2b54020d8072d9cb55f0197f7" + "d99ff066afcf9e41ea8b7aea78eb082d", + }, + { + "f7fb79743e9ba957d2a4f1bd95ceb1299552abecaf758bf840d2dc2c09f3e3cb", + "8b7d7531280f76a8abac8293d87508e3953894087112ae01b6ad32485d4e9b67", + "c868ecf31cee783fe8799ac7e6a662431c822967351d8b79687f4ddf608f79a080c4" + "ff9eed4fdee8c99fe1be905f734cae2a172f1cfdb00771625c0695a5260e", + 42, + "55d8e60c307ee533b1af9ff677a2de40a6eace722bcc9eb5d79907b420e533bc06db" + "674dafbd9f43d672", + }, + { + "8cc9a2469a77fad18b44b871b2b6932cd354641d2d1e84403f746c4fff829791", + "aed5da202d4983dac560faf6704dc76ac111616318570e244043e82ed1bbcd2b", + "aee9616db4135150818eaffa3e4503c2d7e9e834847a4c7d0a8856e952761d361a65" + "7104d36950c9b75770ded00d56a96e06f383fa2406bc935dcf51f272300e", + 42, + "d9b8be2f71b83261304e333d6e35563dc3c36c2eb5a23e1461b6e95aa7c6f381f9c3" + "bd39deaa1b6df2f9", + }, + { + "a247abbef0c1affbf021d1aff128888550532fc0edd77bc39f6ef5312317ec47", + "98ededbad1e5ad7a0d5a0cf4fcd7a794eb5c6900a65e7e921884a636f19b131d", + "f8cc02933851432f0c5df0b70f2067f740ccb72de7d6fa1e9a9b0d6de1402b9c6c52" + "5fd848e45aaaac1423b52880ec3474a2f64b38db6fc8e008d95a310e6e0c", + 47, + "4a5f07eb713932532fc3132c96efdc45862fe7a954c1d2ae4640afdf4728fb58c65e" + "8a4ebfe0d53d5797d5146442b9", + }, + { + "163d69079ddad1f16695c47d81c3b72f869b2fdd50e6e47113db6c85051a6ede", + "93fe602642ee5773f4aaf6a3bc21e98e354035225353f419e78e43c3ec36c88a", + "da747fa2cb47aae1effc1e4cfde0e39fa79937948592a712a7665bf948b8311e7f3f" + "80f966301679520d5c2afa3eadd60e061f0d264887500d8d03a17e10fd02", + 41, + "65fe5c1a0214a59644892e5ac4216f09fbb4e191b89bfb63d6540177d25ef9e37148" + "50b8453bd6b2b6", + }, + { + "7b061bf90eb760971b9ec66a96fd6609635ca4b531f33e3c126b9ae6fdb3d491", + "cb392ebb6912df4111efeeb1278160daf9da396e9291b83979a5ac479f7276d2", + "f6eebe86f7ea672e0707ee518e1798d6fbd118c11b2aa30be07d10e3882e3721f203" + "0f9f044b77c3a7a9a2f1feba7e7ce75d1f7f3807a96a764fded35d341d02", + 45, + "a17f5ce39b9ba7b7cf1147e515d6aa84b22fd0e2d8323a91367198fc6c3aff04ebb2" + "1fc2bdbe7bc0364e8040a9", + }, + { + "c9f8ccbf761cec00ab236c52651e76b5f46d90f8936d44d40561ed5c277104de", + "a3192641e343b669ffd43677c2e5cd4efaed174e876141f1d773bd6cfe30d875", + "d44f884ec9eae2e99e74194b5acc769b7aa369aaad359e92ba6ff0fe629af2a9a715" + "6c19b720e7de8c7f03c039563f160948073cab6f99b26a56a8bb1023ba08", + 47, + "3d7e33b0ecead8269966e9dcd192b73eb8a12573fc8a5fdfbe5753541026ef2e49f5" + "280cba9bc2515a049b3a1c1b49", + }, + { + "ebfa409ac6f987df476858dd35310879bf564eeb62984a52115d2e6c24590124", + "7bb1601fe7215f3f4da9c8ab5e804dc58f57ba41b03223f57ec80d9c9a2dd0e1", + "f3e7c1abfcc9f35556cb1e4c5a2b34445177ac188312d9148f1d1d8467ea8411fa3c" + "da031d023034e45bbe407ef7d1b937bfb098266138857d35cb4efe407306", + 52, + "0c37564f718eda683aa6f3e9ab2487620b1a8b5c8f20adb3b2d7550af0d635371e53" + "1f27cebe76a2abcc96de0875bdae987a45ac", + }, + { + "f993f61902b7da332f2bb001baa7accaf764d824eb0cd073315f7ec43158b8fb", + "55fc8e0da1b454cab6ddefb235311db2b01504bf9ac3f71c7e3f3d0d1f09f80b", + "178bd147673c0ca330e45da63cbd1f1811906bd5284bb44e4bb00f7d7163d1f39697" + "5610b6f71c1ae4686466fad4c5e7bb9685099e21ca4f1a45bb3fcf56ae0c", + 42, + "b7dd613bc9c364d9eeb9a52636d72bc881dfc81a836b6537bbb928bff5b738313589" + "47ea9edea1570550", + }, + { + "05188c09c31b4bb63f0d49b47ccc1654c2aba907b8c6c0a82ee403e950169167", + "e096d808dfabe8e44eb74950199dadcd586f9de6b141a0ce85ab94b3d97866eb", + "669491c8eb7cedbbc0252f3eafb048b39a2a37f60ac87837777c72c879ac8b726c39" + "e10060750c2f539102999b71889746111bc5f71ec8c158cc81cf566aef03", + 44, + "bb8e22469d1c7f1d5418563e8781f69eccb56678bd36d8919f358c2778562ff6b50d" + "e916c12d44f1a778a7f3", + }, + { + "eabe57e1a916ebbffa4ba7abc7f23e83d4deb1338816cc1784d7495d92e98d0b", + "3aad275642f48a46ed1032f3de9f4053e0fd35cf217e065d2e4579c3683932f7", + "b2e9dac2c83942ca374f29c8eff5a30c377c3db3c1c645e593e524d17484e7705b11" + "f79573e2d63495fc3ce3bf216a209f0cb7bea477ae0f8bd297f193af8805", + 44, + "3f2c2d6682ee597f2a92d7e560ac53d5623550311a4939d68adfb904045ed8d215a9" + "fdb757a2368ea4d89f5f", + }, + { + "fef7b893b4b517fab68ca12d36b603bc00826bf3c9b31a05149642ae10bb3f55", + "b3fb891868708dfa5da5b9b5234058767ab42c117f12c3228c02a1976d1c0f83", + "6243e289314b7c7587802909a9be6173a916b36f9de1e164954dfe5d1ebd57c869a7" + "9552d770e13b51855502be6b15e7be42a3675298a81284df58e609b06503", + 47, + "38c69f884045cdbeebe4478fdbd1ccc6cf00a08d8a3120c74e7167d3a2e26a67a043" + "b8e5bd198f7b0ce0358cef7cf9", + }, + { + "16228bec9b724300a37e88e535fc1c58548d34d7148b57c226f2b3af974c1822", + "3c92423a8360c9a5d9a093730d72831bec4601dcadfe84de19fc8c8f91fc3d4b", + "6aebfa9a4294ec888d54bcb517fcb6821e4c16d2708a2afe701f431a28149ff4f139" + "f9d16a52a63f1f91baf4c8dea37710c73f25c263a8035a39cc118ad0280f", + 44, + "a3d7b122cd4431b396b20d8cc46cc73ed4a5253a44a76fc83db62cdc845a2bf7081d" + "069a857955a161cccf84", + }, + { + "2dc3f5f0a0bc32c6632534e1e8f27e59cbe0bf7617d31aff98098e974c828be7", + "b998a416edc28ded988dcacb1caf2bd96c87354b0d1eeccb6980e54a3104f21f", + "76a2ddfc4bea48c47e0c82bcbfee28a37c61ec626af39a468e643e0ef9f6533056a5" + "a0b44e64d614ba3c641a40e5b003a99463445ae2c3c8e1e9882092d74b07", + 42, + "bdae276d738b9758ea3d322b54fd12fe82b767e8d817d8ef3d41f78705748e28d15e" + "9c506962a1b85901", + }, + }; + + ed25519_secret_key private_key; + ed25519_public_key public_key; + ed25519_signature signature; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + nem_private_key(tests[i].private_key, private_key); + MARK_SECRET_DATA(private_key, sizeof(private_key)); + + ed25519_publickey_keccak(private_key, public_key); + UNMARK_SECRET_DATA(public_key, sizeof(public_key)); + ck_assert_mem_eq(public_key, fromhex(tests[i].public_key), 32); + + ed25519_sign_keccak(fromhex(tests[i].data), tests[i].length, private_key, + public_key, signature); + UNMARK_SECRET_DATA(signature, sizeof(signature)); + ck_assert_mem_eq(signature, fromhex(tests[i].signature), 64); + + UNMARK_SECRET_DATA(private_key, sizeof(private_key)); + } } END_TEST START_TEST(test_ed25519_cosi) { - const int MAXN = 10; - ed25519_secret_key keys[MAXN]; - ed25519_public_key pubkeys[MAXN]; - ed25519_secret_key nonces[MAXN]; - ed25519_public_key Rs[MAXN]; - ed25519_cosi_signature sigs[MAXN]; - uint8_t msg[32]; - rfc6979_state rng; - int res; - - init_rfc6979(fromhex("26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36"), - fromhex("26659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), &rng); - - for (int N = 1; N < 11; N++) { - ed25519_public_key pk; - ed25519_public_key R; - ed25519_signature sig; - /* phase 0: create priv/pubkeys and combine pubkeys */ - for (int j = 0; j < N; j++) { - generate_rfc6979(keys[j], &rng); - ed25519_publickey(keys[j], pubkeys[j]); - } - res = ed25519_cosi_combine_publickeys(pk, pubkeys, N); - ck_assert_int_eq(res, 0); - - generate_rfc6979(msg, &rng); - - /* phase 1: create nonces, commitments (R values) and combine commitments */ - for (int j = 0; j < N; j++) { - generate_rfc6979(nonces[j], &rng); - ed25519_publickey(nonces[j], Rs[j]); - } - res = ed25519_cosi_combine_publickeys(R, Rs, N); - ck_assert_int_eq(res, 0); - - MARK_SECRET_DATA(keys, sizeof(keys)); - /* phase 2: sign and combine signatures */ - for (int j = 0; j < N; j++) { - ed25519_cosi_sign(msg, sizeof(msg), keys[j], nonces[j], R, pk, sigs[j]); - } - UNMARK_SECRET_DATA(sigs, sizeof(sigs)); - - ed25519_cosi_combine_signatures(sig, R, sigs, N); - - /* check signature */ - res = ed25519_sign_open(msg, sizeof(msg), pk, sig); - ck_assert_int_eq(res, 0); - - UNMARK_SECRET_DATA(keys, sizeof(keys)); - } + const int MAXN = 10; + ed25519_secret_key keys[MAXN]; + ed25519_public_key pubkeys[MAXN]; + ed25519_secret_key nonces[MAXN]; + ed25519_public_key Rs[MAXN]; + ed25519_cosi_signature sigs[MAXN]; + uint8_t msg[32]; + rfc6979_state rng; + int res; + + init_rfc6979( + fromhex( + "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36"), + fromhex( + "26659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), + &rng); + + for (int N = 1; N < 11; N++) { + ed25519_public_key pk; + ed25519_public_key R; + ed25519_signature sig; + /* phase 0: create priv/pubkeys and combine pubkeys */ + for (int j = 0; j < N; j++) { + generate_rfc6979(keys[j], &rng); + ed25519_publickey(keys[j], pubkeys[j]); + } + res = ed25519_cosi_combine_publickeys(pk, pubkeys, N); + ck_assert_int_eq(res, 0); + + generate_rfc6979(msg, &rng); + + /* phase 1: create nonces, commitments (R values) and combine commitments */ + for (int j = 0; j < N; j++) { + generate_rfc6979(nonces[j], &rng); + ed25519_publickey(nonces[j], Rs[j]); + } + res = ed25519_cosi_combine_publickeys(R, Rs, N); + ck_assert_int_eq(res, 0); + + MARK_SECRET_DATA(keys, sizeof(keys)); + /* phase 2: sign and combine signatures */ + for (int j = 0; j < N; j++) { + ed25519_cosi_sign(msg, sizeof(msg), keys[j], nonces[j], R, pk, sigs[j]); + } + UNMARK_SECRET_DATA(sigs, sizeof(sigs)); + + ed25519_cosi_combine_signatures(sig, R, sigs, N); + + /* check signature */ + res = ed25519_sign_open(msg, sizeof(msg), pk, sig); + ck_assert_int_eq(res, 0); + + UNMARK_SECRET_DATA(keys, sizeof(keys)); + } } END_TEST -START_TEST(test_ed25519_modl_add) -{ - char tests[][3][65] = { - {"0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - }, - - {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", - "0000000000000000000000000000000000000000000000000000000000000000", - "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", - "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a" - }, - - {"0100000000000000000000000000000000000000000000000000000000000000", - "0200000000000000000000000000000000000000000000000000000000000000", - "0300000000000000000000000000000000000000000000000000000000000000" - }, - - {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0a00000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000" - }, - - {"f7bb3bf42b3e58e2edd06f173fc7bfbc7aaf657217946b75648447101136aa08", - "3c16b013109cc27ff39805be2abe04ba4cd6a8526a1d3023047693e950936c06", - "33d2eb073cda1a62e16975d56985c476c7850ec581b19b9868fadaf961c9160f" - }, - }; - - unsigned char buff[32]; - bignum256modm a={0}, b={0}, c={0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i][0]), 32); - expand256_modm(b, fromhex(tests[i][1]), 32); - add256_modm(c, a, b); - contract256_modm(buff, c); - ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32); - } +START_TEST(test_ed25519_modl_add) { + char tests[][3][65] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + + {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", + "0000000000000000000000000000000000000000000000000000000000000000", + "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", + "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"}, + + {"0100000000000000000000000000000000000000000000000000000000000000", + "0200000000000000000000000000000000000000000000000000000000000000", + "0300000000000000000000000000000000000000000000000000000000000000"}, + + {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0a00000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000"}, + + {"f7bb3bf42b3e58e2edd06f173fc7bfbc7aaf657217946b75648447101136aa08", + "3c16b013109cc27ff39805be2abe04ba4cd6a8526a1d3023047693e950936c06", + "33d2eb073cda1a62e16975d56985c476c7850ec581b19b9868fadaf961c9160f"}, + }; + + unsigned char buff[32]; + bignum256modm a = {0}, b = {0}, c = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i][0]), 32); + expand256_modm(b, fromhex(tests[i][1]), 32); + add256_modm(c, a, b); + contract256_modm(buff, c); + ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32); + } } END_TEST -START_TEST(test_ed25519_modl_neg) -{ - char tests[][2][65] = { - {"05d0f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "e803000000000000000000000000000000000000000000000000000000000000"}, +START_TEST(test_ed25519_modl_neg) { + char tests[][2][65] = { + {"05d0f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "e803000000000000000000000000000000000000000000000000000000000000"}, - {"4d4df45c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "a086010000000000000000000000000000000000000000000000000000000000"}, + {"4d4df45c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "a086010000000000000000000000000000000000000000000000000000000000"}, - {"25958944a1b7d4073975ca48996a1d740d0ed98ceec366760c5358da681e9608", - "c83e6c1879ab3d509d272d5a458fc1a0f2f12673113c9989f3aca72597e16907"}, + {"25958944a1b7d4073975ca48996a1d740d0ed98ceec366760c5358da681e9608", + "c83e6c1879ab3d509d272d5a458fc1a0f2f12673113c9989f3aca72597e16907"}, - {"0100000000000000000000000000000000000000000000000000000000000000", - "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"}, + {"0100000000000000000000000000000000000000000000000000000000000000", + "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"}, - {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0100000000000000000000000000000000000000000000000000000000000000"}, + {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0100000000000000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000"}, - }; + {"0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000"}, + }; - unsigned char buff[32]; - bignum256modm a={0}, b={0}; + unsigned char buff[32]; + bignum256modm a = {0}, b = {0}; - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i][0]), 32); - neg256_modm(b, a); - contract256_modm((unsigned char *) buff, b); - ck_assert_mem_eq(buff, fromhex(tests[i][1]), 32); - } + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i][0]), 32); + neg256_modm(b, a); + contract256_modm((unsigned char *)buff, b); + ck_assert_mem_eq(buff, fromhex(tests[i][1]), 32); + } } END_TEST -START_TEST(test_ed25519_modl_sub) -{ - char tests[][3][65] = { - {"0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - }, - - {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", - "53732f60e51ee3a48d21d2d526548c0dadbb79a185678fd7710613d0e76aad0c", - "8859d1d1deee0767a4ff1b72a3e0d0327573c69bbff5fc07cfa61414e6ef3b0e" - }, - - {"9d91e26dbe7a14fdca9f5b20d13e828dc8c1ffe03fe90136a6bba507436ce500", - "9ca406705ccce65eb8cbf63706d3df09fcc67216c0dc3990270731aacbb2e607", - "eec0d15a7c1140f6e8705c8ba9658198ccfa8cca7f0cc8a57eb4745d77b9fe08" - }, - - {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", - "0000000000000000000000000000000000000000000000000000000000000000", - "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "39897fbebf137a34572b014b0638ac0186d17874e3cc142ebdfe24327f5b8509", - "b44a769e5a4f98237f71f657d8c132137a2e878b1c33ebd14201dbcd80a47a06" - }, - - {"0200000000000000000000000000000000000000000000000000000000000000", - "e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0c00000000000000000000000000000000000000000000000000000000000000" - }, - - {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0800000000000000000000000000000000000000000000000000000000000000", - "dbd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" - }, - - {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0000000000000000000000000000000000000000000000000000000000000000", - "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "0100000000000000000000000000000000000000000000000000000000000000" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000010", - "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "ffffff3f00000000000000000000000000000000000000000000000000000010", - "eed3f51c1a631258d69cf7a2def9de1400000000000000000000000000000000" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000010" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "e75f947f11d49d25a137fac8757538a980dec23811235cf63c48ee6bc6e4ed03", - "067461dd088f74323565fdd96884a66b7f213dc7eedca309c3b71194391b120c" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "ecd3f55c1a631258d69cf7a2def9de140000000000000000000000000000ff0f", - "0100000000000000000000000000000000000000000000000000000000000100" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "edd3f55c1a631258d69cf7a2def9de140000000000000000000004000000ff0f", - "0000000000000000000000000000000000000000000000000000fcffffff0000" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "edd3f55c1a631258d69cf7a2def9de150000c0ffffffffffffffffffffffff0f", - "000000000000000000000000000000ffffff3f00000000000000000000000000" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "edd3f55c1a631258d69cf7a2def9de1200000000000000000000000000000110", - "edd3f55c1a631258d69cf7a2def9de160000000000000000000000000000ff0f" - }, - - {"0000000000000000000000000000000000000000000000000000000000000000", - "edd3f55c1a631258d69cf7a2def9de1300000000000000000000000000000010", - "0000000000000000000000000000000100000000000000000000000000000000" - }, - }; - - unsigned char buff[32]; - bignum256modm a={0}, b={0}, c={0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i][0]), 32); - expand256_modm(b, fromhex(tests[i][1]), 32); - sub256_modm(c, a, b); - contract256_modm(buff, c); - ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32); - } +START_TEST(test_ed25519_modl_sub) { + char tests[][3][65] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + + {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", + "53732f60e51ee3a48d21d2d526548c0dadbb79a185678fd7710613d0e76aad0c", + "8859d1d1deee0767a4ff1b72a3e0d0327573c69bbff5fc07cfa61414e6ef3b0e"}, + + {"9d91e26dbe7a14fdca9f5b20d13e828dc8c1ffe03fe90136a6bba507436ce500", + "9ca406705ccce65eb8cbf63706d3df09fcc67216c0dc3990270731aacbb2e607", + "eec0d15a7c1140f6e8705c8ba9658198ccfa8cca7f0cc8a57eb4745d77b9fe08"}, + + {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a", + "0000000000000000000000000000000000000000000000000000000000000000", + "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "39897fbebf137a34572b014b0638ac0186d17874e3cc142ebdfe24327f5b8509", + "b44a769e5a4f98237f71f657d8c132137a2e878b1c33ebd14201dbcd80a47a06"}, + + {"0200000000000000000000000000000000000000000000000000000000000000", + "e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0c00000000000000000000000000000000000000000000000000000000000000"}, + + {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0800000000000000000000000000000000000000000000000000000000000000", + "dbd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"}, + + {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0000000000000000000000000000000000000000000000000000000000000000", + "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "0100000000000000000000000000000000000000000000000000000000000000"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000010", + "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "ffffff3f00000000000000000000000000000000000000000000000000000010", + "eed3f51c1a631258d69cf7a2def9de1400000000000000000000000000000000"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000010"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "e75f947f11d49d25a137fac8757538a980dec23811235cf63c48ee6bc6e4ed03", + "067461dd088f74323565fdd96884a66b7f213dc7eedca309c3b71194391b120c"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "ecd3f55c1a631258d69cf7a2def9de140000000000000000000000000000ff0f", + "0100000000000000000000000000000000000000000000000000000000000100"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "edd3f55c1a631258d69cf7a2def9de140000000000000000000004000000ff0f", + "0000000000000000000000000000000000000000000000000000fcffffff0000"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "edd3f55c1a631258d69cf7a2def9de150000c0ffffffffffffffffffffffff0f", + "000000000000000000000000000000ffffff3f00000000000000000000000000"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "edd3f55c1a631258d69cf7a2def9de1200000000000000000000000000000110", + "edd3f55c1a631258d69cf7a2def9de160000000000000000000000000000ff0f"}, + + {"0000000000000000000000000000000000000000000000000000000000000000", + "edd3f55c1a631258d69cf7a2def9de1300000000000000000000000000000010", + "0000000000000000000000000000000100000000000000000000000000000000"}, + }; + + unsigned char buff[32]; + bignum256modm a = {0}, b = {0}, c = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i][0]), 32); + expand256_modm(b, fromhex(tests[i][1]), 32); + sub256_modm(c, a, b); + contract256_modm(buff, c); + ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32); + } } END_TEST -START_TEST(test_ge25519_double_scalarmult_vartime2) -{ - char tests[][5][65] = { - {"c537208ed4985e66e9f7a35c9a69448a732ba93960bbbd2823604f7ae9e3ed08", "365233e5af17c8888d5ce508787464f4642e91a6212b1b104e6c3769535601b1", "a84f871580176708b4ac21843cb197ad96e8456034442b50859c83c5807b9901", "f022360d1bce903fa3ac58ae42f997328b31f477b8d576a9f6d26fc1d08f14ea", "bf25da82c6b210948b823ae48422a2dcd205d3c94842e68ac27e5cbeaa704ebc"}, - {"4abfabc0dda33588a98127ef3bfe724fed286395fe15932e898b5621661ea102", "e5fd79d03f5df8edfc8def663dcb96bba6cadf857f2ae6f6f51f52f8d14079b7", "4754c286b23e3c1b50054fe3937ebdc4ec01b28da5d05fb6111798b42fc5bf06", "b7e7f9464b98de5bfcf6b02c1b7053cc359df407ad59d943523c6d2ee773b2f6", "6d7d5f729bfa4882dbff8e477cd2b4c354ba347f10e7b178a24f3f16a4e0fec6"}, - {"19f2af4d04cb8181f1fe0d01fe9bb9ecc476c67ceb4a9830dae1bc7fe5fe3b04", "d3c462f4f30991220387a1fbbd1ba1dc45ce058c70a8fb1475071e7b4f0fc463", "577790e025c1fd2014db44a8d613c4e2ab1f248a4a6d14b5d39cbbafd7b20f06", "1376c6837f131f6cd1a45b1056297d2314aa0ac5f7d581d2d878261eb3259b4d", "ce790760ada87dd819b59e4f6765d836d346567ec34f02bbcfcae0585c1d758f"}, - {"cf209db9e7ee85f1e648924ec97edd86b56a833b25707519d4fbe64fd50e150a", "804f0806087dc665a26230ed5fd44c062980ee182a6bd7dbdb33df018c983778", "30d3c448cb08935309753b3051366f52328ca1d9a0b63c72b989edee0da32b0e", "98e3c973a7e85b5eab8111521c66ca584bed5597f060ab0c6b5cdeece502ac48", "2646276e1305396a1b2473690066011a39789570a09e10ce1a013c8f32cd5bea"}, - {"b0a0ffeea67b656c4c585ba58ff528a6f45d2f915db98e4a14a8ff17f27fc105", "4fabe16274f6af526ee053028485db6acd13804e02dcdddccc4183a319ab9e1c", "1e140bb08a936ac6b7437644ca0769f3c165c7aa5501d49f064a0346179b4008", "68fc1be64fb68761542a655b8dbebf50980f1fbc1845528df8d8a06bf89a1495", "7dab86994b47014efe38493fc2b62ffcead806da6e0d73c992db8cb5618a19dc"}, - {"0fee422c2294b06ca83bc3704384dffc580e7ff5921881e51a755e5f9b80af03", "4359a663ead3f7ffc3a0ead5c3c2bde348017e7bfa620f21759c32e469a16dfe", "532066e3eec29334fffc37b17178dfbac3bee15f7845f01449ddbaf5e57a7b0c", "32e46c2fb99402837631c8175db31cdd334c145f922be9070d62e6d9c493c3ea", "8c7b7d2d61cdb648960434d894787426a76d16dd46949c7aa4b85dcf1054b4d5"}, - {"3a712d5b7ceb5257dcf6e6bb06548de6ef3deba5d456cd91fc305a12b46b5d01", "5e7da62e3ec42cf3e554639dd4d2006754ee6839b720cadba94a26b73b1665ee", "2a518ecab17a2d9dde219c775bcf4f2306b190bef2dea34fb65b8e4dccc13405", "3b5d66a4dfb068923b3bc21cc8b40b59e12f845e0b85a86d394db0fa310bf185", "2ec17f1cc0be093e9cdb741a991c0f417230dea275cd7babdad35e949e250521"}, - {"5f815f2d65cef584c5e5d48b2d3d3e4cae310d70b328f88af6e9f63c52b4c90d", "8a539a8c6b2339922b31cf4bc064f1fedeb3912fd89585d79dfcff2a60aee295", "385f7132b72db04146b9e472736b32adfca29556b4775a743c18e2bfab939007", "884aaf96d625968ddb2582922a87abca131272884c47f6b86890ebccf0a79d5b", "a7afdaf24fe8472d8b89e95c3ce4a40bdf700af7cedee44ed3aa5ccca09839bd"}, - {"a043340d072df16a8ab5135f8c1d601bff14c5aba01b9212b886ad71fe164506", "52f6de5fa0fae32d4020a54d395319509d6b92092a0bf849fb34e73f8e71fc99", "37d7472d360164da29e6dcb8f9796976022571c5df4ddf7e30e9a579ba13d509", "8c369e3fd5b1112e4437b1f09e987acca4966f2f8c5227eb15ace240a2c64cc7", "fc795fe7baff5c3ac98366e6882f25874ea2b0a649d16f139e5c54ea47042a1e"}, - {"97a3268db03fa184c8cba020bf216fc789292fa9615a28962385b86870ffd70f", "a76c215587022bb9252ece4c5afeb0e65b820834cd41ac76e6c062d3eea75dc6", "8310271017154cbddf7005e24eb9a9a86777b3f42fa5e35095eafaac4eb24802", "b822665c2406083c851ecaa91ea67aa740c057e7679b5755cee60a6c63f17fd6", "f83e2444527056eba595d49bde40b2e8da76d2c145f203331d26e94560993fbc"}, - {"edaad13efad39f26298e86ba8d06a46e59122232c9529bd22f2f656595421e00", "f38e56a79f5159eb3b581dea537ec12c9c6fac381b2cf6073e27fc621197cb62", "1eea79485954b5958d9d5478f86133af1088806d923535d483b115ab23099a0f", "b32c5e57d57db7a349f4ab845f12a5045c52b4a7a5bce7fd54a1a255b0118185", "3bfb42b4ffd2c6cfc8cce9e4187dc6fbcaecd9d44a4ca1d2b68b97410bb25b81"}, - {"b15eaebe0fc83cb11d755a6f067b710204d4a59101078d8286454b652879080a", "4667a2e61d9df1690f5c33c4168e480f7e26d2f0998168ebdc0a39712946f741", "125379da1a88bfdf5b928f8795d3ea5415ef8c3d9106eb16934c3842873fd707", "8727a692a25e38b1afa98e3dd5bf88815dec6d9810c1fd8a31b56b3de8630f1e", "540883dde400b909e9955a276c20e13d99252ebe542750b8bfbbe5c3b87c51e3"}, - {"e42bdd4af3121bea644a90a76b2007615621ee5b842b9a74c4334ac309478706", "6dc4ab715d3bb975ebfd0f08e2b6f3f39922d0121ae518a8f8d2952ea2fe0b5d", "0285059b0095c97f4a50d43c7726c64c2830bf2b55dfa934ebba7ad71064dc07", "f738c0a3cee31fd8f438f282aa6c823fccfa49cf7b5c86fbf9d56bf0394b6d8d", "a1bd106841e55010decd95a170a1d0dd11780fd00759819e024b15ea3a83b4be"}, - {"5077c30fd08795dbdc7a230c050ca07e316fa3b040fd0dac45907036ab25dd0e", "96f0897f000e49e2439a9166cab40ebc125a31b82851f0541516c19683e7bfaf", "2b67d79a2efdc6451508e7f3c97c4a61b135bb839c02338bb444ef8208dd970b", "7ef4cd7cdc29c2b88ccff49898b5d0b7be5993f93c5772476feec9dc57d7b6e3", "62449b901b25760c964704b28efc184fbd5947e83851ebaf3bbfeb6f742f679f"}, - {"a4b3ce6928fe8f77d13e65ae255eee8310ab0d75bca47028b4570f0511a66006", "4e9da8d77ee337e3bcce3730ccfff2121728641c7bb4fdeb2155890f998af09a", "ff01a5075569d0f6afee45da065c72f5841f46ce772917ef75eb4d230473580f", "36ca32da8a10f4083f5a60ee21868d9d448548d49c56f19cbe6005005e34f816", "99df362a3b762cc1cbb70bc5ddff3c8614ed306037013102e387ef32e7f2494f"}, - {"074aa76351dceb752aa09887d9aca932d5821f58eedb4988fd64d8548e3f2c09", "588b4552f3b98b2f77aee2ef8cc72f88acd424c4373b3e3626393ed2ea24cbda", "f2d9175633f2e3c661b01172b4b4176850cd5b3098ffb0f927e0a5e19c1c8a02", "a6c34868736b2517fd46f57a4e30805ffd475e44a8b1413078f43d9cb3d6edd6", "46e1e7d7b1e939dd5c07c8363af01f4f9dae7c3d10f237ff9776ddc4a1903771"}, - {"ae1c8abd5a542208ee0aa93ffbf0b8e5a957edc4854fe2b48153c5c85bbf3d08", "5e084b9541a70bd5bef400be6525c5a806a5b7fb12de38b07dcd35a22c57edbe", "d95f179a215fb322d81720bf3aecde78d6d676d6f941455d0e0920f1e3619707", "c3e5d43221824de51d8f95705de69c80a2440c0483ca88549d639aee15390429", "df9fea42d3b5ac243244abb4ca4948a69493becddc5d5906f9a4e4c5645b0eab"}, - {"2f1c5adedb7341dc7638bafacc6024bd48255197ea2347fc05714b9341dd4403", "47f55263001542f796c928988f641f59d0cd43294fc8d8616b184bfe9dddf368", "aa5e884e782ab116151c609680c37b1a49b52f23bce5e2ebf28dd8532510d20b", "ef2d6d97ad1a18edfce6450c1e70295b2c7ed2bc749ea8b438a523eae078d1f3", "2396a355c6ae8e2ac24da8f55a674c96fc4cc69b38678b2bd8eb91b96f462bca"}, - {"0242e14105ced74e91cf4d4dcd22a9c09279018901d2fb8319eb54c2a1c4900a", "fcb62a6c520d31fa46efeb4a1000330653b3402f575c2ddc0c688f527e7b97be", "73a7e2e0602e5345f040dedc4db67f6d8e37c5fca3bbb124fa43963d76dbbb08", "152bf4a3305c656f77e292b1256cc470da4d3f6efc3667199db4316d7f431174", "c21ba2080013dfb225e06378d9ac27df623df552526cfddbf9e71bb1d4705dd9"}, - {"07fab4fc7b02fbcf868ffb0326cf60425fef2af1fbad83a8926cc62c2b5dff05", "29ff12c5e052eb5829e8334e0e082c5edde1f293d2b4ed499a79bcca20e48010", "97afb3dd9167877b432a23503aad1ab39188b9be07cc124ceb3fbdbd8d8b890a", "ed121240a2f4591eeedbfd880305ccd17e522673900b03279fb66e73583514ae", "b27f209e88ce5701766565e231e8123adb1df9c9f1dc461920acbc2b38d9f6d7"}, - }; - - unsigned char buff[32]; - bignum256modm a={0}, b={0}; - ge25519 A, B, R; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i][0]), 32); - expand256_modm(b, fromhex(tests[i][2]), 32); - ge25519_unpack_negative_vartime(&A, fromhex(tests[i][1])); curve25519_neg(A.x, A.x); curve25519_neg(A.t, A.t); - ge25519_unpack_negative_vartime(&B, fromhex(tests[i][3])); curve25519_neg(B.x, B.x); curve25519_neg(B.t, B.t); - ge25519_double_scalarmult_vartime2(&R, &A, a, &B, b); - ge25519_pack(buff, &R); - ck_assert_mem_eq(buff, fromhex(tests[i][4]), 32); - } +START_TEST(test_ge25519_double_scalarmult_vartime2) { + char tests[][5][65] = { + {"c537208ed4985e66e9f7a35c9a69448a732ba93960bbbd2823604f7ae9e3ed08", + "365233e5af17c8888d5ce508787464f4642e91a6212b1b104e6c3769535601b1", + "a84f871580176708b4ac21843cb197ad96e8456034442b50859c83c5807b9901", + "f022360d1bce903fa3ac58ae42f997328b31f477b8d576a9f6d26fc1d08f14ea", + "bf25da82c6b210948b823ae48422a2dcd205d3c94842e68ac27e5cbeaa704ebc"}, + {"4abfabc0dda33588a98127ef3bfe724fed286395fe15932e898b5621661ea102", + "e5fd79d03f5df8edfc8def663dcb96bba6cadf857f2ae6f6f51f52f8d14079b7", + "4754c286b23e3c1b50054fe3937ebdc4ec01b28da5d05fb6111798b42fc5bf06", + "b7e7f9464b98de5bfcf6b02c1b7053cc359df407ad59d943523c6d2ee773b2f6", + "6d7d5f729bfa4882dbff8e477cd2b4c354ba347f10e7b178a24f3f16a4e0fec6"}, + {"19f2af4d04cb8181f1fe0d01fe9bb9ecc476c67ceb4a9830dae1bc7fe5fe3b04", + "d3c462f4f30991220387a1fbbd1ba1dc45ce058c70a8fb1475071e7b4f0fc463", + "577790e025c1fd2014db44a8d613c4e2ab1f248a4a6d14b5d39cbbafd7b20f06", + "1376c6837f131f6cd1a45b1056297d2314aa0ac5f7d581d2d878261eb3259b4d", + "ce790760ada87dd819b59e4f6765d836d346567ec34f02bbcfcae0585c1d758f"}, + {"cf209db9e7ee85f1e648924ec97edd86b56a833b25707519d4fbe64fd50e150a", + "804f0806087dc665a26230ed5fd44c062980ee182a6bd7dbdb33df018c983778", + "30d3c448cb08935309753b3051366f52328ca1d9a0b63c72b989edee0da32b0e", + "98e3c973a7e85b5eab8111521c66ca584bed5597f060ab0c6b5cdeece502ac48", + "2646276e1305396a1b2473690066011a39789570a09e10ce1a013c8f32cd5bea"}, + {"b0a0ffeea67b656c4c585ba58ff528a6f45d2f915db98e4a14a8ff17f27fc105", + "4fabe16274f6af526ee053028485db6acd13804e02dcdddccc4183a319ab9e1c", + "1e140bb08a936ac6b7437644ca0769f3c165c7aa5501d49f064a0346179b4008", + "68fc1be64fb68761542a655b8dbebf50980f1fbc1845528df8d8a06bf89a1495", + "7dab86994b47014efe38493fc2b62ffcead806da6e0d73c992db8cb5618a19dc"}, + {"0fee422c2294b06ca83bc3704384dffc580e7ff5921881e51a755e5f9b80af03", + "4359a663ead3f7ffc3a0ead5c3c2bde348017e7bfa620f21759c32e469a16dfe", + "532066e3eec29334fffc37b17178dfbac3bee15f7845f01449ddbaf5e57a7b0c", + "32e46c2fb99402837631c8175db31cdd334c145f922be9070d62e6d9c493c3ea", + "8c7b7d2d61cdb648960434d894787426a76d16dd46949c7aa4b85dcf1054b4d5"}, + {"3a712d5b7ceb5257dcf6e6bb06548de6ef3deba5d456cd91fc305a12b46b5d01", + "5e7da62e3ec42cf3e554639dd4d2006754ee6839b720cadba94a26b73b1665ee", + "2a518ecab17a2d9dde219c775bcf4f2306b190bef2dea34fb65b8e4dccc13405", + "3b5d66a4dfb068923b3bc21cc8b40b59e12f845e0b85a86d394db0fa310bf185", + "2ec17f1cc0be093e9cdb741a991c0f417230dea275cd7babdad35e949e250521"}, + {"5f815f2d65cef584c5e5d48b2d3d3e4cae310d70b328f88af6e9f63c52b4c90d", + "8a539a8c6b2339922b31cf4bc064f1fedeb3912fd89585d79dfcff2a60aee295", + "385f7132b72db04146b9e472736b32adfca29556b4775a743c18e2bfab939007", + "884aaf96d625968ddb2582922a87abca131272884c47f6b86890ebccf0a79d5b", + "a7afdaf24fe8472d8b89e95c3ce4a40bdf700af7cedee44ed3aa5ccca09839bd"}, + {"a043340d072df16a8ab5135f8c1d601bff14c5aba01b9212b886ad71fe164506", + "52f6de5fa0fae32d4020a54d395319509d6b92092a0bf849fb34e73f8e71fc99", + "37d7472d360164da29e6dcb8f9796976022571c5df4ddf7e30e9a579ba13d509", + "8c369e3fd5b1112e4437b1f09e987acca4966f2f8c5227eb15ace240a2c64cc7", + "fc795fe7baff5c3ac98366e6882f25874ea2b0a649d16f139e5c54ea47042a1e"}, + {"97a3268db03fa184c8cba020bf216fc789292fa9615a28962385b86870ffd70f", + "a76c215587022bb9252ece4c5afeb0e65b820834cd41ac76e6c062d3eea75dc6", + "8310271017154cbddf7005e24eb9a9a86777b3f42fa5e35095eafaac4eb24802", + "b822665c2406083c851ecaa91ea67aa740c057e7679b5755cee60a6c63f17fd6", + "f83e2444527056eba595d49bde40b2e8da76d2c145f203331d26e94560993fbc"}, + {"edaad13efad39f26298e86ba8d06a46e59122232c9529bd22f2f656595421e00", + "f38e56a79f5159eb3b581dea537ec12c9c6fac381b2cf6073e27fc621197cb62", + "1eea79485954b5958d9d5478f86133af1088806d923535d483b115ab23099a0f", + "b32c5e57d57db7a349f4ab845f12a5045c52b4a7a5bce7fd54a1a255b0118185", + "3bfb42b4ffd2c6cfc8cce9e4187dc6fbcaecd9d44a4ca1d2b68b97410bb25b81"}, + {"b15eaebe0fc83cb11d755a6f067b710204d4a59101078d8286454b652879080a", + "4667a2e61d9df1690f5c33c4168e480f7e26d2f0998168ebdc0a39712946f741", + "125379da1a88bfdf5b928f8795d3ea5415ef8c3d9106eb16934c3842873fd707", + "8727a692a25e38b1afa98e3dd5bf88815dec6d9810c1fd8a31b56b3de8630f1e", + "540883dde400b909e9955a276c20e13d99252ebe542750b8bfbbe5c3b87c51e3"}, + {"e42bdd4af3121bea644a90a76b2007615621ee5b842b9a74c4334ac309478706", + "6dc4ab715d3bb975ebfd0f08e2b6f3f39922d0121ae518a8f8d2952ea2fe0b5d", + "0285059b0095c97f4a50d43c7726c64c2830bf2b55dfa934ebba7ad71064dc07", + "f738c0a3cee31fd8f438f282aa6c823fccfa49cf7b5c86fbf9d56bf0394b6d8d", + "a1bd106841e55010decd95a170a1d0dd11780fd00759819e024b15ea3a83b4be"}, + {"5077c30fd08795dbdc7a230c050ca07e316fa3b040fd0dac45907036ab25dd0e", + "96f0897f000e49e2439a9166cab40ebc125a31b82851f0541516c19683e7bfaf", + "2b67d79a2efdc6451508e7f3c97c4a61b135bb839c02338bb444ef8208dd970b", + "7ef4cd7cdc29c2b88ccff49898b5d0b7be5993f93c5772476feec9dc57d7b6e3", + "62449b901b25760c964704b28efc184fbd5947e83851ebaf3bbfeb6f742f679f"}, + {"a4b3ce6928fe8f77d13e65ae255eee8310ab0d75bca47028b4570f0511a66006", + "4e9da8d77ee337e3bcce3730ccfff2121728641c7bb4fdeb2155890f998af09a", + "ff01a5075569d0f6afee45da065c72f5841f46ce772917ef75eb4d230473580f", + "36ca32da8a10f4083f5a60ee21868d9d448548d49c56f19cbe6005005e34f816", + "99df362a3b762cc1cbb70bc5ddff3c8614ed306037013102e387ef32e7f2494f"}, + {"074aa76351dceb752aa09887d9aca932d5821f58eedb4988fd64d8548e3f2c09", + "588b4552f3b98b2f77aee2ef8cc72f88acd424c4373b3e3626393ed2ea24cbda", + "f2d9175633f2e3c661b01172b4b4176850cd5b3098ffb0f927e0a5e19c1c8a02", + "a6c34868736b2517fd46f57a4e30805ffd475e44a8b1413078f43d9cb3d6edd6", + "46e1e7d7b1e939dd5c07c8363af01f4f9dae7c3d10f237ff9776ddc4a1903771"}, + {"ae1c8abd5a542208ee0aa93ffbf0b8e5a957edc4854fe2b48153c5c85bbf3d08", + "5e084b9541a70bd5bef400be6525c5a806a5b7fb12de38b07dcd35a22c57edbe", + "d95f179a215fb322d81720bf3aecde78d6d676d6f941455d0e0920f1e3619707", + "c3e5d43221824de51d8f95705de69c80a2440c0483ca88549d639aee15390429", + "df9fea42d3b5ac243244abb4ca4948a69493becddc5d5906f9a4e4c5645b0eab"}, + {"2f1c5adedb7341dc7638bafacc6024bd48255197ea2347fc05714b9341dd4403", + "47f55263001542f796c928988f641f59d0cd43294fc8d8616b184bfe9dddf368", + "aa5e884e782ab116151c609680c37b1a49b52f23bce5e2ebf28dd8532510d20b", + "ef2d6d97ad1a18edfce6450c1e70295b2c7ed2bc749ea8b438a523eae078d1f3", + "2396a355c6ae8e2ac24da8f55a674c96fc4cc69b38678b2bd8eb91b96f462bca"}, + {"0242e14105ced74e91cf4d4dcd22a9c09279018901d2fb8319eb54c2a1c4900a", + "fcb62a6c520d31fa46efeb4a1000330653b3402f575c2ddc0c688f527e7b97be", + "73a7e2e0602e5345f040dedc4db67f6d8e37c5fca3bbb124fa43963d76dbbb08", + "152bf4a3305c656f77e292b1256cc470da4d3f6efc3667199db4316d7f431174", + "c21ba2080013dfb225e06378d9ac27df623df552526cfddbf9e71bb1d4705dd9"}, + {"07fab4fc7b02fbcf868ffb0326cf60425fef2af1fbad83a8926cc62c2b5dff05", + "29ff12c5e052eb5829e8334e0e082c5edde1f293d2b4ed499a79bcca20e48010", + "97afb3dd9167877b432a23503aad1ab39188b9be07cc124ceb3fbdbd8d8b890a", + "ed121240a2f4591eeedbfd880305ccd17e522673900b03279fb66e73583514ae", + "b27f209e88ce5701766565e231e8123adb1df9c9f1dc461920acbc2b38d9f6d7"}, + }; + + unsigned char buff[32]; + bignum256modm a = {0}, b = {0}; + ge25519 A, B, R; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i][0]), 32); + expand256_modm(b, fromhex(tests[i][2]), 32); + ge25519_unpack_negative_vartime(&A, fromhex(tests[i][1])); + curve25519_neg(A.x, A.x); + curve25519_neg(A.t, A.t); + ge25519_unpack_negative_vartime(&B, fromhex(tests[i][3])); + curve25519_neg(B.x, B.x); + curve25519_neg(B.t, B.t); + ge25519_double_scalarmult_vartime2(&R, &A, a, &B, b); + ge25519_pack(buff, &R); + ck_assert_mem_eq(buff, fromhex(tests[i][4]), 32); + } } 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); - if (node->public_key[0] == 1) { - node->public_key[0] = 0x40; // Curve25519 public keys start with 0x40 byte - } +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); + if (node->public_key[0] == 1) { + node->public_key[0] = 0x40; // Curve25519 public keys start with 0x40 byte + } } -static void test_bip32_ecdh(const char *curve_name, int expected_key_size, const uint8_t *expected_key) { - int res, key_size; - HDNode alice, bob; - uint8_t session_key1[expected_key_size], session_key2[expected_key_size]; - - test_bip32_ecdh_init_node(&alice, "Alice", curve_name); - test_bip32_ecdh_init_node(&bob, "Bob", curve_name); - - // Generate shared key from Alice's secret key and Bob's public key - res = hdnode_get_shared_key(&alice, bob.public_key, session_key1, &key_size); - ck_assert_int_eq(res, 0); - ck_assert_int_eq(key_size, expected_key_size); - ck_assert_mem_eq(session_key1, expected_key, key_size); - - // Generate shared key from Bob's secret key and Alice's public key - res = hdnode_get_shared_key(&bob, alice.public_key, session_key2, &key_size); - ck_assert_int_eq(res, 0); - ck_assert_int_eq(key_size, expected_key_size); - ck_assert_mem_eq(session_key2, expected_key, key_size); +static void test_bip32_ecdh(const char *curve_name, int expected_key_size, + const uint8_t *expected_key) { + int res, key_size; + HDNode alice, bob; + uint8_t session_key1[expected_key_size], session_key2[expected_key_size]; + + test_bip32_ecdh_init_node(&alice, "Alice", curve_name); + test_bip32_ecdh_init_node(&bob, "Bob", curve_name); + + // Generate shared key from Alice's secret key and Bob's public key + res = hdnode_get_shared_key(&alice, bob.public_key, session_key1, &key_size); + ck_assert_int_eq(res, 0); + ck_assert_int_eq(key_size, expected_key_size); + ck_assert_mem_eq(session_key1, expected_key, key_size); + + // Generate shared key from Bob's secret key and Alice's public key + res = hdnode_get_shared_key(&bob, alice.public_key, session_key2, &key_size); + ck_assert_int_eq(res, 0); + ck_assert_int_eq(key_size, expected_key_size); + ck_assert_mem_eq(session_key2, expected_key, key_size); } START_TEST(test_bip32_ecdh_nist256p1) { - test_bip32_ecdh( - NIST256P1_NAME, 65, - fromhex("044aa56f917323f071148cd29aa423f6bee96e7fe87f914d0b91a0f95388c6631646ea92e882773d7b0b1bec356b842c8559a1377673d3965fb931c8fe51e64873")); + test_bip32_ecdh( + NIST256P1_NAME, 65, + fromhex( + "044aa56f917323f071148cd29aa423f6bee96e7fe87f914d0b91a0f95388c6631646" + "ea92e882773d7b0b1bec356b842c8559a1377673d3965fb931c8fe51e64873")); } END_TEST START_TEST(test_bip32_ecdh_curve25519) { - test_bip32_ecdh( - CURVE25519_NAME, 33, - fromhex("04f34e35516325bb0d4a58507096c444a05ba13524ccf66910f11ce96c62224169")); + test_bip32_ecdh(CURVE25519_NAME, 33, + fromhex("04f34e35516325bb0d4a58507096c444a05ba13524ccf66910f1" + "1ce96c62224169")); } END_TEST START_TEST(test_bip32_ecdh_errors) { - HDNode node; - const uint8_t peer_public_key[65] = {0}; // invalid public key - uint8_t session_key[65]; - int res, key_size = 0; - - test_bip32_ecdh_init_node(&node, "Seed", ED25519_NAME); - res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(key_size, 0); - - test_bip32_ecdh_init_node(&node, "Seed", CURVE25519_NAME); - res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(key_size, 0); - - test_bip32_ecdh_init_node(&node, "Seed", NIST256P1_NAME); - res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(key_size, 0); + HDNode node; + const uint8_t peer_public_key[65] = {0}; // invalid public key + uint8_t session_key[65]; + int res, key_size = 0; + + test_bip32_ecdh_init_node(&node, "Seed", ED25519_NAME); + res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(key_size, 0); + + test_bip32_ecdh_init_node(&node, "Seed", CURVE25519_NAME); + res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(key_size, 0); + + test_bip32_ecdh_init_node(&node, "Seed", NIST256P1_NAME); + res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(key_size, 0); } END_TEST START_TEST(test_output_script) { - static const char *vectors[] = { - "76A914010966776006953D5567439E5E39F86A0D273BEE88AC", "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", - "A914010966776006953D5567439E5E39F86A0D273BEE87", "31nVrspaydBz8aMpxH9WkS2DuhgqS1fCuG", - "0014010966776006953D5567439E5E39F86A0D273BEE", "p2xtZoXeX5X8BP8JfFhQK2nD3emtjch7UeFm", - "00200102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", "7XhPD7te3C6CVKnJWUhrTJbFTwudhHqfrjpS59AS6sMzL4RYFiCNg", - 0, 0, - }; - const char **scr, **adr; - scr = vectors; - adr = vectors + 1; - char address[60]; - while (*scr && *adr) { - int r = script_output_to_address(fromhex(*scr), strlen(*scr)/2, address, 60); - ck_assert_int_eq(r, (int)(strlen(*adr) + 1)); - ck_assert_str_eq(address, *adr); - scr += 2; - adr += 2; - } + static const char *vectors[] = { + "76A914010966776006953D5567439E5E39F86A0D273BEE88AC", + "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", + "A914010966776006953D5567439E5E39F86A0D273BEE87", + "31nVrspaydBz8aMpxH9WkS2DuhgqS1fCuG", + "0014010966776006953D5567439E5E39F86A0D273BEE", + "p2xtZoXeX5X8BP8JfFhQK2nD3emtjch7UeFm", + "00200102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", + "7XhPD7te3C6CVKnJWUhrTJbFTwudhHqfrjpS59AS6sMzL4RYFiCNg", + 0, + 0, + }; + const char **scr, **adr; + scr = vectors; + adr = vectors + 1; + char address[60]; + while (*scr && *adr) { + int r = + script_output_to_address(fromhex(*scr), strlen(*scr) / 2, address, 60); + ck_assert_int_eq(r, (int)(strlen(*adr) + 1)); + ck_assert_str_eq(address, *adr); + scr += 2; + adr += 2; + } } END_TEST -START_TEST(test_ethereum_pubkeyhash) -{ - uint8_t pubkeyhash[20]; - int res; - HDNode node; - - // init m - hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, SECP256K1_NAME, &node); - - // [Chain m] - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("056db290f8ba3250ca64a45d16284d04bc6f5fbf"), 20); - - // [Chain m/0'] - hdnode_private_ckd_prime(&node, 0); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("bf6e48966d0dcf553b53e7b56cb2e0e72dca9e19"), 20); - - // [Chain m/0'/1] - hdnode_private_ckd(&node, 1); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("29379f45f515c494483298225d1b347f73d1babf"), 20); - - // [Chain m/0'/1/2'] - hdnode_private_ckd_prime(&node, 2); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("d8e85fbbb4b3b3c71c4e63a5580d0c12fb4d2f71"), 20); - - // [Chain m/0'/1/2'/2] - hdnode_private_ckd(&node, 2); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("1d3462d2319ac0bfc1a52e177a9d372492752130"), 20); - - // [Chain m/0'/1/2'/2/1000000000] - hdnode_private_ckd(&node, 1000000000); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("73659c60270d326c06ac204f1a9c63f889a3d14b"), 20); - - // init m - hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, SECP256K1_NAME, &node); - - // [Chain m] - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("6dd2a6f3b05fd15d901fbeec61b87a34bdcfb843"), 20); - - // [Chain m/0] - hdnode_private_ckd(&node, 0); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("abbcd4471a0b6e76a2f6fdc44008fe53831e208e"), 20); - - // [Chain m/0/2147483647'] - hdnode_private_ckd_prime(&node, 2147483647); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("40ef2cef1b2588ae862e7a511162ec7ff33c30fd"), 20); - - // [Chain m/0/2147483647'/1] - hdnode_private_ckd(&node, 1); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("3f2e8905488f795ebc84a39560d133971ccf9b50"), 20); - - // [Chain m/0/2147483647'/1/2147483646'] - hdnode_private_ckd_prime(&node, 2147483646); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("a5016fdf975f767e4e6f355c7a82efa69bf42ea7"), 20); - - // [Chain m/0/2147483647'/1/2147483646'/2] - hdnode_private_ckd(&node, 2); - res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(pubkeyhash, fromhex("8ff2a9f7e7917804e8c8ec150d931d9c5a6fbc50"), 20); +START_TEST(test_ethereum_pubkeyhash) { + uint8_t pubkeyhash[20]; + int res; + HDNode node; + + // init m + hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, + SECP256K1_NAME, &node); + + // [Chain m] + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("056db290f8ba3250ca64a45d16284d04bc6f5fbf"), 20); + + // [Chain m/0'] + hdnode_private_ckd_prime(&node, 0); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("bf6e48966d0dcf553b53e7b56cb2e0e72dca9e19"), 20); + + // [Chain m/0'/1] + hdnode_private_ckd(&node, 1); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("29379f45f515c494483298225d1b347f73d1babf"), 20); + + // [Chain m/0'/1/2'] + hdnode_private_ckd_prime(&node, 2); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("d8e85fbbb4b3b3c71c4e63a5580d0c12fb4d2f71"), 20); + + // [Chain m/0'/1/2'/2] + hdnode_private_ckd(&node, 2); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("1d3462d2319ac0bfc1a52e177a9d372492752130"), 20); + + // [Chain m/0'/1/2'/2/1000000000] + hdnode_private_ckd(&node, 1000000000); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("73659c60270d326c06ac204f1a9c63f889a3d14b"), 20); + + // init m + hdnode_from_seed( + fromhex( + "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c" + "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), + 64, SECP256K1_NAME, &node); + + // [Chain m] + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("6dd2a6f3b05fd15d901fbeec61b87a34bdcfb843"), 20); + + // [Chain m/0] + hdnode_private_ckd(&node, 0); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("abbcd4471a0b6e76a2f6fdc44008fe53831e208e"), 20); + + // [Chain m/0/2147483647'] + hdnode_private_ckd_prime(&node, 2147483647); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("40ef2cef1b2588ae862e7a511162ec7ff33c30fd"), 20); + + // [Chain m/0/2147483647'/1] + hdnode_private_ckd(&node, 1); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("3f2e8905488f795ebc84a39560d133971ccf9b50"), 20); + + // [Chain m/0/2147483647'/1/2147483646'] + hdnode_private_ckd_prime(&node, 2147483646); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("a5016fdf975f767e4e6f355c7a82efa69bf42ea7"), 20); + + // [Chain m/0/2147483647'/1/2147483646'/2] + hdnode_private_ckd(&node, 2); + res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(pubkeyhash, + fromhex("8ff2a9f7e7917804e8c8ec150d931d9c5a6fbc50"), 20); } END_TEST -START_TEST(test_ethereum_address) -{ - static const char *vectors[] = { - "52908400098527886E0F7030069857D2E4169EE7", - "8617E340B3D01FA5F11F306F4090FD50E238070D", - "de709f2102306220921060314715629080e2fb77", - "27b1fdb04752bbc536007a920d24acb045561c26", - "5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", - "fB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", - "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", - "D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", - "5A4EAB120fB44eb6684E5e32785702FF45ea344D", - "5be4BDC48CeF65dbCbCaD5218B1A7D37F58A0741", - "a7dD84573f5ffF821baf2205745f768F8edCDD58", - "027a49d11d118c0060746F1990273FcB8c2fC196", - "CD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", - 0 - }; - uint8_t addr[20]; - char address[41]; - const char **vec = vectors; - while (*vec) { - memcpy(addr, fromhex(*vec), 20); - ethereum_address_checksum(addr, address, false, 0); - ck_assert_str_eq(address, *vec); - vec++; - } +START_TEST(test_ethereum_address) { + static const char *vectors[] = {"52908400098527886E0F7030069857D2E4169EE7", + "8617E340B3D01FA5F11F306F4090FD50E238070D", + "de709f2102306220921060314715629080e2fb77", + "27b1fdb04752bbc536007a920d24acb045561c26", + "5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + "fB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", + "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", + "D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", + "5A4EAB120fB44eb6684E5e32785702FF45ea344D", + "5be4BDC48CeF65dbCbCaD5218B1A7D37F58A0741", + "a7dD84573f5ffF821baf2205745f768F8edCDD58", + "027a49d11d118c0060746F1990273FcB8c2fC196", + "CD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + 0}; + uint8_t addr[20]; + char address[41]; + const char **vec = vectors; + while (*vec) { + memcpy(addr, fromhex(*vec), 20); + ethereum_address_checksum(addr, address, false, 0); + ck_assert_str_eq(address, *vec); + vec++; + } } END_TEST -// test vectors from https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md -START_TEST(test_rsk_address) -{ - uint8_t addr[20]; - char address[41]; - - static const char *rskip60_chain30[] = { - "5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD", - "Fb6916095cA1Df60bb79ce92cE3EA74c37c5d359", - "DBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB", - "D1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB", - 0 - }; - const char **vec = rskip60_chain30; - while (*vec) { - memcpy(addr, fromhex(*vec), 20); - ethereum_address_checksum(addr, address, true, 30); - ck_assert_str_eq(address, *vec); - vec++; - } - - static const char *rskip60_chain31[] = { - "5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd", - "Fb6916095CA1dF60bb79CE92ce3Ea74C37c5D359", - "dbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB", - "d1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB", - 0 - }; - vec = rskip60_chain31; - while (*vec) { - memcpy(addr, fromhex(*vec), 20); - ethereum_address_checksum(addr, address, true, 31); - ck_assert_str_eq(address, *vec); - vec++; - } +// test vectors from +// https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md +START_TEST(test_rsk_address) { + uint8_t addr[20]; + char address[41]; + + static const char *rskip60_chain30[] = { + "5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD", + "Fb6916095cA1Df60bb79ce92cE3EA74c37c5d359", + "DBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB", + "D1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB", 0}; + const char **vec = rskip60_chain30; + while (*vec) { + memcpy(addr, fromhex(*vec), 20); + ethereum_address_checksum(addr, address, true, 30); + ck_assert_str_eq(address, *vec); + vec++; + } + + static const char *rskip60_chain31[] = { + "5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd", + "Fb6916095CA1dF60bb79CE92ce3Ea74C37c5D359", + "dbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB", + "d1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB", 0}; + vec = rskip60_chain31; + while (*vec) { + memcpy(addr, fromhex(*vec), 20); + ethereum_address_checksum(addr, address, true, 31); + ck_assert_str_eq(address, *vec); + vec++; + } } END_TEST -// test vectors from https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/1.test-keys.dat -START_TEST(test_nem_address) -{ - static const struct { - const char *private_key; - const char *public_key; - const char *address; - } tests[] = { - { "575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced", "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", "NDD2CT6LQLIYQ56KIXI3ENTM6EK3D44P5JFXJ4R4", }, - { "5b0e3fa5d3b49a79022d7c1e121ba1cbbf4db5821f47ab8c708ef88defc29bfe", "96eb2a145211b1b7ab5f0d4b14f8abc8d695c7aee31a3cfc2d4881313c68eea3", "NABHFGE5ORQD3LE4O6B7JUFN47ECOFBFASC3SCAC", }, - { "738ba9bb9110aea8f15caa353aca5653b4bdfca1db9f34d0efed2ce1325aeeda", "2d8425e4ca2d8926346c7a7ca39826acd881a8639e81bd68820409c6e30d142a", "NAVOZX4HDVOAR4W6K4WJHWPD3MOFU27DFHC7KZOZ", }, - { "e8bf9bc0f35c12d8c8bf94dd3a8b5b4034f1063948e3cc5304e55e31aa4b95a6", "4feed486777ed38e44c489c7c4e93a830e4c4a907fa19a174e630ef0f6ed0409", "NBZ6JK5YOCU6UPSSZ5D3G27UHAPHTY5HDQMGE6TT", }, - { "c325ea529674396db5675939e7988883d59a5fc17a28ca977e3ba85370232a83", "83ee32e4e145024d29bca54f71fa335a98b3e68283f1a3099c4d4ae113b53e54", "NCQW2P5DNZ5BBXQVGS367DQ4AHC3RXOEVGRCLY6V", }, - { "a811cb7a80a7227ae61f6da536534ee3c2744e3c7e4b85f3e0df3c6a9c5613df", "6d34c04f3a0e42f0c3c6f50e475ae018cfa2f56df58c481ad4300424a6270cbb", "NA5IG3XFXZHIPJ5QLKX2FBJPEZYPMBPPK2ZRC3EH", }, - { "9c66de1ec77f4dfaaebdf9c8bc599ca7e8e6f0bc71390ffee2c9dd3f3619242a", "a8fefd72a3b833dc7c7ed7d57ed86906dac22f88f1f4331873eb2da3152a3e77", "NAABHVFJDBM74XMJJ52R7QN2MTTG2ZUXPQS62QZ7", }, - { "c56bc16ecf727878c15e24f4ae68569600ac7b251218a44ef50ce54175776edc", "c92f761e6d83d20068fd46fe4bd5b97f4c6ba05d23180679b718d1f3e4fb066e", "NCLK3OLMHR3F2E3KSBUIZ4K5PNWUDN37MLSJBJZP", }, - { "9dd73599283882fa1561ddfc9be5830b5dd453c90465d3fe5eeb646a3606374e", "eaf16a4833e59370a04ccd5c63395058de34877b48c17174c71db5ed37b537ed", "ND3AHW4VTI5R5QE5V44KIGPRU5FBJ5AFUCJXOY5H", }, - { "d9639dc6f49dad02a42fd8c217f1b1b4f8ce31ccd770388b645e639c72ff24fa", "0f74a2f537cd9c986df018994dde75bdeee05e35eb9fe27adf506ca8475064f7", "NCTZ4YAP43ONK3UYTASQVNDMBO24ZHJE65F3QPYE", }, - { "efc1992cd50b70ca55ac12c07aa5d026a8b78ffe28a7dbffc9228b26e02c38c1", "2ebff201255f6cf948c78f528658b99a7c13ac791942fa22d59af610558111f5", "NDQ2TMCMXBSFPZQPE2YKH6XLC24HD6LUMN6Z4GIC", }, - { "143a815e92e43f3ed1a921ee48cd143931b88b7c3d8e1e981f743c2a5be3c5ba", "419ed11d48730e4ae2c93f0ea4df853b8d578713a36dab227517cf965861af4e", "NA32IDDW2C53BDSBJNFL3Z6UU3J5CJZJMCZDXCF4", }, - { "bc1a082f5ac6fdd3a83ade211e5986ac0551bad6c7da96727ec744e5df963e2a", "a160e6f9112233a7ce94202ed7a4443e1dac444b5095f9fecbb965fba3f92cac", "NADUCEQLC3FTGB25GTA5HOUTB53CBVQNVOIP7NTJ", }, - { "4e47b4c6f4c7886e49ec109c61f4af5cfbb1637283218941d55a7f9fe1053f72", "fbb91b16df828e21a9802980a44fc757c588bc1382a4cea429d6fa2ae0333f56", "NBAF3BFLLPWH33MYE6VUPP5T6DQBZBKIDEQKZQOE", }, - { "efc4389da48ce49f85365cfa578c746530e9eac42db1b64ec346119b1becd347", "2232f24dda0f2ded3ecd831210d4e8521a096b50cadd5a34f3f7083374e1ec12", "NBOGTK2I2ATOGGD7ZFJHROG5MWL7XCKAUKSWIVSA", }, - { "bdba57c78ca7da16a3360efd13f06276284db8c40351de7fcd38ba0c35ac754d", "c334c6c0dad5aaa2a0d0fb4c6032cb6a0edd96bf61125b5ea9062d5a00ee0eee", "NCLERTEFYXKLK7RA4MVACEFMXMK3P7QMWTM7FBW2", }, - { "20694c1ec3c4a311bcdb29ed2edc428f6d4f9a4c429ad6a5bf3222084e35695f", "518c4de412efa93de06a55947d11f697639443916ec8fcf04ebc3e6d17d0bd93", "NB5V4BPIJHXVONO7UGMJDPFARMFA73BOBNOOYCOV", }, - { "e0d4f3760ac107b33c22c2cac24ab2f520b282684f5f66a4212ff95d926323ce", "b3d16f4ead9de67c290144da535a0ed2504b03c05e5f1ceb8c7863762f786857", "NC4PBAO5TPCAVQKBVOC4F6DMZP3CFSQBU46PSKBD", }, - { "efa9afc617412093c9c7a7c211a5332dd556f941e1a88c494ec860608610eea2", "7e7716e4cebceb731d6f1fd28676f34888e9a0000fcfa1471db1c616c2ddf559", "NCFW2LPXIWLBWAQN2QVIWEOD7IVDO3HQBD2OU56K", }, - { "d98499b3db61944684ce06a91735af4e14105338473fcf6ebe2b0bcada3dfd21", "114171230ad6f8522a000cdc73fbc5c733b30bb71f2b146ccbdf34499f79a810", "NCUKWDY3J3THKQHAKOK5ALF6ANJQABZHCH7VN6DP", }, - }; - - HDNode node; - ed25519_secret_key private_key; - uint8_t chain_code[32]; - char address[41]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - nem_private_key(tests[i].private_key, private_key); - - ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, ED25519_KECCAK_NAME, &node)); - - ck_assert(hdnode_get_nem_address(&node, NEM_NETWORK_MAINNET, address)); - ck_assert_str_eq(address, tests[i].address); - - ck_assert_mem_eq(&node.public_key[1], fromhex(tests[i].public_key), 32); - } +// test vectors from +// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/1.test-keys.dat +START_TEST(test_nem_address) { + static const struct { + const char *private_key; + const char *public_key; + const char *address; + } tests[] = { + { + "575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced", + "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + "NDD2CT6LQLIYQ56KIXI3ENTM6EK3D44P5JFXJ4R4", + }, + { + "5b0e3fa5d3b49a79022d7c1e121ba1cbbf4db5821f47ab8c708ef88defc29bfe", + "96eb2a145211b1b7ab5f0d4b14f8abc8d695c7aee31a3cfc2d4881313c68eea3", + "NABHFGE5ORQD3LE4O6B7JUFN47ECOFBFASC3SCAC", + }, + { + "738ba9bb9110aea8f15caa353aca5653b4bdfca1db9f34d0efed2ce1325aeeda", + "2d8425e4ca2d8926346c7a7ca39826acd881a8639e81bd68820409c6e30d142a", + "NAVOZX4HDVOAR4W6K4WJHWPD3MOFU27DFHC7KZOZ", + }, + { + "e8bf9bc0f35c12d8c8bf94dd3a8b5b4034f1063948e3cc5304e55e31aa4b95a6", + "4feed486777ed38e44c489c7c4e93a830e4c4a907fa19a174e630ef0f6ed0409", + "NBZ6JK5YOCU6UPSSZ5D3G27UHAPHTY5HDQMGE6TT", + }, + { + "c325ea529674396db5675939e7988883d59a5fc17a28ca977e3ba85370232a83", + "83ee32e4e145024d29bca54f71fa335a98b3e68283f1a3099c4d4ae113b53e54", + "NCQW2P5DNZ5BBXQVGS367DQ4AHC3RXOEVGRCLY6V", + }, + { + "a811cb7a80a7227ae61f6da536534ee3c2744e3c7e4b85f3e0df3c6a9c5613df", + "6d34c04f3a0e42f0c3c6f50e475ae018cfa2f56df58c481ad4300424a6270cbb", + "NA5IG3XFXZHIPJ5QLKX2FBJPEZYPMBPPK2ZRC3EH", + }, + { + "9c66de1ec77f4dfaaebdf9c8bc599ca7e8e6f0bc71390ffee2c9dd3f3619242a", + "a8fefd72a3b833dc7c7ed7d57ed86906dac22f88f1f4331873eb2da3152a3e77", + "NAABHVFJDBM74XMJJ52R7QN2MTTG2ZUXPQS62QZ7", + }, + { + "c56bc16ecf727878c15e24f4ae68569600ac7b251218a44ef50ce54175776edc", + "c92f761e6d83d20068fd46fe4bd5b97f4c6ba05d23180679b718d1f3e4fb066e", + "NCLK3OLMHR3F2E3KSBUIZ4K5PNWUDN37MLSJBJZP", + }, + { + "9dd73599283882fa1561ddfc9be5830b5dd453c90465d3fe5eeb646a3606374e", + "eaf16a4833e59370a04ccd5c63395058de34877b48c17174c71db5ed37b537ed", + "ND3AHW4VTI5R5QE5V44KIGPRU5FBJ5AFUCJXOY5H", + }, + { + "d9639dc6f49dad02a42fd8c217f1b1b4f8ce31ccd770388b645e639c72ff24fa", + "0f74a2f537cd9c986df018994dde75bdeee05e35eb9fe27adf506ca8475064f7", + "NCTZ4YAP43ONK3UYTASQVNDMBO24ZHJE65F3QPYE", + }, + { + "efc1992cd50b70ca55ac12c07aa5d026a8b78ffe28a7dbffc9228b26e02c38c1", + "2ebff201255f6cf948c78f528658b99a7c13ac791942fa22d59af610558111f5", + "NDQ2TMCMXBSFPZQPE2YKH6XLC24HD6LUMN6Z4GIC", + }, + { + "143a815e92e43f3ed1a921ee48cd143931b88b7c3d8e1e981f743c2a5be3c5ba", + "419ed11d48730e4ae2c93f0ea4df853b8d578713a36dab227517cf965861af4e", + "NA32IDDW2C53BDSBJNFL3Z6UU3J5CJZJMCZDXCF4", + }, + { + "bc1a082f5ac6fdd3a83ade211e5986ac0551bad6c7da96727ec744e5df963e2a", + "a160e6f9112233a7ce94202ed7a4443e1dac444b5095f9fecbb965fba3f92cac", + "NADUCEQLC3FTGB25GTA5HOUTB53CBVQNVOIP7NTJ", + }, + { + "4e47b4c6f4c7886e49ec109c61f4af5cfbb1637283218941d55a7f9fe1053f72", + "fbb91b16df828e21a9802980a44fc757c588bc1382a4cea429d6fa2ae0333f56", + "NBAF3BFLLPWH33MYE6VUPP5T6DQBZBKIDEQKZQOE", + }, + { + "efc4389da48ce49f85365cfa578c746530e9eac42db1b64ec346119b1becd347", + "2232f24dda0f2ded3ecd831210d4e8521a096b50cadd5a34f3f7083374e1ec12", + "NBOGTK2I2ATOGGD7ZFJHROG5MWL7XCKAUKSWIVSA", + }, + { + "bdba57c78ca7da16a3360efd13f06276284db8c40351de7fcd38ba0c35ac754d", + "c334c6c0dad5aaa2a0d0fb4c6032cb6a0edd96bf61125b5ea9062d5a00ee0eee", + "NCLERTEFYXKLK7RA4MVACEFMXMK3P7QMWTM7FBW2", + }, + { + "20694c1ec3c4a311bcdb29ed2edc428f6d4f9a4c429ad6a5bf3222084e35695f", + "518c4de412efa93de06a55947d11f697639443916ec8fcf04ebc3e6d17d0bd93", + "NB5V4BPIJHXVONO7UGMJDPFARMFA73BOBNOOYCOV", + }, + { + "e0d4f3760ac107b33c22c2cac24ab2f520b282684f5f66a4212ff95d926323ce", + "b3d16f4ead9de67c290144da535a0ed2504b03c05e5f1ceb8c7863762f786857", + "NC4PBAO5TPCAVQKBVOC4F6DMZP3CFSQBU46PSKBD", + }, + { + "efa9afc617412093c9c7a7c211a5332dd556f941e1a88c494ec860608610eea2", + "7e7716e4cebceb731d6f1fd28676f34888e9a0000fcfa1471db1c616c2ddf559", + "NCFW2LPXIWLBWAQN2QVIWEOD7IVDO3HQBD2OU56K", + }, + { + "d98499b3db61944684ce06a91735af4e14105338473fcf6ebe2b0bcada3dfd21", + "114171230ad6f8522a000cdc73fbc5c733b30bb71f2b146ccbdf34499f79a810", + "NCUKWDY3J3THKQHAKOK5ALF6ANJQABZHCH7VN6DP", + }, + }; + + HDNode node; + ed25519_secret_key private_key; + uint8_t chain_code[32]; + char address[41]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + nem_private_key(tests[i].private_key, private_key); + + ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, + ED25519_KECCAK_NAME, &node)); + + ck_assert(hdnode_get_nem_address(&node, NEM_NETWORK_MAINNET, address)); + ck_assert_str_eq(address, tests[i].address); + + ck_assert_mem_eq(&node.public_key[1], fromhex(tests[i].public_key), 32); + } } END_TEST -// test vectors from https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/3.test-derive.dat -START_TEST(test_nem_derive) -{ - static const struct { - const char *salt; - const char *private_key; - const char *public_key; - const char *mul; - const char *shared_key; - } tests[] = { - { "ad63ac08f9afc85eb0bf4f8881ca6eaa0215924c87aa2f137d56109bb76c6f98", "e8857f8e488d4e6d4b71bcd44bb4cff49208c32651e1f6500c3b58cafeb8def6", "9d8e5f200b05a2638fb084a375408cabd6d5989590d96e3eea5f2cb34668178e", "a8352060ba5718745ee4d78b9df564e0fbe13f50d50ab15a8dd524159d81d18b", "990a5f611c65fbcde735378bdec38e1039c5466503511e8c645bbe42795c752b", }, - { "96104f0a28f9cca40901c066cd435134662a3b053eb6c8df80ee0d05dc941963", "d7f67b5f52cbcd1a1367e0376a8eb1012b634acfcf35e8322bae8b22bb9e8dea", "9735c92d150dcee0ade5a8d1822f46a4db22c9cda25f33773ae856fe374a3e8a", "ea14d521d83328dba70982d42094300585818cc2da609fdb1f73bb32235576ff", "b498aa21d4ba4879ea9fd4225e93bacc760dcd9c119f8f38ab0716457d1a6f85", }, - { "d8f94a0bbb1de80aea17aab42e2ffb982e73fc49b649a318479e951e392d8728", "d026ddb445fb3bbf3020e4b55ed7b5f9b7fd1278c34978ca1a6ed6b358dadbae", "d19e6beca3b26b9d1abc127835ebeb7a6c19c33dec8ec472e1c4d458202f4ec8", "0d561f54728ad837ae108ec66c2ece2bb3b26041d3ee9b77fdc6d36d9ebfb2e3", "d012afe3d1d932304e613c91545bf571cf2c7281d6cafa8e81393a551f675540", }, - { "3f8c969678a8abdbfb76866a142c284a6f01636c1c1607947436e0d2c30d5245", "c522b38c391d1c3fa539cc58802bc66ac34bb3c73accd7f41b47f539bedcd016", "ea5b6a0053237f7712b1d2347c447d3e83e0f2191762d07e1f53f8eb7f2dfeaa", "23cccd3b63a9456e4425098b6df36f28c8999461a85e4b2b0c8d8f53c62c9ea9", "7e27efa50eed1c2ac51a12089cbab6a192624709c7330c016d5bc9af146584c1", }, - { "e66415c58b981c7f1f2b8f45a42149e9144616ff6de49ff83d97000ac6f6f992", "2f1b82be8e65d610a4e588f000a89a733a9de98ffc1ac9d55e138b3b0a855da0", "65aeda1b47f66c978a4a41d4dcdfbd8eab5cdeb135695c2b0c28f54417b1486d", "43e5b0a5cc8146c03ac63e6f8cf3d8825a9ca1ed53ea4a88304af4ddf5461b33", "bb4ab31c334e55d378937978c90bb33779b23cd5ef4c68342a394f4ec8fa1ada", }, - { "58487c9818c9d28ddf97cb09c13331941e05d0b62bf4c35ee368de80b552e4d1", "f3869b68183b2e4341307653e8f659bd7cd20e37ea5c00f5a9e203a8fa92359a", "c7e4153a18b4162f5c1f60e1ba483264aa5bb3f4889dca45b434fcd30b9cf56f", "5ae9408ab3156b8828c3e639730bd5e5db93d7afe2cee3fcda98079316c5bb3a", "0224d85ae8f17bfe127ec24b8960b7639a0dbde9c8c39a0575b939448687bb14", }, - { "ad66f3b654844e53d6fb3568134fae75672ba63868c113659d3ca58c2c39d24f", "d38f2ef8dfdc7224fef596130c3f4ff68ac83d3f932a56ee908061466ac28572", "d0c79d0340dc66f0a895ce5ad60a933cf6be659569096fb9d4b81e5d32292372", "1ea22db4708ed585ab541a4c70c3069f8e2c0c1faa188ddade3efaa53c8329f6", "886a7187246934aedf2794748deadfe038c9fd7e78d4b7be76c5a651440ac843", }, - { "eed48604eab279c6ad8128aa83483a3da0928271a4cae1a5745671284e1fb89d", "e2342a8450fc0adfa0ea2fbd0b1d28f100f0a3a905a3da29de34d1353afa7df7", "d2dbe07e0f2dbc3dbb01c70092e3c4247d12827ddcd8d76534fd740a65c30de2", "4c4b30eb6a2bfa17312f5729b4212cb51c2eee8fbfaea82a0e957ca68f4f6a30", "dcae613ac5641ff9d4c3ca58632245f93b0b8657fe4d48bac7b062cc53dd21ad", }, - { "f35b315287b268c0d0b386fb5b31810f65e1c4497cffae24527f69a3abac3884", "049016230dbef7a14a439e5ab2f6d12e78cb8df127db4e0c312673b3c361e350", "1b3b1925a8a535cd7d78725d25298f45bba8ca3dee2cdaabf14241c9b51b37c4", "04c9685dae1f8eb72a6438f24a87dc83a56d79c9024edf7e01aa1ae34656f29e", "b48469d0428c223b93cd1fe34bb2cafd3fb78a8fa15f98f89f1ac9c0ce7c9001", }, - { "d6cf082c5d9a96e756a94a2e27703138580a7c7c1af505c96c3abf7ab6802e1d", "67cd02b0b8b0adcf6fdd4d4d64a1f4193ced68bb8605d0ec941a62011326d140", "a842d5127c93a435e4672dcadd9fccbfd0e9208c79c5404848b298597eccdbdb", "d5c6bd6d81b99659d0bafe91025b6ecf73b16c6b07931cf44718b13f00fde3f7", "8aa160795b587f4be53aa35d26e9b618b4cd6ec765b523bc908e53c258ca8fd4", }, - { "dda32c91c95527a645b00dd05d13f0b98ed612a726ce5f5221431430b7660944", "eba026f92a8ffb5e95060a22e15d597fe838a99a0b2bbcb423c933b6bc718c50", "7dbaf9c313a1ff9128c54d6cd740c7d0cc46bca588e7910d438dd619ca4fd69a", "5bb20a145de83ba27a0c261e1f54bfd7dcea61888fc2eebbe6166876f7b000b8", "3a96f152ad8bf355cccb307e4a40108aa17f8e925522a2b5bb0b3f1e1a262914", }, - { "63c500acbd4ff747f7dadde7d3286482894ac4d7fe68f396712bca29879aa65c", "9663cd3c2030a5fe4a3ea3cc9a1d182b3a63ade68616aaeb4caf40b495f6f227", "b1e7d9070ac820d986d839b79f7aa594dcf708473529dad87af8682cc6197374", "1f7a97584d8db9f395b9ac4447de4b33c5c1f5020187cd4996286a49b07eb8a7", "4d2a974ec12dcf525b5654d31053460850c3092648b7e15598b7131d2930e9fb", }, - { "91f340961029398cc8bcd906388044a6801d24328efdf919d8ed0c609862a073", "45a588500d00142e2226231c01fd11ac6f842ab6a85872418f5b6a1999f8bd98", "397233c96069b6f4a57d6e93f759fa327222eaef71fc981afa673b248206df3f", "062123ef9782e3893f7b2e1d557b4ecce92b9f9aa8577e76380f228b75152f84", "235848cb04230a16d8978aa7c19fe7fbff3ebe29389ea6eb24fb8bc3cb50afc6", }, - { "46120b4da6ba4eb54fb65213cfef99b812c86f7c42a1de1107f8e8c12c0c3b6b", "cc19a97a99ad71ce348bcf831c0218e6a1f0a8d52186cabe6298b56f24e640f9", "c54631bb62f0f9d86b3301fcb2a671621e655e578c95504af5f78da83f7fec4f", "ab73cc20c75260ff3a7cefea8039291d4d15114a07a9250375628cca32225bb6", "70040a360b6a2dfa881272ef4fa6616e2e8fcc45194fa2a21a1eef1160271cd5", }, - { "f0a69ded09f1d731ab9561d0c3a40b7ef30bcb2bf60f92beccd8734e2441403d", "ea732822a381c46a7ac9999bf5ef85e16b7460b26aaf6c1a1c6ffa8c8c82c923", "110decbff79c382b1e60af4259564a3c473087792350b24fca98ae9a74ba9dd9", "81bdee95aecdcf821a9d682f79056f1abdcf1245d2f3b55244447881a283e0d4", "1bc29d4470ccf97d4e35e8d3cd4b12e3ebf2cb0a82425d35984aeedf7ad0f6f9", }, - { "e79cf4536fb1547e57626c0f1a87f71a396fdfb985b00731c0c2876a00645eda", "04213fc02b59c372e3e7f53faa71a2f73b31064102cb6fc8b68432ba7cdf7eb4", "ca1c750aaed53bc30dac07d0696ed86bcd7cdbbcbd3d15bb90d90cb5c6117bac", "c68cd0872a42a3a64e8a229ef7fcad3d722047d5af966f7dda4d4e32d0d57203", "bfdd3d07563d966d95afe4b8abea4b567265fceea8c4ecddb0946256c33e07b2", }, - { "81a40db4cddaf076e0206bd2b0fa7470a72cc456bad34aa3a0469a4859f286be", "52156799fd86cc63345cdbffd65ef4f5f8df0ffd9906a40af5f41d269bbcff5d", "54d61aa0b0b17a87f1376fe89cd8cd6b314827c1f1b9e5e7b20e7a7eee2a8335", "4553fb2cab8555068c32f86ceb692bbf1c2beeaf21627ef1b1be57344b52eea8", "55096b6710ade3bbe38702458ee13faa10c24413261bc076f17675dcbf2c4ee6", }, - { "d28e4a9e6832a3a4dad014a2bf1f666f01093cbba8b9ad4d1dcad3ea10cb42b9", "8ca134404c8fa199b0c72cb53cfa0adcf196dfa560fb521017cce5cbace3ba59", "3a6c39a1e5f9f550f1debedd9a0bc84210cce5f9834797db8f14122bf5817e45", "eb632ca818b4f659630226a339a3ce536b31c8e1e686fea8da3760e8abc20b8e", "9fbb3fbaf1cd54ee0cd90685f59b082545983f1f662ef701332379306a6ad546", }, - { "f9c4bfad9e2a3d98c44c12734881a6f217d6c9523cc210772fad1297993454b4", "b85960fcadda8d0a0960559b6b7818a0d8d4574b4e928b17c9b498fa9ffab4ef", "6a1d0ef23ce0b40a7077ecb7b7264945054e3bdb58ee25e1b0ee8b3e19dbfcdc", "bb145dddcb75074a6a03249fca1aa7d6fa9549e3ed965f138ca5e7071b7878f2", "87d3faea4a98e41009eb8625611ea0fc12094c295af540c126c14a0f55afa76e", }, - { "656df4789a369d220aceb7b318517787d27004ecccedea019d623bcb2d79f5ff", "acf83e30afb2a5066728ec5d93564c08abe5e68e3a2a2ff953bdcf4d44f9da06", "bdda65efe56d7890286aada1452f62f85ba157d0b4621ba641de15d8d1c9e331", "958beef5dc6babc6de383c32ad7dd3a6d6eb8bb3236ed5558eec0f9eb31e5458", "6f6d4ee36d9d76e462c9635adfbb6073134a276cfc7cb86762004ec47197afa0", }, - }; - - HDNode node; - ed25519_secret_key private_key; - uint8_t chain_code[32]; - ed25519_public_key public_key, mul; - uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - nem_private_key(tests[i].private_key, private_key); - - ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, ED25519_KECCAK_NAME, &node)); - memcpy(public_key, fromhex(tests[i].public_key), 32); - - ck_assert(hdnode_get_nem_shared_key(&node, public_key, fromhex(tests[i].salt), mul, shared_key)); - ck_assert_mem_eq(mul, fromhex(tests[i].mul), sizeof(mul)); - ck_assert_mem_eq(shared_key, fromhex(tests[i].shared_key), sizeof(shared_key)); - } +// test vectors from +// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/3.test-derive.dat +START_TEST(test_nem_derive) { + static const struct { + const char *salt; + const char *private_key; + const char *public_key; + const char *mul; + const char *shared_key; + } tests[] = { + { + "ad63ac08f9afc85eb0bf4f8881ca6eaa0215924c87aa2f137d56109bb76c6f98", + "e8857f8e488d4e6d4b71bcd44bb4cff49208c32651e1f6500c3b58cafeb8def6", + "9d8e5f200b05a2638fb084a375408cabd6d5989590d96e3eea5f2cb34668178e", + "a8352060ba5718745ee4d78b9df564e0fbe13f50d50ab15a8dd524159d81d18b", + "990a5f611c65fbcde735378bdec38e1039c5466503511e8c645bbe42795c752b", + }, + { + "96104f0a28f9cca40901c066cd435134662a3b053eb6c8df80ee0d05dc941963", + "d7f67b5f52cbcd1a1367e0376a8eb1012b634acfcf35e8322bae8b22bb9e8dea", + "9735c92d150dcee0ade5a8d1822f46a4db22c9cda25f33773ae856fe374a3e8a", + "ea14d521d83328dba70982d42094300585818cc2da609fdb1f73bb32235576ff", + "b498aa21d4ba4879ea9fd4225e93bacc760dcd9c119f8f38ab0716457d1a6f85", + }, + { + "d8f94a0bbb1de80aea17aab42e2ffb982e73fc49b649a318479e951e392d8728", + "d026ddb445fb3bbf3020e4b55ed7b5f9b7fd1278c34978ca1a6ed6b358dadbae", + "d19e6beca3b26b9d1abc127835ebeb7a6c19c33dec8ec472e1c4d458202f4ec8", + "0d561f54728ad837ae108ec66c2ece2bb3b26041d3ee9b77fdc6d36d9ebfb2e3", + "d012afe3d1d932304e613c91545bf571cf2c7281d6cafa8e81393a551f675540", + }, + { + "3f8c969678a8abdbfb76866a142c284a6f01636c1c1607947436e0d2c30d5245", + "c522b38c391d1c3fa539cc58802bc66ac34bb3c73accd7f41b47f539bedcd016", + "ea5b6a0053237f7712b1d2347c447d3e83e0f2191762d07e1f53f8eb7f2dfeaa", + "23cccd3b63a9456e4425098b6df36f28c8999461a85e4b2b0c8d8f53c62c9ea9", + "7e27efa50eed1c2ac51a12089cbab6a192624709c7330c016d5bc9af146584c1", + }, + { + "e66415c58b981c7f1f2b8f45a42149e9144616ff6de49ff83d97000ac6f6f992", + "2f1b82be8e65d610a4e588f000a89a733a9de98ffc1ac9d55e138b3b0a855da0", + "65aeda1b47f66c978a4a41d4dcdfbd8eab5cdeb135695c2b0c28f54417b1486d", + "43e5b0a5cc8146c03ac63e6f8cf3d8825a9ca1ed53ea4a88304af4ddf5461b33", + "bb4ab31c334e55d378937978c90bb33779b23cd5ef4c68342a394f4ec8fa1ada", + }, + { + "58487c9818c9d28ddf97cb09c13331941e05d0b62bf4c35ee368de80b552e4d1", + "f3869b68183b2e4341307653e8f659bd7cd20e37ea5c00f5a9e203a8fa92359a", + "c7e4153a18b4162f5c1f60e1ba483264aa5bb3f4889dca45b434fcd30b9cf56f", + "5ae9408ab3156b8828c3e639730bd5e5db93d7afe2cee3fcda98079316c5bb3a", + "0224d85ae8f17bfe127ec24b8960b7639a0dbde9c8c39a0575b939448687bb14", + }, + { + "ad66f3b654844e53d6fb3568134fae75672ba63868c113659d3ca58c2c39d24f", + "d38f2ef8dfdc7224fef596130c3f4ff68ac83d3f932a56ee908061466ac28572", + "d0c79d0340dc66f0a895ce5ad60a933cf6be659569096fb9d4b81e5d32292372", + "1ea22db4708ed585ab541a4c70c3069f8e2c0c1faa188ddade3efaa53c8329f6", + "886a7187246934aedf2794748deadfe038c9fd7e78d4b7be76c5a651440ac843", + }, + { + "eed48604eab279c6ad8128aa83483a3da0928271a4cae1a5745671284e1fb89d", + "e2342a8450fc0adfa0ea2fbd0b1d28f100f0a3a905a3da29de34d1353afa7df7", + "d2dbe07e0f2dbc3dbb01c70092e3c4247d12827ddcd8d76534fd740a65c30de2", + "4c4b30eb6a2bfa17312f5729b4212cb51c2eee8fbfaea82a0e957ca68f4f6a30", + "dcae613ac5641ff9d4c3ca58632245f93b0b8657fe4d48bac7b062cc53dd21ad", + }, + { + "f35b315287b268c0d0b386fb5b31810f65e1c4497cffae24527f69a3abac3884", + "049016230dbef7a14a439e5ab2f6d12e78cb8df127db4e0c312673b3c361e350", + "1b3b1925a8a535cd7d78725d25298f45bba8ca3dee2cdaabf14241c9b51b37c4", + "04c9685dae1f8eb72a6438f24a87dc83a56d79c9024edf7e01aa1ae34656f29e", + "b48469d0428c223b93cd1fe34bb2cafd3fb78a8fa15f98f89f1ac9c0ce7c9001", + }, + { + "d6cf082c5d9a96e756a94a2e27703138580a7c7c1af505c96c3abf7ab6802e1d", + "67cd02b0b8b0adcf6fdd4d4d64a1f4193ced68bb8605d0ec941a62011326d140", + "a842d5127c93a435e4672dcadd9fccbfd0e9208c79c5404848b298597eccdbdb", + "d5c6bd6d81b99659d0bafe91025b6ecf73b16c6b07931cf44718b13f00fde3f7", + "8aa160795b587f4be53aa35d26e9b618b4cd6ec765b523bc908e53c258ca8fd4", + }, + { + "dda32c91c95527a645b00dd05d13f0b98ed612a726ce5f5221431430b7660944", + "eba026f92a8ffb5e95060a22e15d597fe838a99a0b2bbcb423c933b6bc718c50", + "7dbaf9c313a1ff9128c54d6cd740c7d0cc46bca588e7910d438dd619ca4fd69a", + "5bb20a145de83ba27a0c261e1f54bfd7dcea61888fc2eebbe6166876f7b000b8", + "3a96f152ad8bf355cccb307e4a40108aa17f8e925522a2b5bb0b3f1e1a262914", + }, + { + "63c500acbd4ff747f7dadde7d3286482894ac4d7fe68f396712bca29879aa65c", + "9663cd3c2030a5fe4a3ea3cc9a1d182b3a63ade68616aaeb4caf40b495f6f227", + "b1e7d9070ac820d986d839b79f7aa594dcf708473529dad87af8682cc6197374", + "1f7a97584d8db9f395b9ac4447de4b33c5c1f5020187cd4996286a49b07eb8a7", + "4d2a974ec12dcf525b5654d31053460850c3092648b7e15598b7131d2930e9fb", + }, + { + "91f340961029398cc8bcd906388044a6801d24328efdf919d8ed0c609862a073", + "45a588500d00142e2226231c01fd11ac6f842ab6a85872418f5b6a1999f8bd98", + "397233c96069b6f4a57d6e93f759fa327222eaef71fc981afa673b248206df3f", + "062123ef9782e3893f7b2e1d557b4ecce92b9f9aa8577e76380f228b75152f84", + "235848cb04230a16d8978aa7c19fe7fbff3ebe29389ea6eb24fb8bc3cb50afc6", + }, + { + "46120b4da6ba4eb54fb65213cfef99b812c86f7c42a1de1107f8e8c12c0c3b6b", + "cc19a97a99ad71ce348bcf831c0218e6a1f0a8d52186cabe6298b56f24e640f9", + "c54631bb62f0f9d86b3301fcb2a671621e655e578c95504af5f78da83f7fec4f", + "ab73cc20c75260ff3a7cefea8039291d4d15114a07a9250375628cca32225bb6", + "70040a360b6a2dfa881272ef4fa6616e2e8fcc45194fa2a21a1eef1160271cd5", + }, + { + "f0a69ded09f1d731ab9561d0c3a40b7ef30bcb2bf60f92beccd8734e2441403d", + "ea732822a381c46a7ac9999bf5ef85e16b7460b26aaf6c1a1c6ffa8c8c82c923", + "110decbff79c382b1e60af4259564a3c473087792350b24fca98ae9a74ba9dd9", + "81bdee95aecdcf821a9d682f79056f1abdcf1245d2f3b55244447881a283e0d4", + "1bc29d4470ccf97d4e35e8d3cd4b12e3ebf2cb0a82425d35984aeedf7ad0f6f9", + }, + { + "e79cf4536fb1547e57626c0f1a87f71a396fdfb985b00731c0c2876a00645eda", + "04213fc02b59c372e3e7f53faa71a2f73b31064102cb6fc8b68432ba7cdf7eb4", + "ca1c750aaed53bc30dac07d0696ed86bcd7cdbbcbd3d15bb90d90cb5c6117bac", + "c68cd0872a42a3a64e8a229ef7fcad3d722047d5af966f7dda4d4e32d0d57203", + "bfdd3d07563d966d95afe4b8abea4b567265fceea8c4ecddb0946256c33e07b2", + }, + { + "81a40db4cddaf076e0206bd2b0fa7470a72cc456bad34aa3a0469a4859f286be", + "52156799fd86cc63345cdbffd65ef4f5f8df0ffd9906a40af5f41d269bbcff5d", + "54d61aa0b0b17a87f1376fe89cd8cd6b314827c1f1b9e5e7b20e7a7eee2a8335", + "4553fb2cab8555068c32f86ceb692bbf1c2beeaf21627ef1b1be57344b52eea8", + "55096b6710ade3bbe38702458ee13faa10c24413261bc076f17675dcbf2c4ee6", + }, + { + "d28e4a9e6832a3a4dad014a2bf1f666f01093cbba8b9ad4d1dcad3ea10cb42b9", + "8ca134404c8fa199b0c72cb53cfa0adcf196dfa560fb521017cce5cbace3ba59", + "3a6c39a1e5f9f550f1debedd9a0bc84210cce5f9834797db8f14122bf5817e45", + "eb632ca818b4f659630226a339a3ce536b31c8e1e686fea8da3760e8abc20b8e", + "9fbb3fbaf1cd54ee0cd90685f59b082545983f1f662ef701332379306a6ad546", + }, + { + "f9c4bfad9e2a3d98c44c12734881a6f217d6c9523cc210772fad1297993454b4", + "b85960fcadda8d0a0960559b6b7818a0d8d4574b4e928b17c9b498fa9ffab4ef", + "6a1d0ef23ce0b40a7077ecb7b7264945054e3bdb58ee25e1b0ee8b3e19dbfcdc", + "bb145dddcb75074a6a03249fca1aa7d6fa9549e3ed965f138ca5e7071b7878f2", + "87d3faea4a98e41009eb8625611ea0fc12094c295af540c126c14a0f55afa76e", + }, + { + "656df4789a369d220aceb7b318517787d27004ecccedea019d623bcb2d79f5ff", + "acf83e30afb2a5066728ec5d93564c08abe5e68e3a2a2ff953bdcf4d44f9da06", + "bdda65efe56d7890286aada1452f62f85ba157d0b4621ba641de15d8d1c9e331", + "958beef5dc6babc6de383c32ad7dd3a6d6eb8bb3236ed5558eec0f9eb31e5458", + "6f6d4ee36d9d76e462c9635adfbb6073134a276cfc7cb86762004ec47197afa0", + }, + }; + + HDNode node; + ed25519_secret_key private_key; + uint8_t chain_code[32]; + ed25519_public_key public_key, mul; + uint8_t shared_key[SHA3_256_DIGEST_LENGTH]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + nem_private_key(tests[i].private_key, private_key); + + ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, + ED25519_KECCAK_NAME, &node)); + memcpy(public_key, fromhex(tests[i].public_key), 32); + + ck_assert(hdnode_get_nem_shared_key( + &node, public_key, fromhex(tests[i].salt), mul, shared_key)); + ck_assert_mem_eq(mul, fromhex(tests[i].mul), sizeof(mul)); + ck_assert_mem_eq(shared_key, fromhex(tests[i].shared_key), + sizeof(shared_key)); + } } END_TEST -// test vectors from https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/4.test-cipher.dat -START_TEST(test_nem_cipher) -{ - static const struct { - const char *private_key; - const char *public_key; - const char *salt; - const char *iv; - const char *input; - const char *output; - } tests[] = { - { "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", "83616c67f076d356fd1288a6e0fd7a60488ba312a3adf0088b1b33c7655c3e6a", "a73ff5c32f8fd055b09775817a6a3f95", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "70815da779b1b954d7a7f00c16940e9917a0412a06a444b539bf147603eef87f", }, - { "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", "703ce0b1d276b10eef35672df03234385a903460db18ba9d4e05b3ad31abb284", "91246c2d5493867c4fa3e78f85963677", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "564b2f40d42c0efc1bd6f057115a5abd1564cae36d7ccacf5d825d38401aa894", }, - { "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", "b22e8e8e7373ac31ca7f0f6eb8b93130aba5266772a658593f3a11792e7e8d92", "9f8e33d82374dad6aac0e3dbe7aea704", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "7cab88d00a3fc656002eccbbd966e1d5d14a3090d92cf502cdbf843515625dcf", }, - { "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", "af646c54cd153dffe453b60efbceeb85c1e95a414ea0036c4da94afb3366f5d9", "6acdf8e01acc8074ddc807281b6af888", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "aa70543a485b63a4dd141bb7fd78019092ac6fad731e914280a287c7467bae1a", }, - { "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", "d9c0d386636c8a024935c024589f9cd39e820a16485b14951e690a967830e269", "f2e9f18aeb374965f54d2f4e31189a8f", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "33d97c216ea6498dfddabf94c2e2403d73efc495e9b284d9d90aaff840217d25", }, - { "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", "06c227baac1ae3b0b1dc583f4850f13f9ba5d53be4a98fa5c3ea16217847530d", "3735123e78c44895df6ea33fa57e9a72", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "d5b5d66ba8cee0eb7ecf95b143fa77a46d6de13749e12eff40f5a7e649167ccb", }, - { "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", "92f55ba5bc6fc2f23e3eedc299357c71518e36ba2447a4da7a9dfe9dfeb107b5", "1cbc4982e53e370052af97ab088fa942", "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", "d48ef1ef526d805656cfc932aff259eadb17aa3391dde1877a722cba31d935b2", }, - { "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", "10f15a39ba49866292a43b7781bc71ca8bbd4889f1616461caf056bcb91b0158", "c40d531d92bfee969dce91417346c892", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "e6d75afdb542785669b42198577c5b358d95397d71ec6f5835dca46d332cc08dbf73ea790b7bcb169a65719c0d55054c", }, - { "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", "9c01ed42b219b3bbe1a43ae9d7af5c1dd09363baacfdba8f4d03d1046915e26e", "059a35d5f83249e632790015ed6518b9", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "5ef11aadff2eccee8b712dab968fa842eb770818ec0e6663ed242ea8b6bbc1c66d6285ee5b5f03d55dfee382fb4fa25d", }, - { "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", "bc1067e2a7415ea45ff1ca9894338c591ff15f2e57ae2789ae31b9d5bea0f11e", "8c73f0d6613898daeefa3cf8b0686d37", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "6d220213b1878cd40a458f2a1e6e3b48040455fdf504dcd857f4f2ca1ad642e3a44fc401d04e339d302f66a9fad3d919", }, - { "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", "cf4a21cb790552165827b678ca9695fcaf77566d382325112ff79483455de667", "bfbf5482e06f55b88bdd9e053b7eee6e", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "1198a78c29c215d5c450f7b8513ead253160bc9fde80d9cc8e6bee2efe9713cf5a09d6293c41033271c9e8c22036a28b", }, - { "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", "eba5eae8aef79114082c3e70baef95bb02edf13b3897e8be7a70272962ef8838", "af9a56da3da18e2fbd2948a16332532b", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "1062ab5fbbdee9042ad35bdadfd3047c0a2127fe0f001da1be1b0582185edfc9687be8d68f85795833bb04af9cedd3bb", }, - { "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", "518f8dfd0c138f1ffb4ea8029db15441d70abd893c3d767dc668f23ba7770e27", "42d28307974a1b2a2d921d270cfce03b", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "005e49fb7c5da540a84b034c853fc9f78a6b901ea495aed0c2abd4f08f1a96f9ffefc6a57f1ac09e0aea95ca0f03ffd8", }, - { "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", "582fdf58b53715c26e10ba809e8f2ab70502e5a3d4e9a81100b7227732ab0bbc", "91f2aad3189bb2edc93bc891e73911ba", "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a4", "821a69cb16c57f0cb866e590b38069e35faec3ae18f158bb067db83a11237d29ab1e6b868b3147236a0958f15c2e2167", }, - { "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", "a415b4c006118fb72fc37b2746ef288e23ac45c8ff7ade5f368a31557b6ac93a", "2b7c5f75606c0b8106c6489ea5657a9e", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "2781d5ee8ef1cb1596f8902b33dfae5045f84a987ca58173af5830dbce386062", }, - { "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", "47e73ec362ea82d3a7c5d55532ad51d2cdf5316b981b2b2bd542b0efa027e8ea", "b2193f59030c8d05a7d3577b7f64dd33", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "3f43912db8dd6672b9996e5272e18c4b88fec9d7e8372db9c5f4709a4af1d86f", }, - { "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", "aaa006c57b6d1e402650577fe9787d8d285f4bacd7c01f998be49c766f8860c7", "130304ddb9adc8870cf56bcae9487b7f", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "878cc7d8c0ef8dac0182a78eedc8080a402f59d8062a6b4ca8f4a74f3c3b3de7", }, - { "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", "28dc7ccd6c2a939eef64b8be7b9ae248295e7fcd8471c22fa2f98733fea97611", "cb13890d3a11bc0a7433738263006710", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "e74ded846bebfa912fa1720e4c1415e6e5df7e7a1a7fedb5665d68f1763209a4", }, - { "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", "79974fa2cad95154d0873902c153ccc3e7d54b17f2eeb3f29b6344cad9365a9a", "22123357979d20f44cc8eb0263d84e0e", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "eb14dec7b8b64d81a2ee4db07b0adf144d4f79a519bbf332b823583fa2d45405", }, - { "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", "3409a6f8c4dcd9bd04144eb67e55a98696b674735b01bf1196191f29871ef966", "a823a0965969380ea1f8659ea5fd8fdd", "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", "00a7eb708eae745847173f8217efb05be13059710aee632e3f471ac3c6202b51", }, - { "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10", "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c", "c25701b9b7328c4ac3d23223d10623bd527c0a98e38ae9c62fbc403c80ab20ae", "4b4ee0e4443779f3af429a749212f476", "b6926d0ec82cec86c0d27ec9a33a0e0f", "f39f7d66e0fde39ecdf58be2c0ef361a17cfd6843e310adbe0ec3118cd72800d", }, - { "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10", "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c", "31d18fdffc480310828778496ff817039df5d6f30bf6d9edd0b4396863d05f93", "418bcbdf52860a450bfacc96920d02cf", "b6926d0ec82cec86c0d27ec9a33a0e0f", "0e6ce9889fe7b3cd82794b0ae27c1f5985d2f2a1f398371a138f8db1df1f54de", }, - { "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", "56b4c645f81dbfb6ba0c6d3f1626e1e5cd648eeb36562715f7cd7e9ea86a0d7f", "dc9bdce76d68d2e4d72267cf4e72b022", "b6926d0ec82cec86c0d27ec9a33a0e0f", "dc6f046c3008002041517a7c4f3ababe609cf02616fcccda39c075d1be4175f5", }, - { "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", "df180b91986c8c7000792f96d1faa61e30138330430a402322be1855089b0e7f", "ccf9b77341c866465b474e2f4a3b1cf8", "b6926d0ec82cec86c0d27ec9a33a0e0f", "94e4ae89041437f39826704f02cb5d775226f34344635e592846417497a5020b", }, - { "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", "a0eee7e84c76e63fdae6e938b43330775eaf17d260e40b98c9e6616b668102a7", "662c681cfec6f6d052ff0e2c1255f2c2", "b6926d0ec82cec86c0d27ec9a33a0e0f", "70bba3c48be9c75a144b1888ca3d21a6b21f52eec133981a024390a6a0ba36f9", }, - { "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", "c6acd2d90eb782c3053b366680ffa0e148de81fea198c87bb643869fd97e5cb0", "908dc33ba80520f2f0f04e7890e3a3c0", "b6926d0ec82cec86c0d27ec9a33a0e0f", "f6efe1d76d270aac264aa35d03049d9ce63be1996d543aef00559219c8666f71", }, - }; - - HDNode node; - ed25519_secret_key private_key; - uint8_t chain_code[32]; - ed25519_public_key public_key; - uint8_t salt[sizeof(public_key)]; - - uint8_t iv[AES_BLOCK_SIZE]; - uint8_t buffer[FROMHEX_MAXLEN]; - - uint8_t input[FROMHEX_MAXLEN]; - uint8_t output[FROMHEX_MAXLEN]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - nem_private_key(tests[i].private_key, private_key); - - ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, ED25519_KECCAK_NAME, &node)); - memcpy(public_key, fromhex(tests[i].public_key), 32); - memcpy(salt, fromhex(tests[i].salt), sizeof(salt)); - - size_t input_size = strlen(tests[i].input) / 2; - size_t output_size = strlen(tests[i].output) / 2; - - memcpy(input, fromhex(tests[i].input), input_size); - memcpy(output, fromhex(tests[i].output), output_size); - - memcpy(iv, fromhex(tests[i].iv), sizeof(iv)); - ck_assert(hdnode_nem_encrypt(&node, public_key, iv, salt, input, input_size, buffer)); - ck_assert_int_eq(output_size, NEM_ENCRYPTED_SIZE(input_size)); - ck_assert_mem_eq(buffer, output, output_size); - - memcpy(iv, fromhex(tests[i].iv), sizeof(iv)); - ck_assert(hdnode_nem_decrypt(&node, public_key, iv, salt, output, output_size, buffer)); - ck_assert_int_eq(input_size, NEM_DECRYPTED_SIZE(buffer, output_size)); - ck_assert_mem_eq(buffer, input, input_size); - } +// test vectors from +// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/4.test-cipher.dat +START_TEST(test_nem_cipher) { + static const struct { + const char *private_key; + const char *public_key; + const char *salt; + const char *iv; + const char *input; + const char *output; + } tests[] = { + { + "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", + "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", + "83616c67f076d356fd1288a6e0fd7a60488ba312a3adf0088b1b33c7655c3e6a", + "a73ff5c32f8fd055b09775817a6a3f95", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "70815da779b1b954d7a7f00c16940e9917a0412a06a444b539bf147603eef87f", + }, + { + "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", + "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", + "703ce0b1d276b10eef35672df03234385a903460db18ba9d4e05b3ad31abb284", + "91246c2d5493867c4fa3e78f85963677", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "564b2f40d42c0efc1bd6f057115a5abd1564cae36d7ccacf5d825d38401aa894", + }, + { + "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", + "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", + "b22e8e8e7373ac31ca7f0f6eb8b93130aba5266772a658593f3a11792e7e8d92", + "9f8e33d82374dad6aac0e3dbe7aea704", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "7cab88d00a3fc656002eccbbd966e1d5d14a3090d92cf502cdbf843515625dcf", + }, + { + "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", + "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", + "af646c54cd153dffe453b60efbceeb85c1e95a414ea0036c4da94afb3366f5d9", + "6acdf8e01acc8074ddc807281b6af888", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "aa70543a485b63a4dd141bb7fd78019092ac6fad731e914280a287c7467bae1a", + }, + { + "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6", + "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21", + "d9c0d386636c8a024935c024589f9cd39e820a16485b14951e690a967830e269", + "f2e9f18aeb374965f54d2f4e31189a8f", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "33d97c216ea6498dfddabf94c2e2403d73efc495e9b284d9d90aaff840217d25", + }, + { + "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", + "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", + "06c227baac1ae3b0b1dc583f4850f13f9ba5d53be4a98fa5c3ea16217847530d", + "3735123e78c44895df6ea33fa57e9a72", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "d5b5d66ba8cee0eb7ecf95b143fa77a46d6de13749e12eff40f5a7e649167ccb", + }, + { + "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", + "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", + "92f55ba5bc6fc2f23e3eedc299357c71518e36ba2447a4da7a9dfe9dfeb107b5", + "1cbc4982e53e370052af97ab088fa942", + "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c", + "d48ef1ef526d805656cfc932aff259eadb17aa3391dde1877a722cba31d935b2", + }, + { + "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", + "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", + "10f15a39ba49866292a43b7781bc71ca8bbd4889f1616461caf056bcb91b0158", + "c40d531d92bfee969dce91417346c892", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "e6d75afdb542785669b42198577c5b358d95397d71ec6f5835dca46d332cc08dbf73" + "ea790b7bcb169a65719c0d55054c", + }, + { + "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", + "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", + "9c01ed42b219b3bbe1a43ae9d7af5c1dd09363baacfdba8f4d03d1046915e26e", + "059a35d5f83249e632790015ed6518b9", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "5ef11aadff2eccee8b712dab968fa842eb770818ec0e6663ed242ea8b6bbc1c66d62" + "85ee5b5f03d55dfee382fb4fa25d", + }, + { + "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a", + "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04", + "bc1067e2a7415ea45ff1ca9894338c591ff15f2e57ae2789ae31b9d5bea0f11e", + "8c73f0d6613898daeefa3cf8b0686d37", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "6d220213b1878cd40a458f2a1e6e3b48040455fdf504dcd857f4f2ca1ad642e3a44f" + "c401d04e339d302f66a9fad3d919", + }, + { + "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", + "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", + "cf4a21cb790552165827b678ca9695fcaf77566d382325112ff79483455de667", + "bfbf5482e06f55b88bdd9e053b7eee6e", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "1198a78c29c215d5c450f7b8513ead253160bc9fde80d9cc8e6bee2efe9713cf5a09" + "d6293c41033271c9e8c22036a28b", + }, + { + "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", + "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", + "eba5eae8aef79114082c3e70baef95bb02edf13b3897e8be7a70272962ef8838", + "af9a56da3da18e2fbd2948a16332532b", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "1062ab5fbbdee9042ad35bdadfd3047c0a2127fe0f001da1be1b0582185edfc9687b" + "e8d68f85795833bb04af9cedd3bb", + }, + { + "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", + "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", + "518f8dfd0c138f1ffb4ea8029db15441d70abd893c3d767dc668f23ba7770e27", + "42d28307974a1b2a2d921d270cfce03b", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "005e49fb7c5da540a84b034c853fc9f78a6b901ea495aed0c2abd4f08f1a96f9ffef" + "c6a57f1ac09e0aea95ca0f03ffd8", + }, + { + "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", + "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", + "582fdf58b53715c26e10ba809e8f2ab70502e5a3d4e9a81100b7227732ab0bbc", + "91f2aad3189bb2edc93bc891e73911ba", + "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a" + "4", + "821a69cb16c57f0cb866e590b38069e35faec3ae18f158bb067db83a11237d29ab1e" + "6b868b3147236a0958f15c2e2167", + }, + { + "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921", + "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094", + "a415b4c006118fb72fc37b2746ef288e23ac45c8ff7ade5f368a31557b6ac93a", + "2b7c5f75606c0b8106c6489ea5657a9e", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "2781d5ee8ef1cb1596f8902b33dfae5045f84a987ca58173af5830dbce386062", + }, + { + "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", + "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "47e73ec362ea82d3a7c5d55532ad51d2cdf5316b981b2b2bd542b0efa027e8ea", + "b2193f59030c8d05a7d3577b7f64dd33", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "3f43912db8dd6672b9996e5272e18c4b88fec9d7e8372db9c5f4709a4af1d86f", + }, + { + "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", + "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "aaa006c57b6d1e402650577fe9787d8d285f4bacd7c01f998be49c766f8860c7", + "130304ddb9adc8870cf56bcae9487b7f", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "878cc7d8c0ef8dac0182a78eedc8080a402f59d8062a6b4ca8f4a74f3c3b3de7", + }, + { + "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", + "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "28dc7ccd6c2a939eef64b8be7b9ae248295e7fcd8471c22fa2f98733fea97611", + "cb13890d3a11bc0a7433738263006710", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "e74ded846bebfa912fa1720e4c1415e6e5df7e7a1a7fedb5665d68f1763209a4", + }, + { + "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", + "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "79974fa2cad95154d0873902c153ccc3e7d54b17f2eeb3f29b6344cad9365a9a", + "22123357979d20f44cc8eb0263d84e0e", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "eb14dec7b8b64d81a2ee4db07b0adf144d4f79a519bbf332b823583fa2d45405", + }, + { + "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc", + "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "3409a6f8c4dcd9bd04144eb67e55a98696b674735b01bf1196191f29871ef966", + "a823a0965969380ea1f8659ea5fd8fdd", + "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85", + "00a7eb708eae745847173f8217efb05be13059710aee632e3f471ac3c6202b51", + }, + { + "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10", + "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c", + "c25701b9b7328c4ac3d23223d10623bd527c0a98e38ae9c62fbc403c80ab20ae", + "4b4ee0e4443779f3af429a749212f476", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "f39f7d66e0fde39ecdf58be2c0ef361a17cfd6843e310adbe0ec3118cd72800d", + }, + { + "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10", + "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c", + "31d18fdffc480310828778496ff817039df5d6f30bf6d9edd0b4396863d05f93", + "418bcbdf52860a450bfacc96920d02cf", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "0e6ce9889fe7b3cd82794b0ae27c1f5985d2f2a1f398371a138f8db1df1f54de", + }, + { + "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", + "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", + "56b4c645f81dbfb6ba0c6d3f1626e1e5cd648eeb36562715f7cd7e9ea86a0d7f", + "dc9bdce76d68d2e4d72267cf4e72b022", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "dc6f046c3008002041517a7c4f3ababe609cf02616fcccda39c075d1be4175f5", + }, + { + "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", + "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", + "df180b91986c8c7000792f96d1faa61e30138330430a402322be1855089b0e7f", + "ccf9b77341c866465b474e2f4a3b1cf8", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "94e4ae89041437f39826704f02cb5d775226f34344635e592846417497a5020b", + }, + { + "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", + "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", + "a0eee7e84c76e63fdae6e938b43330775eaf17d260e40b98c9e6616b668102a7", + "662c681cfec6f6d052ff0e2c1255f2c2", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "70bba3c48be9c75a144b1888ca3d21a6b21f52eec133981a024390a6a0ba36f9", + }, + { + "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041", + "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9", + "c6acd2d90eb782c3053b366680ffa0e148de81fea198c87bb643869fd97e5cb0", + "908dc33ba80520f2f0f04e7890e3a3c0", + "b6926d0ec82cec86c0d27ec9a33a0e0f", + "f6efe1d76d270aac264aa35d03049d9ce63be1996d543aef00559219c8666f71", + }, + }; + + HDNode node; + ed25519_secret_key private_key; + uint8_t chain_code[32]; + ed25519_public_key public_key; + uint8_t salt[sizeof(public_key)]; + + uint8_t iv[AES_BLOCK_SIZE]; + uint8_t buffer[FROMHEX_MAXLEN]; + + uint8_t input[FROMHEX_MAXLEN]; + uint8_t output[FROMHEX_MAXLEN]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + nem_private_key(tests[i].private_key, private_key); + + ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key, + ED25519_KECCAK_NAME, &node)); + memcpy(public_key, fromhex(tests[i].public_key), 32); + memcpy(salt, fromhex(tests[i].salt), sizeof(salt)); + + size_t input_size = strlen(tests[i].input) / 2; + size_t output_size = strlen(tests[i].output) / 2; + + memcpy(input, fromhex(tests[i].input), input_size); + memcpy(output, fromhex(tests[i].output), output_size); + + memcpy(iv, fromhex(tests[i].iv), sizeof(iv)); + ck_assert(hdnode_nem_encrypt(&node, public_key, iv, salt, input, input_size, + buffer)); + ck_assert_int_eq(output_size, NEM_ENCRYPTED_SIZE(input_size)); + ck_assert_mem_eq(buffer, output, output_size); + + memcpy(iv, fromhex(tests[i].iv), sizeof(iv)); + ck_assert(hdnode_nem_decrypt(&node, public_key, iv, salt, output, + output_size, buffer)); + ck_assert_int_eq(input_size, NEM_DECRYPTED_SIZE(buffer, output_size)); + ck_assert_mem_eq(buffer, input, input_size); + } } END_TEST -START_TEST(test_nem_transaction_transfer) -{ - nem_transaction_ctx ctx; - - uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; - - // http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f - - nem_transaction_start(&ctx, fromhex("e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_transfer(&ctx, - NEM_NETWORK_TESTNET, 0, NULL, 0, 0, - "TBGIMRE4SBFRUJXMH7DVF2IBY36L2EDWZ37GVSC4", 50000000000000, - NULL, 0, false, - 0)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f"), sizeof(hash)); - - // http://bob.nem.ninja:8765/#/transfer/3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c - - nem_transaction_start(&ctx, fromhex("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_transfer(&ctx, - NEM_NETWORK_TESTNET, 14072100, NULL, 194000000, 14075700, - "TBLOODPLWOWMZ2TARX4RFPOSOWLULHXMROBN2WXI", 3000000, - (uint8_t *) "sending you 3 pairs of paddles\n", 31, false, - 2)); - - ck_assert(nem_transaction_write_mosaic(&ctx, - "gimre.games.pong", "paddles", 2)); - - ck_assert(nem_transaction_write_mosaic(&ctx, - "nem", "xem", 44000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c"), sizeof(hash)); - - // http://chain.nem.ninja/#/transfer/e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb - - nem_transaction_start(&ctx, fromhex("8d07f90fb4bbe7715fa327c926770166a11be2e494a970605f2e12557f66c9b9"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_transfer(&ctx, - NEM_NETWORK_MAINNET, 0, NULL, 0, 0, - "NBT3WHA2YXG2IR4PWKFFMO772JWOITTD2V4PECSB", 5175000000000, - (uint8_t *) "Good luck!", 10, false, - 0)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb"), sizeof(hash)); - - // http://chain.nem.ninja/#/transfer/40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c - - nem_transaction_start(&ctx, fromhex("f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_transfer(&ctx, - NEM_NETWORK_MAINNET, 77229, NULL, 30000000, 80829, - "NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3", 30000000, - fromhex("4d9dcf9186967d30be93d6d5404ded22812dbbae7c3f0de5" - "01bcd7228cba45bded13000eec7b4c6215fc4d3588168c92" - "18167cec98e6977359153a4132e050f594548e61e0dc61c1" - "53f0f53c5e65c595239c9eb7c4e7d48e0f4bb8b1dd2f5ddc"), 96, true, - 0)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c"), sizeof(hash)); - - // http://chain.nem.ninja/#/transfer/882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e - - nem_transaction_start(&ctx, fromhex("f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_transfer(&ctx, - NEM_NETWORK_MAINNET, 26730750, NULL, 179500000, 26734350, - "NBE223WPKEBHQPCYUC4U4CDUQCRRFMPZLOQLB5OP", 1000000, - (uint8_t *) "enjoy! :)", 9, false, - 1)); - - ck_assert(nem_transaction_write_mosaic(&ctx, - "imre.g", "tokens", 1)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e"), sizeof(hash)); +START_TEST(test_nem_transaction_transfer) { + nem_transaction_ctx ctx; + + uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; + + // http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f + + nem_transaction_start( + &ctx, + fromhex( + "e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_transfer( + &ctx, NEM_NETWORK_TESTNET, 0, NULL, 0, 0, + "TBGIMRE4SBFRUJXMH7DVF2IBY36L2EDWZ37GVSC4", 50000000000000, NULL, 0, + false, 0)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f"), + sizeof(hash)); + + // http://bob.nem.ninja:8765/#/transfer/3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c + + nem_transaction_start( + &ctx, + fromhex( + "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_transfer( + &ctx, NEM_NETWORK_TESTNET, 14072100, NULL, 194000000, 14075700, + "TBLOODPLWOWMZ2TARX4RFPOSOWLULHXMROBN2WXI", 3000000, + (uint8_t *)"sending you 3 pairs of paddles\n", 31, false, 2)); + + ck_assert( + nem_transaction_write_mosaic(&ctx, "gimre.games.pong", "paddles", 2)); + + ck_assert(nem_transaction_write_mosaic(&ctx, "nem", "xem", 44000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c"), + sizeof(hash)); + + // http://chain.nem.ninja/#/transfer/e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb + + nem_transaction_start( + &ctx, + fromhex( + "8d07f90fb4bbe7715fa327c926770166a11be2e494a970605f2e12557f66c9b9"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_transfer( + &ctx, NEM_NETWORK_MAINNET, 0, NULL, 0, 0, + "NBT3WHA2YXG2IR4PWKFFMO772JWOITTD2V4PECSB", 5175000000000, + (uint8_t *)"Good luck!", 10, false, 0)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb"), + sizeof(hash)); + + // http://chain.nem.ninja/#/transfer/40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c + + nem_transaction_start( + &ctx, + fromhex( + "f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_transfer( + &ctx, NEM_NETWORK_MAINNET, 77229, NULL, 30000000, 80829, + "NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3", 30000000, + fromhex("4d9dcf9186967d30be93d6d5404ded22812dbbae7c3f0de5" + "01bcd7228cba45bded13000eec7b4c6215fc4d3588168c92" + "18167cec98e6977359153a4132e050f594548e61e0dc61c1" + "53f0f53c5e65c595239c9eb7c4e7d48e0f4bb8b1dd2f5ddc"), + 96, true, 0)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c"), + sizeof(hash)); + + // http://chain.nem.ninja/#/transfer/882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e + + nem_transaction_start( + &ctx, + fromhex( + "f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_transfer( + &ctx, NEM_NETWORK_MAINNET, 26730750, NULL, 179500000, 26734350, + "NBE223WPKEBHQPCYUC4U4CDUQCRRFMPZLOQLB5OP", 1000000, + (uint8_t *)"enjoy! :)", 9, false, 1)); + + ck_assert(nem_transaction_write_mosaic(&ctx, "imre.g", "tokens", 1)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e"), + sizeof(hash)); } END_TEST -START_TEST(test_nem_transaction_multisig) -{ - nem_transaction_ctx ctx, other_trans; - - uint8_t buffer[1024], inner[1024]; - const uint8_t *signature; - - // http://bob.nem.ninja:8765/#/multisig/7d3a7087023ee29005262016706818579a2b5499eb9ca76bad98c1e6f4c46642 - - nem_transaction_start(&other_trans, fromhex("abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"), inner, sizeof(inner)); - - ck_assert(nem_transaction_create_aggregate_modification(&other_trans, - NEM_NETWORK_TESTNET, 3939039, NULL, 16000000, 3960639, - 1, false)); - - ck_assert(nem_transaction_write_cosignatory_modification(&other_trans, 2, fromhex("e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))); - - nem_transaction_start(&ctx, fromhex("59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_multisig(&ctx, - NEM_NETWORK_TESTNET, 3939039, NULL, 6000000, 3960639, - &other_trans)); - - signature = fromhex("933930a8828b560168bddb3137df9252048678d829aa5135fa27bb306ff6562efb92755462988b852b0314bde058487d00e47816b6fb7df6bcfd7e1f150d1d00"); - ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, ctx.public_key, signature), 0); - - nem_transaction_start(&ctx, fromhex("71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_multisig_signature(&ctx, - NEM_NETWORK_TESTNET, 3939891, NULL, 6000000, 3961491, - &other_trans)); - - signature = fromhex("a849f13bfeeba808a8a4a79d579febe584d831a3a6ad03da3b9d008530b3d7a79fcf7156121cd7ee847029d94af7ea7a683ca8e643dc5e5f489557c2054b830b"); - ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, ctx.public_key, signature), 0); - - // http://chain.nem.ninja/#/multisig/1016cf3bdd61bd57b9b2b07b6ff2dee390279d8d899265bdc23d42360abe2e6c - - nem_transaction_start(&other_trans, fromhex("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"), inner, sizeof(inner)); - - ck_assert(nem_transaction_create_provision_namespace(&other_trans, - NEM_NETWORK_MAINNET, 59414272, NULL, 20000000, 59500672, - "dim", NULL, - "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 5000000000)); - - nem_transaction_start(&ctx, fromhex("cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_multisig(&ctx, - NEM_NETWORK_MAINNET, 59414272, NULL, 6000000, 59500672, - &other_trans)); - - signature = fromhex("52a876a37511068fe214bd710b2284823921ec7318c01e083419a062eae5369c9c11c3abfdb590f65c717fab82873431d52be62e10338cb5656d1833bbdac70c"); - ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, ctx.public_key, signature), 0); - - nem_transaction_start(&ctx, fromhex("1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_multisig_signature(&ctx, - NEM_NETWORK_MAINNET, 59414342, NULL, 6000000, 59500742, - &other_trans)); - - signature = fromhex("b9a59239e5d06992c28840034ff7a7f13da9c4e6f4a6f72c1b1806c3b602f83a7d727a345371f5d15abf958208a32359c6dd77bde92273ada8ea6fda3dc76b00"); - ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, ctx.public_key, signature), 0); - - nem_transaction_start(&ctx, fromhex("7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_multisig_signature(&ctx, - NEM_NETWORK_MAINNET, 59414381, NULL, 6000000, 59500781, - &other_trans)); - - signature = fromhex("e874ae9f069f0538008631d2df9f2e8a59944ff182e8672f743d2700fb99224aafb7a0ab09c4e9ea39ee7c8ca04a8a3d6103ae1122d87772e871761d4f00ca01"); - ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, ctx.public_key, signature), 0); +START_TEST(test_nem_transaction_multisig) { + nem_transaction_ctx ctx, other_trans; + + uint8_t buffer[1024], inner[1024]; + const uint8_t *signature; + + // http://bob.nem.ninja:8765/#/multisig/7d3a7087023ee29005262016706818579a2b5499eb9ca76bad98c1e6f4c46642 + + nem_transaction_start( + &other_trans, + fromhex( + "abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"), + inner, sizeof(inner)); + + ck_assert(nem_transaction_create_aggregate_modification( + &other_trans, NEM_NETWORK_TESTNET, 3939039, NULL, 16000000, 3960639, 1, + false)); + + ck_assert(nem_transaction_write_cosignatory_modification( + &other_trans, 2, + fromhex( + "e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))); + + nem_transaction_start( + &ctx, + fromhex( + "59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_multisig(&ctx, NEM_NETWORK_TESTNET, 3939039, + NULL, 6000000, 3960639, + &other_trans)); + + signature = fromhex( + "933930a8828b560168bddb3137df9252048678d829aa5135fa27bb306ff6562efb927554" + "62988b852b0314bde058487d00e47816b6fb7df6bcfd7e1f150d1d00"); + ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, + ctx.public_key, signature), + 0); + + nem_transaction_start( + &ctx, + fromhex( + "71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_TESTNET, + 3939891, NULL, 6000000, + 3961491, &other_trans)); + + signature = fromhex( + "a849f13bfeeba808a8a4a79d579febe584d831a3a6ad03da3b9d008530b3d7a79fcf7156" + "121cd7ee847029d94af7ea7a683ca8e643dc5e5f489557c2054b830b"); + ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, + ctx.public_key, signature), + 0); + + // http://chain.nem.ninja/#/multisig/1016cf3bdd61bd57b9b2b07b6ff2dee390279d8d899265bdc23d42360abe2e6c + + nem_transaction_start( + &other_trans, + fromhex( + "a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"), + inner, sizeof(inner)); + + ck_assert(nem_transaction_create_provision_namespace( + &other_trans, NEM_NETWORK_MAINNET, 59414272, NULL, 20000000, 59500672, + "dim", NULL, "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 5000000000)); + + nem_transaction_start( + &ctx, + fromhex( + "cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_multisig(&ctx, NEM_NETWORK_MAINNET, 59414272, + NULL, 6000000, 59500672, + &other_trans)); + + signature = fromhex( + "52a876a37511068fe214bd710b2284823921ec7318c01e083419a062eae5369c9c11c3ab" + "fdb590f65c717fab82873431d52be62e10338cb5656d1833bbdac70c"); + ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, + ctx.public_key, signature), + 0); + + nem_transaction_start( + &ctx, + fromhex( + "1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_MAINNET, + 59414342, NULL, 6000000, + 59500742, &other_trans)); + + signature = fromhex( + "b9a59239e5d06992c28840034ff7a7f13da9c4e6f4a6f72c1b1806c3b602f83a7d727a34" + "5371f5d15abf958208a32359c6dd77bde92273ada8ea6fda3dc76b00"); + ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, + ctx.public_key, signature), + 0); + + nem_transaction_start( + &ctx, + fromhex( + "7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_MAINNET, + 59414381, NULL, 6000000, + 59500781, &other_trans)); + + signature = fromhex( + "e874ae9f069f0538008631d2df9f2e8a59944ff182e8672f743d2700fb99224aafb7a0ab" + "09c4e9ea39ee7c8ca04a8a3d6103ae1122d87772e871761d4f00ca01"); + ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset, + ctx.public_key, signature), + 0); } END_TEST -START_TEST(test_nem_transaction_provision_namespace) -{ - nem_transaction_ctx ctx; - - uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; - - // http://bob.nem.ninja:8765/#/namespace/f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3 - - nem_transaction_start(&ctx, fromhex("84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_provision_namespace(&ctx, - NEM_NETWORK_TESTNET, 56999445, NULL, 20000000, 57003045, - "gimre", NULL, - "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3"), sizeof(hash)); - - // http://bob.nem.ninja:8765/#/namespace/7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d - - nem_transaction_start(&ctx, fromhex("244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_provision_namespace(&ctx, - NEM_NETWORK_TESTNET, 21496797, NULL, 108000000, 21500397, - "misc", "alice", - "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d"), sizeof(hash)); - - // http://chain.nem.ninja/#/namespace/57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569 - - nem_transaction_start(&ctx, fromhex("9f3c14f304309c8b72b2821339c4428793b1518bea72d58dd01f19d523518614"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_provision_namespace(&ctx, - NEM_NETWORK_MAINNET, 26699717, NULL, 108000000, 26703317, - "sex", NULL, - "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 50000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569"), sizeof(hash)); +START_TEST(test_nem_transaction_provision_namespace) { + nem_transaction_ctx ctx; + + uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; + + // http://bob.nem.ninja:8765/#/namespace/f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3 + + nem_transaction_start( + &ctx, + fromhex( + "84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_provision_namespace( + &ctx, NEM_NETWORK_TESTNET, 56999445, NULL, 20000000, 57003045, "gimre", + NULL, "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3"), + sizeof(hash)); + + // http://bob.nem.ninja:8765/#/namespace/7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d + + nem_transaction_start( + &ctx, + fromhex( + "244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_provision_namespace( + &ctx, NEM_NETWORK_TESTNET, 21496797, NULL, 108000000, 21500397, "misc", + "alice", "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d"), + sizeof(hash)); + + // http://chain.nem.ninja/#/namespace/57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569 + + nem_transaction_start( + &ctx, + fromhex( + "9f3c14f304309c8b72b2821339c4428793b1518bea72d58dd01f19d523518614"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_provision_namespace( + &ctx, NEM_NETWORK_MAINNET, 26699717, NULL, 108000000, 26703317, "sex", + NULL, "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 50000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569"), + sizeof(hash)); } END_TEST -START_TEST(test_nem_transaction_mosaic_creation) -{ - nem_transaction_ctx ctx; - - uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; - - // http://bob.nem.ninja:8765/#/mosaic/68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa/0 - - nem_transaction_start(&ctx, fromhex("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_creation(&ctx, - NEM_NETWORK_TESTNET, 14070896, NULL, 108000000, 14074496, - "gimre.games.pong", "paddles", - "Paddles for the bong game.\n", - 0, 10000, true, true, - 0, 0, NULL, NULL, NULL, - "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa"), sizeof(hash)); - - // http://bob.nem.ninja:8765/#/mosaic/b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55/0 - - nem_transaction_start(&ctx, fromhex("244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_creation(&ctx, - NEM_NETWORK_TESTNET, 21497248, NULL, 108000000, 21500848, - "alice.misc", "bar", - "Special offer: get one bar extra by bying one foo!", - 0, 1000, false, true, - 1, 1, "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "nem", "xem", - "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55"), sizeof(hash)); - - // http://chain.nem.ninja/#/mosaic/269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b/0 - - nem_transaction_start(&ctx, fromhex("58956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f23"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_creation(&ctx, - NEM_NETWORK_MAINNET, 26729938, NULL, 108000000, 26733538, - "jabo38", "red_token", - "This token is to celebrate the release of Namespaces and Mosaics on the NEM system. " - "This token was the fist ever mosaic created other than nem.xem. " - "There are only 10,000 Red Tokens that will ever be created. " - "It has no levy and can be traded freely among third parties.", - 2, 10000, false, true, - 0, 0, NULL, NULL, NULL, - "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 50000000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b"), sizeof(hash)); - - // http://chain.nem.ninja/#/mosaic/e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6/0 - - nem_transaction_start(&ctx, fromhex("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_creation(&ctx, - NEM_NETWORK_MAINNET, 69251020, NULL, 20000000, 69337420, - "dim", "coin", - "DIM COIN", - 6, 9000000000, false, true, - 2, 10, "NCGGLVO2G3CUACVI5GNX2KRBJSQCN4RDL2ZWJ4DP", "dim", "coin", - "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 500000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6"), sizeof(hash)); +START_TEST(test_nem_transaction_mosaic_creation) { + nem_transaction_ctx ctx; + + uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; + + // http://bob.nem.ninja:8765/#/mosaic/68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa/0 + + nem_transaction_start( + &ctx, + fromhex( + "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_creation( + &ctx, NEM_NETWORK_TESTNET, 14070896, NULL, 108000000, 14074496, + "gimre.games.pong", "paddles", "Paddles for the bong game.\n", 0, 10000, + true, true, 0, 0, NULL, NULL, NULL, + "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa"), + sizeof(hash)); + + // http://bob.nem.ninja:8765/#/mosaic/b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55/0 + + nem_transaction_start( + &ctx, + fromhex( + "244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_creation( + &ctx, NEM_NETWORK_TESTNET, 21497248, NULL, 108000000, 21500848, + "alice.misc", "bar", "Special offer: get one bar extra by bying one foo!", + 0, 1000, false, true, 1, 1, "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "nem", "xem", "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55"), + sizeof(hash)); + + // http://chain.nem.ninja/#/mosaic/269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b/0 + + nem_transaction_start( + &ctx, + fromhex( + "58956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f23"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_creation( + &ctx, NEM_NETWORK_MAINNET, 26729938, NULL, 108000000, 26733538, "jabo38", + "red_token", + "This token is to celebrate the release of Namespaces and Mosaics on the " + "NEM system. " + "This token was the fist ever mosaic created other than nem.xem. " + "There are only 10,000 Red Tokens that will ever be created. " + "It has no levy and can be traded freely among third parties.", + 2, 10000, false, true, 0, 0, NULL, NULL, NULL, + "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 50000000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b"), + sizeof(hash)); + + // http://chain.nem.ninja/#/mosaic/e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6/0 + + nem_transaction_start( + &ctx, + fromhex( + "a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_creation( + &ctx, NEM_NETWORK_MAINNET, 69251020, NULL, 20000000, 69337420, "dim", + "coin", "DIM COIN", 6, 9000000000, false, true, 2, 10, + "NCGGLVO2G3CUACVI5GNX2KRBJSQCN4RDL2ZWJ4DP", "dim", "coin", + "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 500000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6"), + sizeof(hash)); } END_TEST -START_TEST(test_nem_transaction_mosaic_supply_change) -{ - nem_transaction_ctx ctx; - - uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; - - // http://bigalice2.nem.ninja:7890/transaction/get?hash=33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50 - - nem_transaction_start(&ctx, fromhex("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_supply_change(&ctx, - NEM_NETWORK_TESTNET, 14071648, NULL, 108000000, 14075248, - "gimre.games.pong", "paddles", - 1, 1234)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50"), sizeof(hash)); - - // http://bigalice2.nem.ninja:7890/transaction/get?hash=1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2 - - nem_transaction_start(&ctx, fromhex("84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_supply_change(&ctx, - NEM_NETWORK_TESTNET, 14126909, NULL, 108000000, 14130509, - "jabo38_ltd.fuzzy_kittens_cafe", "coupons", - 2, 1)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2"), sizeof(hash)); - - // http://bigalice3.nem.ninja:7890/transaction/get?hash=694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff - - nem_transaction_start(&ctx, fromhex("b7ccc27b21ba6cf5c699a8dc86ba6ba98950442597ff9fa30e0abe0f5f4dd05d"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_supply_change(&ctx, - NEM_NETWORK_MAINNET, 53377685, NULL, 20000000, 53464085, - "abvapp", "abv", - 1, 9000000)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff"), sizeof(hash)); - - // http://bigalice3.nem.ninja:7890/transaction/get?hash=09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185 - - nem_transaction_start(&ctx, fromhex("75f001a8641e2ce5c4386883dda561399ed346177411b492a677b73899502f13"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_mosaic_supply_change(&ctx, - NEM_NETWORK_MAINNET, 55176304, NULL, 20000000, 55262704, - "sushi", "wasabi", - 2, 20)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185"), sizeof(hash)); +START_TEST(test_nem_transaction_mosaic_supply_change) { + nem_transaction_ctx ctx; + + uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; + + // http://bigalice2.nem.ninja:7890/transaction/get?hash=33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50 + + nem_transaction_start( + &ctx, + fromhex( + "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_supply_change( + &ctx, NEM_NETWORK_TESTNET, 14071648, NULL, 108000000, 14075248, + "gimre.games.pong", "paddles", 1, 1234)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50"), + sizeof(hash)); + + // http://bigalice2.nem.ninja:7890/transaction/get?hash=1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2 + + nem_transaction_start( + &ctx, + fromhex( + "84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_supply_change( + &ctx, NEM_NETWORK_TESTNET, 14126909, NULL, 108000000, 14130509, + "jabo38_ltd.fuzzy_kittens_cafe", "coupons", 2, 1)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2"), + sizeof(hash)); + + // http://bigalice3.nem.ninja:7890/transaction/get?hash=694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff + + nem_transaction_start( + &ctx, + fromhex( + "b7ccc27b21ba6cf5c699a8dc86ba6ba98950442597ff9fa30e0abe0f5f4dd05d"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_supply_change( + &ctx, NEM_NETWORK_MAINNET, 53377685, NULL, 20000000, 53464085, "abvapp", + "abv", 1, 9000000)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff"), + sizeof(hash)); + + // http://bigalice3.nem.ninja:7890/transaction/get?hash=09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185 + + nem_transaction_start( + &ctx, + fromhex( + "75f001a8641e2ce5c4386883dda561399ed346177411b492a677b73899502f13"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_mosaic_supply_change( + &ctx, NEM_NETWORK_MAINNET, 55176304, NULL, 20000000, 55262704, "sushi", + "wasabi", 2, 20)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185"), + sizeof(hash)); } END_TEST -START_TEST(test_nem_transaction_aggregate_modification) -{ - nem_transaction_ctx ctx; - - uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; - - // http://bob.nem.ninja:8765/#/aggregate/6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2 - - nem_transaction_start(&ctx, fromhex("462ee976890916e54fa825d26bdd0235f5eb5b6a143c199ab0ae5ee9328e08ce"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_aggregate_modification(&ctx, - NEM_NETWORK_TESTNET, 0, NULL, 22000000, 0, - 2, false)); - - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("c54d6e33ed1446eedd7f7a80a588dd01857f723687a09200c1917d5524752f8b"))); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2"), sizeof(hash)); - - // http://bob.nem.ninja:8765/#/aggregate/1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584 - - nem_transaction_start(&ctx, fromhex("6bf7849c1eec6a2002995cc457dc00c4e29bad5c88de63f51e42dfdcd7b2131d"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_aggregate_modification(&ctx, - NEM_NETWORK_TESTNET, 6542254, NULL, 40000000, 6545854, - 4, true)); - - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("5f53d076c8c3ec3110b98364bc423092c3ec2be2b1b3c40fd8ab68d54fa39295"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("9eb199c2b4d406f64cb7aa5b2b0815264b56ba8fe44d558a6cb423a31a33c4c2"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("94b2323dab23a3faba24fa6ddda0ece4fbb06acfedd74e76ad9fae38d006882b"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("d88c6ee2a2cd3929d0d76b6b14ecb549d21296ab196a2b3a4cb2536bcce32e87"))); - - ck_assert(nem_transaction_write_minimum_cosignatories(&ctx, 2)); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584"), sizeof(hash)); - - // http://chain.nem.ninja/#/aggregate/cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c - - nem_transaction_start(&ctx, fromhex("f41b99320549741c5cce42d9e4bb836d98c50ed5415d0c3c2912d1bb50e6a0e5"), buffer, sizeof(buffer)); - - ck_assert(nem_transaction_create_aggregate_modification(&ctx, - NEM_NETWORK_MAINNET, 0, NULL, 40000000, 0, - 5, false)); - - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("1fbdbdde28daf828245e4533765726f0b7790e0b7146e2ce205df3e86366980b"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("f94e8702eb1943b23570b1b83be1b81536df35538978820e98bfce8f999e2d37"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("826cedee421ff66e708858c17815fcd831a4bb68e3d8956299334e9e24380ba8"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("719862cd7d0f4e875a6a0274c9a1738f38f40ad9944179006a54c34724c1274d"))); - ck_assert(nem_transaction_write_cosignatory_modification(&ctx, 1, fromhex("43aa69177018fc3e2bdbeb259c81cddf24be50eef9c5386db51d82386c41475a"))); - - keccak_256(ctx.buffer, ctx.offset, hash); - ck_assert_mem_eq(hash, fromhex("cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c"), sizeof(hash)); +START_TEST(test_nem_transaction_aggregate_modification) { + nem_transaction_ctx ctx; + + uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH]; + + // http://bob.nem.ninja:8765/#/aggregate/6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2 + + nem_transaction_start( + &ctx, + fromhex( + "462ee976890916e54fa825d26bdd0235f5eb5b6a143c199ab0ae5ee9328e08ce"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_aggregate_modification( + &ctx, NEM_NETWORK_TESTNET, 0, NULL, 22000000, 0, 2, false)); + + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "c54d6e33ed1446eedd7f7a80a588dd01857f723687a09200c1917d5524752f8b"))); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2"), + sizeof(hash)); + + // http://bob.nem.ninja:8765/#/aggregate/1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584 + + nem_transaction_start( + &ctx, + fromhex( + "6bf7849c1eec6a2002995cc457dc00c4e29bad5c88de63f51e42dfdcd7b2131d"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_aggregate_modification( + &ctx, NEM_NETWORK_TESTNET, 6542254, NULL, 40000000, 6545854, 4, true)); + + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "5f53d076c8c3ec3110b98364bc423092c3ec2be2b1b3c40fd8ab68d54fa39295"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "9eb199c2b4d406f64cb7aa5b2b0815264b56ba8fe44d558a6cb423a31a33c4c2"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "94b2323dab23a3faba24fa6ddda0ece4fbb06acfedd74e76ad9fae38d006882b"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "d88c6ee2a2cd3929d0d76b6b14ecb549d21296ab196a2b3a4cb2536bcce32e87"))); + + ck_assert(nem_transaction_write_minimum_cosignatories(&ctx, 2)); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584"), + sizeof(hash)); + + // http://chain.nem.ninja/#/aggregate/cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c + + nem_transaction_start( + &ctx, + fromhex( + "f41b99320549741c5cce42d9e4bb836d98c50ed5415d0c3c2912d1bb50e6a0e5"), + buffer, sizeof(buffer)); + + ck_assert(nem_transaction_create_aggregate_modification( + &ctx, NEM_NETWORK_MAINNET, 0, NULL, 40000000, 0, 5, false)); + + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "1fbdbdde28daf828245e4533765726f0b7790e0b7146e2ce205df3e86366980b"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "f94e8702eb1943b23570b1b83be1b81536df35538978820e98bfce8f999e2d37"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "826cedee421ff66e708858c17815fcd831a4bb68e3d8956299334e9e24380ba8"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "719862cd7d0f4e875a6a0274c9a1738f38f40ad9944179006a54c34724c1274d"))); + ck_assert(nem_transaction_write_cosignatory_modification( + &ctx, 1, + fromhex( + "43aa69177018fc3e2bdbeb259c81cddf24be50eef9c5386db51d82386c41475a"))); + + keccak_256(ctx.buffer, ctx.offset, hash); + ck_assert_mem_eq( + hash, + fromhex( + "cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c"), + sizeof(hash)); } END_TEST -START_TEST(test_multibyte_address) -{ - uint8_t priv_key[32]; - char wif[57]; - uint8_t pub_key[33]; - char address[40]; - uint8_t decode[24]; - int res; - - memcpy(priv_key, fromhex("47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"), 32); - ecdsa_get_wif(priv_key, 0, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "13QtoXmbhELWcrwD9YA9KzvXy5rTaptiNuFR8L8ArpBNn4xmQj4N"); - ecdsa_get_wif(priv_key, 0x12, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "3hrF6SFnqzpzABB36uGDf8dJSuUCcMmoJrTmCWMshRkBr2Vx86qJ"); - ecdsa_get_wif(priv_key, 0x1234, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "CtPTF9awbVbfDWGepGdVhB3nBhr4HktUGya8nf8dLxgC8tbqBreB9"); - ecdsa_get_wif(priv_key, 0x123456, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "uTrDevVQt5QZgoL3iJ1cPWHaCz7ZMBncM7QXZfCegtxiMHqBvWoYJa"); - ecdsa_get_wif(priv_key, 0x12345678, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "4zZWMzv1SVbs95pmLXWrXJVp9ntPEam1mfwb6CXBLn9MpWNxLg9huYgv"); - ecdsa_get_wif(priv_key, 0xffffffff, HASHER_SHA2D, wif, sizeof(wif)); ck_assert_str_eq(wif, "y9KVfV1RJXcTxpVjeuh6WYWh8tMwnAUeyUwDEiRviYdrJ61njTmnfUjE"); - - memcpy(pub_key, fromhex("0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71"), 33); - ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8"); - ecdsa_get_address(pub_key, 0x12, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq"); - ecdsa_get_address(pub_key, 0x1234, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV"); - ecdsa_get_address(pub_key, 0x123456, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq"); - ecdsa_get_address(pub_key, 0x12345678, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44"); - ecdsa_get_address(pub_key, 0xffffffff, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, sizeof(address)); ck_assert_str_eq(address, "3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT"); - - res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21); - res = ecdsa_address_decode("8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq", 0x12, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("1279fbfc3f34e7745860d76137da68f362380c606c"), 21); - res = ecdsa_address_decode("ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV", 0x1234, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("123479fbfc3f34e7745860d76137da68f362380c606c"), 21); - res = ecdsa_address_decode("3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq", 0x123456, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("12345679fbfc3f34e7745860d76137da68f362380c606c"), 21); - res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", 0x12345678, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("1234567879fbfc3f34e7745860d76137da68f362380c606c"), 21); - res = ecdsa_address_decode("3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT", 0xffffffff, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 1); - ck_assert_mem_eq(decode, fromhex("ffffffff79fbfc3f34e7745860d76137da68f362380c606c"), 21); - - // wrong length - res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", 0x123456, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); - - // wrong address prefix - res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", 0x22345678, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); - - // wrong checksum - res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL45", 0x12345678, HASHER_SHA2D, decode); - ck_assert_int_eq(res, 0); +START_TEST(test_multibyte_address) { + uint8_t priv_key[32]; + char wif[57]; + uint8_t pub_key[33]; + char address[40]; + uint8_t decode[24]; + int res; + + memcpy( + priv_key, + fromhex( + "47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"), + 32); + ecdsa_get_wif(priv_key, 0, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "13QtoXmbhELWcrwD9YA9KzvXy5rTaptiNuFR8L8ArpBNn4xmQj4N"); + ecdsa_get_wif(priv_key, 0x12, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, "3hrF6SFnqzpzABB36uGDf8dJSuUCcMmoJrTmCWMshRkBr2Vx86qJ"); + ecdsa_get_wif(priv_key, 0x1234, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, + "CtPTF9awbVbfDWGepGdVhB3nBhr4HktUGya8nf8dLxgC8tbqBreB9"); + ecdsa_get_wif(priv_key, 0x123456, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, + "uTrDevVQt5QZgoL3iJ1cPWHaCz7ZMBncM7QXZfCegtxiMHqBvWoYJa"); + ecdsa_get_wif(priv_key, 0x12345678, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, + "4zZWMzv1SVbs95pmLXWrXJVp9ntPEam1mfwb6CXBLn9MpWNxLg9huYgv"); + ecdsa_get_wif(priv_key, 0xffffffff, HASHER_SHA2D, wif, sizeof(wif)); + ck_assert_str_eq(wif, + "y9KVfV1RJXcTxpVjeuh6WYWh8tMwnAUeyUwDEiRviYdrJ61njTmnfUjE"); + + memcpy( + pub_key, + fromhex( + "0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71"), + 33); + ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8"); + ecdsa_get_address(pub_key, 0x12, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq"); + ecdsa_get_address(pub_key, 0x1234, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address, + sizeof(address)); + ck_assert_str_eq(address, "ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV"); + ecdsa_get_address(pub_key, 0x123456, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq"); + ecdsa_get_address(pub_key, 0x12345678, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44"); + ecdsa_get_address(pub_key, 0xffffffff, HASHER_SHA2_RIPEMD, HASHER_SHA2D, + address, sizeof(address)); + ck_assert_str_eq(address, "3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT"); + + res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21); + res = ecdsa_address_decode("8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq", 0x12, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("1279fbfc3f34e7745860d76137da68f362380c606c"), 21); + res = ecdsa_address_decode("ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV", 0x1234, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq(decode, + fromhex("123479fbfc3f34e7745860d76137da68f362380c606c"), 21); + res = ecdsa_address_decode("3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq", 0x123456, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + decode, fromhex("12345679fbfc3f34e7745860d76137da68f362380c606c"), 21); + res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", + 0x12345678, HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + decode, fromhex("1234567879fbfc3f34e7745860d76137da68f362380c606c"), 21); + res = ecdsa_address_decode("3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT", + 0xffffffff, HASHER_SHA2D, decode); + ck_assert_int_eq(res, 1); + ck_assert_mem_eq( + decode, fromhex("ffffffff79fbfc3f34e7745860d76137da68f362380c606c"), 21); + + // wrong length + res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", 0x123456, + HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); + + // wrong address prefix + res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", + 0x22345678, HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); + + // wrong checksum + res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL45", + 0x12345678, HASHER_SHA2D, decode); + ck_assert_int_eq(res, 0); } END_TEST // https://tools.ietf.org/html/rfc6229#section-2 -START_TEST(test_rc4_rfc6229) -{ - static const size_t offsets[] = { - 0x0, - 0xf0, - 0x1f0, - 0x2f0, - 0x3f0, - 0x5f0, - 0x7f0, - 0xbf0, - 0xff0, - }; - - static const struct { - char key[65]; - char vectors[sizeof(offsets) / sizeof(*offsets)][65]; - } tests[] = { - { - "0102030405", - { - "b2396305f03dc027ccc3524a0a1118a8" "6982944f18fc82d589c403a47a0d0919", - "28cb1132c96ce286421dcaadb8b69eae" "1cfcf62b03eddb641d77dfcf7f8d8c93", - "42b7d0cdd918a8a33dd51781c81f4041" "6459844432a7da923cfb3eb4980661f6", - "ec10327bde2beefd18f9277680457e22" "eb62638d4f0ba1fe9fca20e05bf8ff2b", - "45129048e6a0ed0b56b490338f078da5" "30abbcc7c20b01609f23ee2d5f6bb7df", - "3294f744d8f9790507e70f62e5bbceea" "d8729db41882259bee4f825325f5a130", - "1eb14a0c13b3bf47fa2a0ba93ad45b8b" "cc582f8ba9f265e2b1be9112e975d2d7", - "f2e30f9bd102ecbf75aaade9bc35c43c" "ec0e11c479dc329dc8da7968fe965681", - "068326a2118416d21f9d04b2cd1ca050" "ff25b58995996707e51fbdf08b34d875", - } - }, { - "01020304050607", - { - "293f02d47f37c9b633f2af5285feb46b" "e620f1390d19bd84e2e0fd752031afc1", - "914f02531c9218810df60f67e338154c" "d0fdb583073ce85ab83917740ec011d5", - "75f81411e871cffa70b90c74c592e454" "0bb87202938dad609e87a5a1b079e5e4", - "c2911246b612e7e7b903dfeda1dad866" "32828f91502b6291368de8081de36fc2", - "f3b9a7e3b297bf9ad804512f9063eff1" "8ecb67a9ba1f55a5a067e2b026a3676f", - "d2aa902bd42d0d7cfd340cd45810529f" "78b272c96e42eab4c60bd914e39d06e3", - "f4332fd31a079396ee3cee3f2a4ff049" "05459781d41fda7f30c1be7e1246c623", - "adfd3868b8e51485d5e610017e3dd609" "ad26581c0c5be45f4cea01db2f3805d5", - "f3172ceffc3b3d997c85ccd5af1a950c" "e74b0b9731227fd37c0ec08a47ddd8b8", - } - }, { - "0102030405060708", - { - "97ab8a1bf0afb96132f2f67258da15a8" "8263efdb45c4a18684ef87e6b19e5b09", - "9636ebc9841926f4f7d1f362bddf6e18" "d0a990ff2c05fef5b90373c9ff4b870a", - "73239f1db7f41d80b643c0c52518ec63" "163b319923a6bdb4527c626126703c0f", - "49d6c8af0f97144a87df21d91472f966" "44173a103b6616c5d5ad1cee40c863d0", - "273c9c4b27f322e4e716ef53a47de7a4" "c6d0e7b226259fa9023490b26167ad1d", - "1fe8986713f07c3d9ae1c163ff8cf9d3" "8369e1a965610be887fbd0c79162aafb", - "0a0127abb44484b9fbef5abcae1b579f" "c2cdadc6402e8ee866e1f37bdb47e42c", - "26b51ea37df8e1d6f76fc3b66a7429b3" "bc7683205d4f443dc1f29dda3315c87b", - "d5fa5a3469d29aaaf83d23589db8c85b" "3fb46e2c8f0f068edce8cdcd7dfc5862", - } - }, { - "0102030405060708090a", - { - "ede3b04643e586cc907dc21851709902" "03516ba78f413beb223aa5d4d2df6711", - "3cfd6cb58ee0fdde640176ad0000044d" "48532b21fb6079c9114c0ffd9c04a1ad", - "3e8cea98017109979084b1ef92f99d86" "e20fb49bdb337ee48b8d8dc0f4afeffe", - "5c2521eacd7966f15e056544bea0d315" "e067a7031931a246a6c3875d2f678acb", - "a64f70af88ae56b6f87581c0e23e6b08" "f449031de312814ec6f319291f4a0516", - "bdae85924b3cb1d0a2e33a30c6d79599" "8a0feddbac865a09bcd127fb562ed60a", - "b55a0a5b51a12a8be34899c3e047511a" "d9a09cea3ce75fe39698070317a71339", - "552225ed1177f44584ac8cfa6c4eb5fc" "7e82cbabfc95381b080998442129c2f8", - "1f135ed14ce60a91369d2322bef25e3c" "08b6be45124a43e2eb77953f84dc8553", - } - }, { - "0102030405060708090a0b0c0d0e0f10", - { - "9ac7cc9a609d1ef7b2932899cde41b97" "5248c4959014126a6e8a84f11d1a9e1c", - "065902e4b620f6cc36c8589f66432f2b" "d39d566bc6bce3010768151549f3873f", - "b6d1e6c4a5e4771cad79538df295fb11" "c68c1d5c559a974123df1dbc52a43b89", - "c5ecf88de897fd57fed301701b82a259" "eccbe13de1fcc91c11a0b26c0bc8fa4d", - "e7a72574f8782ae26aabcf9ebcd66065" "bdf0324e6083dcc6d3cedd3ca8c53c16", - "b40110c4190b5622a96116b0017ed297" "ffa0b514647ec04f6306b892ae661181", - "d03d1bc03cd33d70dff9fa5d71963ebd" "8a44126411eaa78bd51e8d87a8879bf5", - "fabeb76028ade2d0e48722e46c4615a3" "c05d88abd50357f935a63c59ee537623", - "ff38265c1642c1abe8d3c2fe5e572bf8" "a36a4c301ae8ac13610ccbc12256cacc", - } - }, { - "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", - { - "eaa6bd25880bf93d3f5d1e4ca2611d91" "cfa45c9f7e714b54bdfa80027cb14380", - "114ae344ded71b35f2e60febad727fd8" "02e1e7056b0f623900496422943e97b6", - "91cb93c787964e10d9527d999c6f936b" "49b18b42f8e8367cbeb5ef104ba1c7cd", - "87084b3ba700bade955610672745b374" "e7a7b9e9ec540d5ff43bdb12792d1b35", - "c799b596738f6b018c76c74b1759bd90" "7fec5bfd9f9b89ce6548309092d7e958", - "40f250b26d1f096a4afd4c340a588815" "3e34135c79db010200767651cf263073", - "f656abccf88dd827027b2ce917d464ec" "18b62503bfbc077fbabb98f20d98ab34", - "8aed95ee5b0dcbfbef4eb21d3a3f52f9" "625a1ab00ee39a5327346bddb01a9c18", - "a13a7c79c7e119b5ab0296ab28c300b9" "f3e4c0a2e02d1d01f7f0a74618af2b48", - } - }, { - "833222772a", - { - "80ad97bdc973df8a2e879e92a497efda" "20f060c2f2e5126501d3d4fea10d5fc0", - "faa148e99046181fec6b2085f3b20ed9" "f0daf5bab3d596839857846f73fbfe5a", - "1c7e2fc4639232fe297584b296996bc8" "3db9b249406cc8edffac55ccd322ba12", - "e4f9f7e0066154bbd125b745569bc897" "75d5ef262b44c41a9cf63ae14568e1b9", - "6da453dbf81e82334a3d8866cb50a1e3" "7828d074119cab5c22b294d7a9bfa0bb", - "adb89cea9a15fbe617295bd04b8ca05c" "6251d87fd4aaae9a7e4ad5c217d3f300", - "e7119bd6dd9b22afe8f89585432881e2" "785b60fd7ec4e9fcb6545f350d660fab", - "afecc037fdb7b0838eb3d70bcd268382" "dbc1a7b49d57358cc9fa6d61d73b7cf0", - "6349d126a37afcba89794f9804914fdc" "bf42c3018c2f7c66bfde524975768115", - } - }, { - "1910833222772a", - { - "bc9222dbd3274d8fc66d14ccbda6690b" "7ae627410c9a2be693df5bb7485a63e3", - "3f0931aa03defb300f060103826f2a64" "beaa9ec8d59bb68129f3027c96361181", - "74e04db46d28648d7dee8a0064b06cfe" "9b5e81c62fe023c55be42f87bbf932b8", - "ce178fc1826efecbc182f57999a46140" "8bdf55cd55061c06dba6be11de4a578a", - "626f5f4dce652501f3087d39c92cc349" "42daac6a8f9ab9a7fd137c6037825682", - "cc03fdb79192a207312f53f5d4dc33d9" "f70f14122a1c98a3155d28b8a0a8a41d", - "2a3a307ab2708a9c00fe0b42f9c2d6a1" "862617627d2261eab0b1246597ca0ae9", - "55f877ce4f2e1ddbbf8e13e2cde0fdc8" "1b1556cb935f173337705fbb5d501fc1", - "ecd0e96602be7f8d5092816cccf2c2e9" "027881fab4993a1c262024a94fff3f61", - } - }, { - "641910833222772a", - { - "bbf609de9413172d07660cb680716926" "46101a6dab43115d6c522b4fe93604a9", - "cbe1fff21c96f3eef61e8fe0542cbdf0" "347938bffa4009c512cfb4034b0dd1a7", - "7867a786d00a7147904d76ddf1e520e3" "8d3e9e1caefcccb3fbf8d18f64120b32", - "942337f8fd76f0fae8c52d7954810672" "b8548c10f51667f6e60e182fa19b30f7", - "0211c7c6190c9efd1237c34c8f2e06c4" "bda64f65276d2aacb8f90212203a808e", - "bd3820f732ffb53ec193e79d33e27c73" "d0168616861907d482e36cdac8cf5749", - "97b0f0f224b2d2317114808fb03af7a0" "e59616e469787939a063ceea9af956d1", - "c47e0dc1660919c11101208f9e69aa1f" "5ae4f12896b8379a2aad89b5b553d6b0", - "6b6b098d0c293bc2993d80bf0518b6d9" "8170cc3ccd92a698621b939dd38fe7b9", - } - }, { - "8b37641910833222772a", - { - "ab65c26eddb287600db2fda10d1e605c" "bb759010c29658f2c72d93a2d16d2930", - "b901e8036ed1c383cd3c4c4dd0a6ab05" "3d25ce4922924c55f064943353d78a6c", - "12c1aa44bbf87e75e611f69b2c38f49b" "28f2b3434b65c09877470044c6ea170d", - "bd9ef822de5288196134cf8af7839304" "67559c23f052158470a296f725735a32", - "8bab26fbc2c12b0f13e2ab185eabf241" "31185a6d696f0cfa9b42808b38e132a2", - "564d3dae183c5234c8af1e51061c44b5" "3c0778a7b5f72d3c23a3135c7d67b9f4", - "f34369890fcf16fb517dcaae4463b2dd" "02f31c81e8200731b899b028e791bfa7", - "72da646283228c14300853701795616f" "4e0a8c6f7934a788e2265e81d6d0c8f4", - "438dd5eafea0111b6f36b4b938da2a68" "5f6bfc73815874d97100f086979357d8", - } - }, { - "ebb46227c6cc8b37641910833222772a", - { - "720c94b63edf44e131d950ca211a5a30" "c366fdeacf9ca80436be7c358424d20b", - "b3394a40aabf75cba42282ef25a0059f" "4847d81da4942dbc249defc48c922b9f", - "08128c469f275342adda202b2b58da95" "970dacef40ad98723bac5d6955b81761", - "3cb89993b07b0ced93de13d2a11013ac" "ef2d676f1545c2c13dc680a02f4adbfe", - "b60595514f24bc9fe522a6cad7393644" "b515a8c5011754f59003058bdb81514e", - "3c70047e8cbc038e3b9820db601da495" "1175da6ee756de46a53e2b075660b770", - "00a542bba02111cc2c65b38ebdba587e" "5865fdbb5b48064104e830b380f2aede", - "34b21ad2ad44e999db2d7f0863f0d9b6" "84a9218fc36e8a5f2ccfbeae53a27d25", - "a2221a11b833ccb498a59540f0545f4a" "5bbeb4787d59e5373fdbea6c6f75c29b", - } - }, { - "c109163908ebe51debb46227c6cc8b37641910833222772a", - { - "54b64e6b5a20b5e2ec84593dc7989da7" "c135eee237a85465ff97dc03924f45ce", - "cfcc922fb4a14ab45d6175aabbf2d201" "837b87e2a446ad0ef798acd02b94124f", - "17a6dbd664926a0636b3f4c37a4f4694" "4a5f9f26aeeed4d4a25f632d305233d9", - "80a3d01ef00c8e9a4209c17f4eeb358c" "d15e7d5ffaaabc0207bf200a117793a2", - "349682bf588eaa52d0aa1560346aeafa" "f5854cdb76c889e3ad63354e5f7275e3", - "532c7ceccb39df3236318405a4b1279c" "baefe6d9ceb651842260e0d1e05e3b90", - "e82d8c6db54e3c633f581c952ba04207" "4b16e50abd381bd70900a9cd9a62cb23", - "3682ee33bd148bd9f58656cd8f30d9fb" "1e5a0b8475045d9b20b2628624edfd9e", - "63edd684fb826282fe528f9c0e9237bc" "e4dd2e98d6960fae0b43545456743391", - } - }, { - "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a", - { - "dd5bcb0018e922d494759d7c395d02d3" "c8446f8f77abf737685353eb89a1c9eb", - "af3e30f9c095045938151575c3fb9098" "f8cb6274db99b80b1d2012a98ed48f0e", - "25c3005a1cb85de076259839ab7198ab" "9dcbc183e8cb994b727b75be3180769c", - "a1d3078dfa9169503ed9d4491dee4eb2" "8514a5495858096f596e4bcd66b10665", - "5f40d59ec1b03b33738efa60b2255d31" "3477c7f764a41baceff90bf14f92b7cc", - "ac4e95368d99b9eb78b8da8f81ffa795" "8c3c13f8c2388bb73f38576e65b7c446", - "13c4b9c1dfb66579eddd8a280b9f7316" "ddd27820550126698efaadc64b64f66e", - "f08f2e66d28ed143f3a237cf9de73559" "9ea36c525531b880ba124334f57b0b70", - "d5a39e3dfcc50280bac4a6b5aa0dca7d" "370b1c1fe655916d97fd0d47ca1d72b8", - } - } - }; - - RC4_CTX ctx; - uint8_t key[64]; - uint8_t buffer[0x1010]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - size_t length = strlen(tests[i].key) / 2; - memcpy(key, fromhex(tests[i].key), length); - memzero(buffer, sizeof(buffer)); - - rc4_init(&ctx, key, length); - rc4_encrypt(&ctx, buffer, sizeof(buffer)); - - for (size_t j = 0; j < (sizeof(offsets) / sizeof(*offsets)); j++) { - size_t size = strlen(tests[i].vectors[j]) / 2; - ck_assert_mem_eq(&buffer[offsets[j]], fromhex(tests[i].vectors[j]), size); - } - } +START_TEST(test_rc4_rfc6229) { + static const size_t offsets[] = { + 0x0, 0xf0, 0x1f0, 0x2f0, 0x3f0, 0x5f0, 0x7f0, 0xbf0, 0xff0, + }; + + static const struct { + char key[65]; + char vectors[sizeof(offsets) / sizeof(*offsets)][65]; + } tests[] = { + {"0102030405", + { + "b2396305f03dc027ccc3524a0a1118a8" + "6982944f18fc82d589c403a47a0d0919", + "28cb1132c96ce286421dcaadb8b69eae" + "1cfcf62b03eddb641d77dfcf7f8d8c93", + "42b7d0cdd918a8a33dd51781c81f4041" + "6459844432a7da923cfb3eb4980661f6", + "ec10327bde2beefd18f9277680457e22" + "eb62638d4f0ba1fe9fca20e05bf8ff2b", + "45129048e6a0ed0b56b490338f078da5" + "30abbcc7c20b01609f23ee2d5f6bb7df", + "3294f744d8f9790507e70f62e5bbceea" + "d8729db41882259bee4f825325f5a130", + "1eb14a0c13b3bf47fa2a0ba93ad45b8b" + "cc582f8ba9f265e2b1be9112e975d2d7", + "f2e30f9bd102ecbf75aaade9bc35c43c" + "ec0e11c479dc329dc8da7968fe965681", + "068326a2118416d21f9d04b2cd1ca050" + "ff25b58995996707e51fbdf08b34d875", + }}, + {"01020304050607", + { + "293f02d47f37c9b633f2af5285feb46b" + "e620f1390d19bd84e2e0fd752031afc1", + "914f02531c9218810df60f67e338154c" + "d0fdb583073ce85ab83917740ec011d5", + "75f81411e871cffa70b90c74c592e454" + "0bb87202938dad609e87a5a1b079e5e4", + "c2911246b612e7e7b903dfeda1dad866" + "32828f91502b6291368de8081de36fc2", + "f3b9a7e3b297bf9ad804512f9063eff1" + "8ecb67a9ba1f55a5a067e2b026a3676f", + "d2aa902bd42d0d7cfd340cd45810529f" + "78b272c96e42eab4c60bd914e39d06e3", + "f4332fd31a079396ee3cee3f2a4ff049" + "05459781d41fda7f30c1be7e1246c623", + "adfd3868b8e51485d5e610017e3dd609" + "ad26581c0c5be45f4cea01db2f3805d5", + "f3172ceffc3b3d997c85ccd5af1a950c" + "e74b0b9731227fd37c0ec08a47ddd8b8", + }}, + {"0102030405060708", + { + "97ab8a1bf0afb96132f2f67258da15a8" + "8263efdb45c4a18684ef87e6b19e5b09", + "9636ebc9841926f4f7d1f362bddf6e18" + "d0a990ff2c05fef5b90373c9ff4b870a", + "73239f1db7f41d80b643c0c52518ec63" + "163b319923a6bdb4527c626126703c0f", + "49d6c8af0f97144a87df21d91472f966" + "44173a103b6616c5d5ad1cee40c863d0", + "273c9c4b27f322e4e716ef53a47de7a4" + "c6d0e7b226259fa9023490b26167ad1d", + "1fe8986713f07c3d9ae1c163ff8cf9d3" + "8369e1a965610be887fbd0c79162aafb", + "0a0127abb44484b9fbef5abcae1b579f" + "c2cdadc6402e8ee866e1f37bdb47e42c", + "26b51ea37df8e1d6f76fc3b66a7429b3" + "bc7683205d4f443dc1f29dda3315c87b", + "d5fa5a3469d29aaaf83d23589db8c85b" + "3fb46e2c8f0f068edce8cdcd7dfc5862", + }}, + {"0102030405060708090a", + { + "ede3b04643e586cc907dc21851709902" + "03516ba78f413beb223aa5d4d2df6711", + "3cfd6cb58ee0fdde640176ad0000044d" + "48532b21fb6079c9114c0ffd9c04a1ad", + "3e8cea98017109979084b1ef92f99d86" + "e20fb49bdb337ee48b8d8dc0f4afeffe", + "5c2521eacd7966f15e056544bea0d315" + "e067a7031931a246a6c3875d2f678acb", + "a64f70af88ae56b6f87581c0e23e6b08" + "f449031de312814ec6f319291f4a0516", + "bdae85924b3cb1d0a2e33a30c6d79599" + "8a0feddbac865a09bcd127fb562ed60a", + "b55a0a5b51a12a8be34899c3e047511a" + "d9a09cea3ce75fe39698070317a71339", + "552225ed1177f44584ac8cfa6c4eb5fc" + "7e82cbabfc95381b080998442129c2f8", + "1f135ed14ce60a91369d2322bef25e3c" + "08b6be45124a43e2eb77953f84dc8553", + }}, + {"0102030405060708090a0b0c0d0e0f10", + { + "9ac7cc9a609d1ef7b2932899cde41b97" + "5248c4959014126a6e8a84f11d1a9e1c", + "065902e4b620f6cc36c8589f66432f2b" + "d39d566bc6bce3010768151549f3873f", + "b6d1e6c4a5e4771cad79538df295fb11" + "c68c1d5c559a974123df1dbc52a43b89", + "c5ecf88de897fd57fed301701b82a259" + "eccbe13de1fcc91c11a0b26c0bc8fa4d", + "e7a72574f8782ae26aabcf9ebcd66065" + "bdf0324e6083dcc6d3cedd3ca8c53c16", + "b40110c4190b5622a96116b0017ed297" + "ffa0b514647ec04f6306b892ae661181", + "d03d1bc03cd33d70dff9fa5d71963ebd" + "8a44126411eaa78bd51e8d87a8879bf5", + "fabeb76028ade2d0e48722e46c4615a3" + "c05d88abd50357f935a63c59ee537623", + "ff38265c1642c1abe8d3c2fe5e572bf8" + "a36a4c301ae8ac13610ccbc12256cacc", + }}, + {"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + { + "eaa6bd25880bf93d3f5d1e4ca2611d91" + "cfa45c9f7e714b54bdfa80027cb14380", + "114ae344ded71b35f2e60febad727fd8" + "02e1e7056b0f623900496422943e97b6", + "91cb93c787964e10d9527d999c6f936b" + "49b18b42f8e8367cbeb5ef104ba1c7cd", + "87084b3ba700bade955610672745b374" + "e7a7b9e9ec540d5ff43bdb12792d1b35", + "c799b596738f6b018c76c74b1759bd90" + "7fec5bfd9f9b89ce6548309092d7e958", + "40f250b26d1f096a4afd4c340a588815" + "3e34135c79db010200767651cf263073", + "f656abccf88dd827027b2ce917d464ec" + "18b62503bfbc077fbabb98f20d98ab34", + "8aed95ee5b0dcbfbef4eb21d3a3f52f9" + "625a1ab00ee39a5327346bddb01a9c18", + "a13a7c79c7e119b5ab0296ab28c300b9" + "f3e4c0a2e02d1d01f7f0a74618af2b48", + }}, + {"833222772a", + { + "80ad97bdc973df8a2e879e92a497efda" + "20f060c2f2e5126501d3d4fea10d5fc0", + "faa148e99046181fec6b2085f3b20ed9" + "f0daf5bab3d596839857846f73fbfe5a", + "1c7e2fc4639232fe297584b296996bc8" + "3db9b249406cc8edffac55ccd322ba12", + "e4f9f7e0066154bbd125b745569bc897" + "75d5ef262b44c41a9cf63ae14568e1b9", + "6da453dbf81e82334a3d8866cb50a1e3" + "7828d074119cab5c22b294d7a9bfa0bb", + "adb89cea9a15fbe617295bd04b8ca05c" + "6251d87fd4aaae9a7e4ad5c217d3f300", + "e7119bd6dd9b22afe8f89585432881e2" + "785b60fd7ec4e9fcb6545f350d660fab", + "afecc037fdb7b0838eb3d70bcd268382" + "dbc1a7b49d57358cc9fa6d61d73b7cf0", + "6349d126a37afcba89794f9804914fdc" + "bf42c3018c2f7c66bfde524975768115", + }}, + {"1910833222772a", + { + "bc9222dbd3274d8fc66d14ccbda6690b" + "7ae627410c9a2be693df5bb7485a63e3", + "3f0931aa03defb300f060103826f2a64" + "beaa9ec8d59bb68129f3027c96361181", + "74e04db46d28648d7dee8a0064b06cfe" + "9b5e81c62fe023c55be42f87bbf932b8", + "ce178fc1826efecbc182f57999a46140" + "8bdf55cd55061c06dba6be11de4a578a", + "626f5f4dce652501f3087d39c92cc349" + "42daac6a8f9ab9a7fd137c6037825682", + "cc03fdb79192a207312f53f5d4dc33d9" + "f70f14122a1c98a3155d28b8a0a8a41d", + "2a3a307ab2708a9c00fe0b42f9c2d6a1" + "862617627d2261eab0b1246597ca0ae9", + "55f877ce4f2e1ddbbf8e13e2cde0fdc8" + "1b1556cb935f173337705fbb5d501fc1", + "ecd0e96602be7f8d5092816cccf2c2e9" + "027881fab4993a1c262024a94fff3f61", + }}, + {"641910833222772a", + { + "bbf609de9413172d07660cb680716926" + "46101a6dab43115d6c522b4fe93604a9", + "cbe1fff21c96f3eef61e8fe0542cbdf0" + "347938bffa4009c512cfb4034b0dd1a7", + "7867a786d00a7147904d76ddf1e520e3" + "8d3e9e1caefcccb3fbf8d18f64120b32", + "942337f8fd76f0fae8c52d7954810672" + "b8548c10f51667f6e60e182fa19b30f7", + "0211c7c6190c9efd1237c34c8f2e06c4" + "bda64f65276d2aacb8f90212203a808e", + "bd3820f732ffb53ec193e79d33e27c73" + "d0168616861907d482e36cdac8cf5749", + "97b0f0f224b2d2317114808fb03af7a0" + "e59616e469787939a063ceea9af956d1", + "c47e0dc1660919c11101208f9e69aa1f" + "5ae4f12896b8379a2aad89b5b553d6b0", + "6b6b098d0c293bc2993d80bf0518b6d9" + "8170cc3ccd92a698621b939dd38fe7b9", + }}, + {"8b37641910833222772a", + { + "ab65c26eddb287600db2fda10d1e605c" + "bb759010c29658f2c72d93a2d16d2930", + "b901e8036ed1c383cd3c4c4dd0a6ab05" + "3d25ce4922924c55f064943353d78a6c", + "12c1aa44bbf87e75e611f69b2c38f49b" + "28f2b3434b65c09877470044c6ea170d", + "bd9ef822de5288196134cf8af7839304" + "67559c23f052158470a296f725735a32", + "8bab26fbc2c12b0f13e2ab185eabf241" + "31185a6d696f0cfa9b42808b38e132a2", + "564d3dae183c5234c8af1e51061c44b5" + "3c0778a7b5f72d3c23a3135c7d67b9f4", + "f34369890fcf16fb517dcaae4463b2dd" + "02f31c81e8200731b899b028e791bfa7", + "72da646283228c14300853701795616f" + "4e0a8c6f7934a788e2265e81d6d0c8f4", + "438dd5eafea0111b6f36b4b938da2a68" + "5f6bfc73815874d97100f086979357d8", + }}, + {"ebb46227c6cc8b37641910833222772a", + { + "720c94b63edf44e131d950ca211a5a30" + "c366fdeacf9ca80436be7c358424d20b", + "b3394a40aabf75cba42282ef25a0059f" + "4847d81da4942dbc249defc48c922b9f", + "08128c469f275342adda202b2b58da95" + "970dacef40ad98723bac5d6955b81761", + "3cb89993b07b0ced93de13d2a11013ac" + "ef2d676f1545c2c13dc680a02f4adbfe", + "b60595514f24bc9fe522a6cad7393644" + "b515a8c5011754f59003058bdb81514e", + "3c70047e8cbc038e3b9820db601da495" + "1175da6ee756de46a53e2b075660b770", + "00a542bba02111cc2c65b38ebdba587e" + "5865fdbb5b48064104e830b380f2aede", + "34b21ad2ad44e999db2d7f0863f0d9b6" + "84a9218fc36e8a5f2ccfbeae53a27d25", + "a2221a11b833ccb498a59540f0545f4a" + "5bbeb4787d59e5373fdbea6c6f75c29b", + }}, + {"c109163908ebe51debb46227c6cc8b37641910833222772a", + { + "54b64e6b5a20b5e2ec84593dc7989da7" + "c135eee237a85465ff97dc03924f45ce", + "cfcc922fb4a14ab45d6175aabbf2d201" + "837b87e2a446ad0ef798acd02b94124f", + "17a6dbd664926a0636b3f4c37a4f4694" + "4a5f9f26aeeed4d4a25f632d305233d9", + "80a3d01ef00c8e9a4209c17f4eeb358c" + "d15e7d5ffaaabc0207bf200a117793a2", + "349682bf588eaa52d0aa1560346aeafa" + "f5854cdb76c889e3ad63354e5f7275e3", + "532c7ceccb39df3236318405a4b1279c" + "baefe6d9ceb651842260e0d1e05e3b90", + "e82d8c6db54e3c633f581c952ba04207" + "4b16e50abd381bd70900a9cd9a62cb23", + "3682ee33bd148bd9f58656cd8f30d9fb" + "1e5a0b8475045d9b20b2628624edfd9e", + "63edd684fb826282fe528f9c0e9237bc" + "e4dd2e98d6960fae0b43545456743391", + }}, + {"1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a", + { + "dd5bcb0018e922d494759d7c395d02d3" + "c8446f8f77abf737685353eb89a1c9eb", + "af3e30f9c095045938151575c3fb9098" + "f8cb6274db99b80b1d2012a98ed48f0e", + "25c3005a1cb85de076259839ab7198ab" + "9dcbc183e8cb994b727b75be3180769c", + "a1d3078dfa9169503ed9d4491dee4eb2" + "8514a5495858096f596e4bcd66b10665", + "5f40d59ec1b03b33738efa60b2255d31" + "3477c7f764a41baceff90bf14f92b7cc", + "ac4e95368d99b9eb78b8da8f81ffa795" + "8c3c13f8c2388bb73f38576e65b7c446", + "13c4b9c1dfb66579eddd8a280b9f7316" + "ddd27820550126698efaadc64b64f66e", + "f08f2e66d28ed143f3a237cf9de73559" + "9ea36c525531b880ba124334f57b0b70", + "d5a39e3dfcc50280bac4a6b5aa0dca7d" + "370b1c1fe655916d97fd0d47ca1d72b8", + }}}; + + RC4_CTX ctx; + uint8_t key[64]; + uint8_t buffer[0x1010]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + size_t length = strlen(tests[i].key) / 2; + memcpy(key, fromhex(tests[i].key), length); + memzero(buffer, sizeof(buffer)); + + rc4_init(&ctx, key, length); + rc4_encrypt(&ctx, buffer, sizeof(buffer)); + + for (size_t j = 0; j < (sizeof(offsets) / sizeof(*offsets)); j++) { + size_t size = strlen(tests[i].vectors[j]) / 2; + ck_assert_mem_eq(&buffer[offsets[j]], fromhex(tests[i].vectors[j]), size); + } + } } END_TEST -#include "test_check_segwit.h" +static int my_strncasecmp(const char *s1, const char *s2, size_t n) { + size_t i = 0; + while (i < n) { + char c1 = s1[i]; + char c2 = s2[i]; + if (c1 >= 'A' && c1 <= 'Z') c1 = (c1 - 'A') + 'a'; + if (c2 >= 'A' && c2 <= 'Z') c2 = (c2 - 'A') + 'a'; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + if (c1 == 0) return 0; + ++i; + } + return 0; +} + #include "test_check_cashaddr.h" +#include "test_check_segwit.h" #if USE_CARDANO #include "test_check_cardano.h" @@ -4815,323 +8334,321 @@ END_TEST #endif // define test suite and cases -Suite *test_suite(void) -{ - Suite *s = suite_create("trezor-crypto"); - TCase *tc; - - tc = tcase_create("bignum"); - tcase_add_test(tc, test_bignum_read_be); - tcase_add_test(tc, test_bignum_write_be); - tcase_add_test(tc, test_bignum_is_equal); - tcase_add_test(tc, test_bignum_zero); - tcase_add_test(tc, test_bignum_is_zero); - tcase_add_test(tc, test_bignum_one); - tcase_add_test(tc, test_bignum_read_le); - tcase_add_test(tc, test_bignum_write_le); - tcase_add_test(tc, test_bignum_read_uint32); - tcase_add_test(tc, test_bignum_read_uint64); - tcase_add_test(tc, test_bignum_write_uint32); - tcase_add_test(tc, test_bignum_write_uint64); - tcase_add_test(tc, test_bignum_copy); - tcase_add_test(tc, test_bignum_is_even); - tcase_add_test(tc, test_bignum_is_odd); - tcase_add_test(tc, test_bignum_bitcount); - tcase_add_test(tc, test_bignum_digitcount); - tcase_add_test(tc, test_bignum_is_less); - tcase_add_test(tc, test_bignum_format); - tcase_add_test(tc, test_bignum_format_uint64); - suite_add_tcase(s, tc); - - tc = tcase_create("base32"); - tcase_add_test(tc, test_base32_rfc4648); - suite_add_tcase(s, tc); - - tc = tcase_create("base58"); - tcase_add_test(tc, test_base58); - suite_add_tcase(s, tc); +Suite *test_suite(void) { + Suite *s = suite_create("trezor-crypto"); + TCase *tc; + + tc = tcase_create("bignum"); + tcase_add_test(tc, test_bignum_read_be); + tcase_add_test(tc, test_bignum_write_be); + tcase_add_test(tc, test_bignum_is_equal); + tcase_add_test(tc, test_bignum_zero); + tcase_add_test(tc, test_bignum_is_zero); + tcase_add_test(tc, test_bignum_one); + tcase_add_test(tc, test_bignum_read_le); + tcase_add_test(tc, test_bignum_write_le); + tcase_add_test(tc, test_bignum_read_uint32); + tcase_add_test(tc, test_bignum_read_uint64); + tcase_add_test(tc, test_bignum_write_uint32); + tcase_add_test(tc, test_bignum_write_uint64); + tcase_add_test(tc, test_bignum_copy); + tcase_add_test(tc, test_bignum_is_even); + tcase_add_test(tc, test_bignum_is_odd); + tcase_add_test(tc, test_bignum_bitcount); + tcase_add_test(tc, test_bignum_digitcount); + tcase_add_test(tc, test_bignum_is_less); + tcase_add_test(tc, test_bignum_format); + tcase_add_test(tc, test_bignum_format_uint64); + suite_add_tcase(s, tc); + + tc = tcase_create("base32"); + tcase_add_test(tc, test_base32_rfc4648); + suite_add_tcase(s, tc); + + tc = tcase_create("base58"); + tcase_add_test(tc, test_base58); + suite_add_tcase(s, tc); #if USE_GRAPHENE - tc = tcase_create("base58gph"); - tcase_add_test(tc, test_base58gph); - suite_add_tcase(s, tc); + tc = tcase_create("base58gph"); + tcase_add_test(tc, test_base58gph); + suite_add_tcase(s, tc); #endif - tc = tcase_create("bignum_divmod"); - tcase_add_test(tc, test_bignum_divmod); - suite_add_tcase(s, tc); - - tc = tcase_create("bip32"); - tcase_add_test(tc, test_bip32_vector_1); - tcase_add_test(tc, test_bip32_vector_2); - tcase_add_test(tc, test_bip32_vector_3); - tcase_add_test(tc, test_bip32_compare); - tcase_add_test(tc, test_bip32_optimized); - tcase_add_test(tc, test_bip32_cache_1); - tcase_add_test(tc, test_bip32_cache_2); - suite_add_tcase(s, tc); - - tc = tcase_create("bip32-nist"); - tcase_add_test(tc, test_bip32_nist_seed); - tcase_add_test(tc, test_bip32_nist_vector_1); - tcase_add_test(tc, test_bip32_nist_vector_2); - tcase_add_test(tc, test_bip32_nist_compare); - tcase_add_test(tc, test_bip32_nist_repeat); - suite_add_tcase(s, tc); - - tc = tcase_create("bip32-ed25519"); - tcase_add_test(tc, test_bip32_ed25519_vector_1); - tcase_add_test(tc, test_bip32_ed25519_vector_2); - suite_add_tcase(s, tc); - - tc = tcase_create("bip32-ecdh"); - tcase_add_test(tc, test_bip32_ecdh_nist256p1); - tcase_add_test(tc, test_bip32_ecdh_curve25519); - tcase_add_test(tc, test_bip32_ecdh_errors); - suite_add_tcase(s, tc); - - tc = tcase_create("bip32-decred"); - tcase_add_test(tc, test_bip32_decred_vector_1); - tcase_add_test(tc, test_bip32_decred_vector_2); - suite_add_tcase(s, tc); - - tc = tcase_create("ecdsa"); - tcase_add_test(tc, test_ecdsa_signature); - suite_add_tcase(s, tc); - - tc = tcase_create("rfc6979"); - tcase_add_test(tc, test_rfc6979); - suite_add_tcase(s, tc); - - tc = tcase_create("address"); - tcase_add_test(tc, test_address); - suite_add_tcase(s, tc); - - tc = tcase_create("address_decode"); - tcase_add_test(tc, test_address_decode); - suite_add_tcase(s, tc); - - tc = tcase_create("ethereum_address"); - tcase_add_test(tc, test_ethereum_address); - suite_add_tcase(s, tc); - - tc = tcase_create("rsk_address"); - tcase_add_test(tc, test_rsk_address); - suite_add_tcase(s, tc); - - tc = tcase_create("wif"); - tcase_add_test(tc, test_wif); - suite_add_tcase(s, tc); - - tc = tcase_create("ecdsa_der"); - tcase_add_test(tc, test_ecdsa_der); - suite_add_tcase(s, tc); - - tc = tcase_create("aes"); - tcase_add_test(tc, test_aes); - suite_add_tcase(s, tc); - - tc = tcase_create("sha2"); - tcase_add_test(tc, test_sha1); - tcase_add_test(tc, test_sha256); - tcase_add_test(tc, test_sha512); - suite_add_tcase(s, tc); - - tc = tcase_create("sha3"); - tcase_add_test(tc, test_sha3_256); - tcase_add_test(tc, test_sha3_512); - tcase_add_test(tc, test_keccak_256); - suite_add_tcase(s, tc); - - tc = tcase_create("blake"); - tcase_add_test(tc, test_blake256); - suite_add_tcase(s, tc); - - tc = tcase_create("blake2"); - tcase_add_test(tc, test_blake2b); - tcase_add_test(tc, test_blake2s); - suite_add_tcase(s, tc); - - tc = tcase_create("pbkdf2"); - tcase_add_test(tc, test_pbkdf2_hmac_sha256); - tcase_add_test(tc, test_pbkdf2_hmac_sha512); - suite_add_tcase(s, tc); - - tc = tcase_create("bip39"); - tcase_add_test(tc, test_mnemonic); - tcase_add_test(tc, test_mnemonic_check); - tcase_add_test(tc, test_mnemonic_to_entropy); - suite_add_tcase(s, tc); - - tc = tcase_create("pubkey_validity"); - tcase_add_test(tc, test_pubkey_validity); - suite_add_tcase(s, tc); - - tc = tcase_create("pubkey_uncompress"); - tcase_add_test(tc, test_pubkey_uncompress); - suite_add_tcase(s, tc); - - tc = tcase_create("codepoints"); - tcase_add_test(tc, test_codepoints_secp256k1); - tcase_add_test(tc, test_codepoints_nist256p1); - suite_add_tcase(s, tc); - - tc = tcase_create("mult_border_cases"); - tcase_add_test(tc, test_mult_border_cases_secp256k1); - tcase_add_test(tc, test_mult_border_cases_nist256p1); - suite_add_tcase(s, tc); - - tc = tcase_create("scalar_mult"); - tcase_add_test(tc, test_scalar_mult_secp256k1); - tcase_add_test(tc, test_scalar_mult_nist256p1); - suite_add_tcase(s, tc); - - tc = tcase_create("point_mult"); - tcase_add_test(tc, test_point_mult_secp256k1); - tcase_add_test(tc, test_point_mult_nist256p1); - suite_add_tcase(s, tc); - - tc = tcase_create("scalar_point_mult"); - tcase_add_test(tc, test_scalar_point_mult_secp256k1); - tcase_add_test(tc, test_scalar_point_mult_nist256p1); - suite_add_tcase(s, tc); - - tc = tcase_create("ed25519"); - tcase_add_test(tc, test_ed25519); - suite_add_tcase(s, tc); - - tc = tcase_create("ed25519_keccak"); - tcase_add_test(tc, test_ed25519_keccak); - suite_add_tcase(s, tc); - - tc = tcase_create("ed25519_cosi"); - tcase_add_test(tc, test_ed25519_cosi); - suite_add_tcase(s, tc); - - tc = tcase_create("ed25519_modm"); - tcase_add_test(tc, test_ed25519_modl_add); - tcase_add_test(tc, test_ed25519_modl_neg); - tcase_add_test(tc, test_ed25519_modl_sub); - suite_add_tcase(s, tc); + tc = tcase_create("bignum_divmod"); + tcase_add_test(tc, test_bignum_divmod); + suite_add_tcase(s, tc); + + tc = tcase_create("bip32"); + tcase_add_test(tc, test_bip32_vector_1); + tcase_add_test(tc, test_bip32_vector_2); + tcase_add_test(tc, test_bip32_vector_3); + tcase_add_test(tc, test_bip32_compare); + tcase_add_test(tc, test_bip32_optimized); + tcase_add_test(tc, test_bip32_cache_1); + tcase_add_test(tc, test_bip32_cache_2); + suite_add_tcase(s, tc); + + tc = tcase_create("bip32-nist"); + tcase_add_test(tc, test_bip32_nist_seed); + tcase_add_test(tc, test_bip32_nist_vector_1); + tcase_add_test(tc, test_bip32_nist_vector_2); + tcase_add_test(tc, test_bip32_nist_compare); + tcase_add_test(tc, test_bip32_nist_repeat); + suite_add_tcase(s, tc); + + tc = tcase_create("bip32-ed25519"); + tcase_add_test(tc, test_bip32_ed25519_vector_1); + tcase_add_test(tc, test_bip32_ed25519_vector_2); + suite_add_tcase(s, tc); + + tc = tcase_create("bip32-ecdh"); + tcase_add_test(tc, test_bip32_ecdh_nist256p1); + tcase_add_test(tc, test_bip32_ecdh_curve25519); + tcase_add_test(tc, test_bip32_ecdh_errors); + suite_add_tcase(s, tc); + + tc = tcase_create("bip32-decred"); + tcase_add_test(tc, test_bip32_decred_vector_1); + tcase_add_test(tc, test_bip32_decred_vector_2); + suite_add_tcase(s, tc); + + tc = tcase_create("ecdsa"); + tcase_add_test(tc, test_ecdsa_signature); + suite_add_tcase(s, tc); + + tc = tcase_create("rfc6979"); + tcase_add_test(tc, test_rfc6979); + suite_add_tcase(s, tc); + + tc = tcase_create("address"); + tcase_add_test(tc, test_address); + suite_add_tcase(s, tc); + + tc = tcase_create("address_decode"); + tcase_add_test(tc, test_address_decode); + suite_add_tcase(s, tc); + + tc = tcase_create("ethereum_address"); + tcase_add_test(tc, test_ethereum_address); + suite_add_tcase(s, tc); + + tc = tcase_create("rsk_address"); + tcase_add_test(tc, test_rsk_address); + suite_add_tcase(s, tc); + + tc = tcase_create("wif"); + tcase_add_test(tc, test_wif); + suite_add_tcase(s, tc); + + tc = tcase_create("ecdsa_der"); + tcase_add_test(tc, test_ecdsa_der); + suite_add_tcase(s, tc); + + tc = tcase_create("aes"); + tcase_add_test(tc, test_aes); + suite_add_tcase(s, tc); + + tc = tcase_create("sha2"); + tcase_add_test(tc, test_sha1); + tcase_add_test(tc, test_sha256); + tcase_add_test(tc, test_sha512); + suite_add_tcase(s, tc); + + tc = tcase_create("sha3"); + tcase_add_test(tc, test_sha3_256); + tcase_add_test(tc, test_sha3_512); + tcase_add_test(tc, test_keccak_256); + suite_add_tcase(s, tc); + + tc = tcase_create("blake"); + tcase_add_test(tc, test_blake256); + suite_add_tcase(s, tc); + + tc = tcase_create("blake2"); + tcase_add_test(tc, test_blake2b); + tcase_add_test(tc, test_blake2s); + suite_add_tcase(s, tc); + + tc = tcase_create("pbkdf2"); + tcase_add_test(tc, test_pbkdf2_hmac_sha256); + tcase_add_test(tc, test_pbkdf2_hmac_sha512); + suite_add_tcase(s, tc); + + tc = tcase_create("bip39"); + tcase_add_test(tc, test_mnemonic); + tcase_add_test(tc, test_mnemonic_check); + tcase_add_test(tc, test_mnemonic_to_entropy); + suite_add_tcase(s, tc); + + tc = tcase_create("pubkey_validity"); + tcase_add_test(tc, test_pubkey_validity); + suite_add_tcase(s, tc); + + tc = tcase_create("pubkey_uncompress"); + tcase_add_test(tc, test_pubkey_uncompress); + suite_add_tcase(s, tc); + + tc = tcase_create("codepoints"); + tcase_add_test(tc, test_codepoints_secp256k1); + tcase_add_test(tc, test_codepoints_nist256p1); + suite_add_tcase(s, tc); + + tc = tcase_create("mult_border_cases"); + tcase_add_test(tc, test_mult_border_cases_secp256k1); + tcase_add_test(tc, test_mult_border_cases_nist256p1); + suite_add_tcase(s, tc); + + tc = tcase_create("scalar_mult"); + tcase_add_test(tc, test_scalar_mult_secp256k1); + tcase_add_test(tc, test_scalar_mult_nist256p1); + suite_add_tcase(s, tc); + + tc = tcase_create("point_mult"); + tcase_add_test(tc, test_point_mult_secp256k1); + tcase_add_test(tc, test_point_mult_nist256p1); + suite_add_tcase(s, tc); + + tc = tcase_create("scalar_point_mult"); + tcase_add_test(tc, test_scalar_point_mult_secp256k1); + tcase_add_test(tc, test_scalar_point_mult_nist256p1); + suite_add_tcase(s, tc); + + tc = tcase_create("ed25519"); + tcase_add_test(tc, test_ed25519); + suite_add_tcase(s, tc); + + tc = tcase_create("ed25519_keccak"); + tcase_add_test(tc, test_ed25519_keccak); + suite_add_tcase(s, tc); + + tc = tcase_create("ed25519_cosi"); + tcase_add_test(tc, test_ed25519_cosi); + suite_add_tcase(s, tc); + + tc = tcase_create("ed25519_modm"); + tcase_add_test(tc, test_ed25519_modl_add); + tcase_add_test(tc, test_ed25519_modl_neg); + tcase_add_test(tc, test_ed25519_modl_sub); + suite_add_tcase(s, tc); #if USE_MONERO - tc = tcase_create("ed25519_ge"); - tcase_add_test(tc, test_ge25519_double_scalarmult_vartime2); - suite_add_tcase(s, tc); + tc = tcase_create("ed25519_ge"); + tcase_add_test(tc, test_ge25519_double_scalarmult_vartime2); + suite_add_tcase(s, tc); #endif - tc = tcase_create("script"); - tcase_add_test(tc, test_output_script); - suite_add_tcase(s, tc); + tc = tcase_create("script"); + tcase_add_test(tc, test_output_script); + suite_add_tcase(s, tc); - tc = tcase_create("ethereum_pubkeyhash"); - tcase_add_test(tc, test_ethereum_pubkeyhash); - suite_add_tcase(s, tc); + tc = tcase_create("ethereum_pubkeyhash"); + tcase_add_test(tc, test_ethereum_pubkeyhash); + suite_add_tcase(s, tc); - tc = tcase_create("nem_address"); - tcase_add_test(tc, test_nem_address); - suite_add_tcase(s, tc); + tc = tcase_create("nem_address"); + tcase_add_test(tc, test_nem_address); + suite_add_tcase(s, tc); - tc = tcase_create("nem_encryption"); - tcase_add_test(tc, test_nem_derive); - tcase_add_test(tc, test_nem_cipher); - suite_add_tcase(s, tc); + tc = tcase_create("nem_encryption"); + tcase_add_test(tc, test_nem_derive); + tcase_add_test(tc, test_nem_cipher); + suite_add_tcase(s, tc); - tc = tcase_create("nem_transaction"); - tcase_add_test(tc, test_nem_transaction_transfer); - tcase_add_test(tc, test_nem_transaction_multisig); - tcase_add_test(tc, test_nem_transaction_provision_namespace); - tcase_add_test(tc, test_nem_transaction_mosaic_creation); - tcase_add_test(tc, test_nem_transaction_mosaic_supply_change); - tcase_add_test(tc, test_nem_transaction_aggregate_modification); - suite_add_tcase(s, tc); + tc = tcase_create("nem_transaction"); + tcase_add_test(tc, test_nem_transaction_transfer); + tcase_add_test(tc, test_nem_transaction_multisig); + tcase_add_test(tc, test_nem_transaction_provision_namespace); + tcase_add_test(tc, test_nem_transaction_mosaic_creation); + tcase_add_test(tc, test_nem_transaction_mosaic_supply_change); + tcase_add_test(tc, test_nem_transaction_aggregate_modification); + suite_add_tcase(s, tc); - tc = tcase_create("multibyte_address"); - tcase_add_test(tc, test_multibyte_address); - suite_add_tcase(s, tc); + tc = tcase_create("multibyte_address"); + tcase_add_test(tc, test_multibyte_address); + suite_add_tcase(s, tc); - tc = tcase_create("rc4"); - tcase_add_test(tc, test_rc4_rfc6229); - suite_add_tcase(s, tc); + tc = tcase_create("rc4"); + tcase_add_test(tc, test_rc4_rfc6229); + suite_add_tcase(s, tc); - tc = tcase_create("segwit"); - tcase_add_test(tc, test_segwit); - suite_add_tcase(s, tc); + tc = tcase_create("segwit"); + tcase_add_test(tc, test_segwit); + suite_add_tcase(s, tc); - tc = tcase_create("cashaddr"); - tcase_add_test(tc, test_cashaddr); - suite_add_tcase(s, tc); + tc = tcase_create("cashaddr"); + 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); + 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 #if USE_MONERO - tc = tcase_create("xmr_base58"); - tcase_add_test(tc, test_xmr_base58); - suite_add_tcase(s, tc); - - tc = tcase_create("xmr_crypto"); - tcase_add_test(tc, test_xmr_getset256_modm); - tcase_add_test(tc, test_xmr_cmp256_modm); - tcase_add_test(tc, test_xmr_copy_check_modm); - tcase_add_test(tc, test_xmr_mulsub256_modm); - tcase_add_test(tc, test_xmr_muladd256_modm); - tcase_add_test(tc, test_xmr_curve25519_set); - tcase_add_test(tc, test_xmr_curve25519_consts); - tcase_add_test(tc, test_xmr_curve25519_tests); - tcase_add_test(tc, test_xmr_curve25519_expand_reduce); - tcase_add_test(tc, test_xmr_ge25519_base); - tcase_add_test(tc, test_xmr_ge25519_check); - tcase_add_test(tc, test_xmr_ge25519_scalarmult_base_wrapper); - tcase_add_test(tc, test_xmr_ge25519_scalarmult); - tcase_add_test(tc, test_xmr_ge25519_ops); - suite_add_tcase(s, tc); - - tc = tcase_create("xmr_xmr"); - tcase_add_test(tc, test_xmr_check_point); - tcase_add_test(tc, test_xmr_h); - tcase_add_test(tc, test_xmr_fast_hash); - tcase_add_test(tc, test_xmr_hasher); - tcase_add_test(tc, test_xmr_hash_to_scalar); - tcase_add_test(tc, test_xmr_hash_to_ec); - tcase_add_test(tc, test_xmr_derivation_to_scalar); - tcase_add_test(tc, test_xmr_generate_key_derivation); - tcase_add_test(tc, test_xmr_derive_private_key); - tcase_add_test(tc, test_xmr_derive_public_key); - tcase_add_test(tc, test_xmr_add_keys2); - tcase_add_test(tc, test_xmr_add_keys3); - tcase_add_test(tc, test_xmr_get_subaddress_secret_key); - tcase_add_test(tc, test_xmr_gen_c); - tcase_add_test(tc, test_xmr_varint); - tcase_add_test(tc, test_xmr_gen_range_sig); - suite_add_tcase(s, tc); + tc = tcase_create("xmr_base58"); + tcase_add_test(tc, test_xmr_base58); + suite_add_tcase(s, tc); + + tc = tcase_create("xmr_crypto"); + tcase_add_test(tc, test_xmr_getset256_modm); + tcase_add_test(tc, test_xmr_cmp256_modm); + tcase_add_test(tc, test_xmr_copy_check_modm); + tcase_add_test(tc, test_xmr_mulsub256_modm); + tcase_add_test(tc, test_xmr_muladd256_modm); + tcase_add_test(tc, test_xmr_curve25519_set); + tcase_add_test(tc, test_xmr_curve25519_consts); + tcase_add_test(tc, test_xmr_curve25519_tests); + tcase_add_test(tc, test_xmr_curve25519_expand_reduce); + tcase_add_test(tc, test_xmr_ge25519_base); + tcase_add_test(tc, test_xmr_ge25519_check); + tcase_add_test(tc, test_xmr_ge25519_scalarmult_base_wrapper); + tcase_add_test(tc, test_xmr_ge25519_scalarmult); + tcase_add_test(tc, test_xmr_ge25519_ops); + suite_add_tcase(s, tc); + + tc = tcase_create("xmr_xmr"); + tcase_add_test(tc, test_xmr_check_point); + tcase_add_test(tc, test_xmr_h); + tcase_add_test(tc, test_xmr_fast_hash); + tcase_add_test(tc, test_xmr_hasher); + tcase_add_test(tc, test_xmr_hash_to_scalar); + tcase_add_test(tc, test_xmr_hash_to_ec); + tcase_add_test(tc, test_xmr_derivation_to_scalar); + tcase_add_test(tc, test_xmr_generate_key_derivation); + tcase_add_test(tc, test_xmr_derive_private_key); + tcase_add_test(tc, test_xmr_derive_public_key); + tcase_add_test(tc, test_xmr_add_keys2); + tcase_add_test(tc, test_xmr_add_keys3); + tcase_add_test(tc, test_xmr_get_subaddress_secret_key); + tcase_add_test(tc, test_xmr_gen_c); + tcase_add_test(tc, test_xmr_varint); + tcase_add_test(tc, test_xmr_gen_range_sig); + suite_add_tcase(s, tc); #endif - return s; + return s; } // run suite -int main(void) -{ - int number_failed; - Suite *s = test_suite(); - SRunner *sr = srunner_create(s); - srunner_run_all(sr, CK_VERBOSE); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - if (number_failed == 0) { - printf("PASSED ALL TESTS\n"); - } - return number_failed; +int main(void) { + int number_failed; + Suite *s = test_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + if (number_failed == 0) { + printf("PASSED ALL TESTS\n"); + } + return number_failed; } diff --git a/tests/test_check_cardano.h b/tests/test_check_cardano.h index 4c734dfad..434ea96b9 100644 --- a/tests/test_check_cardano.h +++ b/tests/test_check_cardano.h @@ -1,215 +1,379 @@ // 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; - } +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[] = + { + "6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea5" + "3", // private key + "60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8" + "e", // private key extension + "64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe" + "1", // public key + "45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c7" + "9331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10" + "d", // signature + + "e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830" + "c", // private key + "794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a" + "4", // private key extension + "95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931d" + "f", // public key + "f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b1" + "9ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560" + "f", // signature + + "9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0" + "c", // private key + "b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedeb" + "b", // private key extension + "79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19" + "f", // public key + "2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a" + "88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800" + "f", // signature + + "52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40" + "c", // private key + "6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a2580" + "3", // private key extension + "dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d" + "6", // public key + "0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a6" + "2a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd78160" + "2", // signature + + "11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec0" + "4", // private key + "c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a547340235" + "2", // private key extension + "839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db7" + "8", // public key + "e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f" + "9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa490" + "5", // signature + + "5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e50" + "5", // private key + "ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098c" + "d", // private key extension + "75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb7" + "6", // public key + "631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fb" + "c10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda59890" + "6", // signature + + "624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50" + "d", // private key + "097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b0" + "2", // private key extension + "0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b0" + "0", // public key + "1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a" + "57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f90" + "1", // 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 -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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); - - ck_assert_mem_eq(node.chain_code, fromhex("affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"), 32); - ck_assert_mem_eq(node.private_key, fromhex("08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("9a1d04808b4c0682816961cf666e82a7fd35949658aba5354c517eccf12aacb4"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); + + ck_assert_mem_eq( + node.chain_code, + fromhex( + "affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "9a1d04808b4c0682816961cf666e82a7fd35949658aba5354c517eccf12aacb4"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - - ck_assert_mem_eq(node.chain_code, fromhex("104c6a0736e501c9bfe2966ba3773f5320495b19c3f2ed222234850af2ccd5b1"), 32); - ck_assert_mem_eq(node.private_key, fromhex("6064bf06b2e981d7c9792b1482eeecd40ec3cfa12143f4a1f149d48ce8b6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("64aa9a16331f14c981b769efcf96addcc4c6db44047fe7a7feae0be23d33bf54"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("c651c14a13c2311fc30a7acf244add1fdac3683e7ba89b4571e4cbcab509b915"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000000); + + ck_assert_mem_eq( + node.chain_code, + fromhex( + "104c6a0736e501c9bfe2966ba3773f5320495b19c3f2ed222234850af2ccd5b1"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "6064bf06b2e981d7c9792b1482eeecd40ec3cfa12143f4a1f149d48ce8b6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "64aa9a16331f14c981b769efcf96addcc4c6db44047fe7a7feae0be23d33bf54"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "c651c14a13c2311fc30a7acf244add1fdac3683e7ba89b4571e4cbcab509b915"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000001); - - ck_assert_mem_eq(node.chain_code, fromhex("da99870d7e69de2a76f255ba8c7ed22428c7e5b0a8df978753c707c95ec3d4ca"), 32); - ck_assert_mem_eq(node.private_key, fromhex("c85fa69f4a1891fd98d1d1fc5f0cf9b1d6e44b0e6906744ab23ea766edb6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("b4fc241feffe840b8a54a26ab447f5a5caa31032db3a8091fca14f38b86ed539"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("5a5b0c92530cd366f05cf072509c806f904262c259e79a0080bbd5ee35706bb1"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node); + + hdnode_private_ckd_cardano(&node, 0x80000001); + + ck_assert_mem_eq( + node.chain_code, + fromhex( + "da99870d7e69de2a76f255ba8c7ed22428c7e5b0a8df978753c707c95ec3d4ca"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "c85fa69f4a1891fd98d1d1fc5f0cf9b1d6e44b0e6906744ab23ea766edb6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "b4fc241feffe840b8a54a26ab447f5a5caa31032db3a8091fca14f38b86ed539"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "5a5b0c92530cd366f05cf072509c806f904262c259e79a0080bbd5ee35706bb1"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, 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("b40c44dfd9be08591b62be7f9991c85f812d8196927f3c824d9fcb17d275089e"), 32); - ck_assert_mem_eq(node.private_key, fromhex("d064dcf1449d9c3e47f5b422680343561989035bf2e4e23fc34cb61fedb6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("a3071959013af95aaecf78a7a2e1b9838bbbc4864d6a8a2295243782078345cd"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("aaaca5e7adc69a03ef1f5c017ed02879e8ca871df028461ed9bf19fb8fa15038"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, 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( + "b40c44dfd9be08591b62be7f9991c85f812d8196927f3c824d9fcb17d275089e"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "d064dcf1449d9c3e47f5b422680343561989035bf2e4e23fc34cb61fedb6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "a3071959013af95aaecf78a7a2e1b9838bbbc4864d6a8a2295243782078345cd"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "aaaca5e7adc69a03ef1f5c017ed02879e8ca871df028461ed9bf19fb8fa15038"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, 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("2593896baf92f6ab2c0f253787ab16be0244ba95e0d48ba09da1a7fd3f926c72"), 32); - ck_assert_mem_eq(node.private_key, fromhex("0811b6d5d6f7120cb05d4ce5453d6ce42825c2a8e53b6d370a6b05ccf4b6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("5bebf1eea68acd04932653d944b064b10baaf5886dd73c185cc285059bf93363"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("1c87a32c5babad2fe33e0586bdc523574c6126f8368bc76598e17ea46201f980"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, 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( + "2593896baf92f6ab2c0f253787ab16be0244ba95e0d48ba09da1a7fd3f926c72"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "0811b6d5d6f7120cb05d4ce5453d6ce42825c2a8e53b6d370a6b05ccf4b6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "5bebf1eea68acd04932653d944b064b10baaf5886dd73c185cc285059bf93363"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "1c87a32c5babad2fe33e0586bdc523574c6126f8368bc76598e17ea46201f980"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, 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("fe8c6c2ab1e30385513fcffb49dcfe3e7805260425ea76b3b72b9f5bbe3b3d40"), 32); - ck_assert_mem_eq(node.private_key, fromhex("6019b9f5ef6ca530b657bcdb500de5455db8d51afb951fa045b6fbb3f6b6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("466332cb097934b43008701e7e27044aa56c7859019e4eba18d91a3bea23dff7"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("0b8f04755481ced76b4e5795aaafdb3cbd757c10fe60e9c58f48cf29a7ec3575"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, 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( + "fe8c6c2ab1e30385513fcffb49dcfe3e7805260425ea76b3b72b9f5bbe3b3d40"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "6019b9f5ef6ca530b657bcdb500de5455db8d51afb951fa045b6fbb3f6b6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "466332cb097934b43008701e7e27044aa56c7859019e4eba18d91a3bea23dff7"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "0b8f04755481ced76b4e5795aaafdb3cbd757c10fe60e9c58f48cf29a7ec3575"), + 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); - ck_assert_int_eq(seed_len, 132); - hdnode_from_seed_cardano((const uint8_t *)"", 0, 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("ff77c08d37471c1d4cedd3fae2642c009324d9712492efc74dedab09c9bf973c"), 32); - ck_assert_mem_eq(node.private_key, fromhex("488f34840bba516f7920f91676b8681d0dd833b4ce14468e0810b255f9b6ea46"), 32); - ck_assert_mem_eq(node.private_key_extension, fromhex("01eccef768a79859f824a1d3c3e35e131184e2940c3fca9a4c9b307741f65363"), 32); - hdnode_fill_public_key(&node); - ck_assert_mem_eq(node.public_key + 1, fromhex("148605be54585773b44ba87e79265149ae444c4cc37cb1f8db8c08482fba293b"), 32); +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); + ck_assert_int_eq(seed_len, 132); + hdnode_from_seed_cardano((const uint8_t *)"", 0, 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( + "ff77c08d37471c1d4cedd3fae2642c009324d9712492efc74dedab09c9bf973c"), + 32); + ck_assert_mem_eq( + node.private_key, + fromhex( + "488f34840bba516f7920f91676b8681d0dd833b4ce14468e0810b255f9b6ea46"), + 32); + ck_assert_mem_eq( + node.private_key_extension, + fromhex( + "01eccef768a79859f824a1d3c3e35e131184e2940c3fca9a4c9b307741f65363"), + 32); + hdnode_fill_public_key(&node); + ck_assert_mem_eq( + node.public_key + 1, + fromhex( + "148605be54585773b44ba87e79265149ae444c4cc37cb1f8db8c08482fba293b"), + 32); } END_TEST diff --git a/tests/test_check_cashaddr.h b/tests/test_check_cashaddr.h index cc4608730..d38b744a6 100644 --- a/tests/test_check_cashaddr.h +++ b/tests/test_check_cashaddr.h @@ -1,76 +1,67 @@ #include "cash_addr.h" static const char* valid_cashchecksum[] = { - "prefix:x64nx6hz", - "p:gpf8m4h7", - "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn", - "bchtest:testnetaddress4d6njnut", - "bchreg:555555555555555555555555555555555555555555555udxmlmrz", + "prefix:x64nx6hz", + "p:gpf8m4h7", + "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn", + "bchtest:testnetaddress4d6njnut", + "bchreg:555555555555555555555555555555555555555555555udxmlmrz", }; struct valid_cashaddr_data { - const char* legacy; - const char* cashaddress; + const char* legacy; + const char* cashaddress; }; static struct valid_cashaddr_data valid_cashaddr[] = { - { - "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu", - "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a" - }, - { - "1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR", - "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy" - }, - { - "16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb", - "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r" - }, - { - "3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC", - "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq" - }, - { - "3LDsS579y7sruadqu11beEJoTjdFiFCdX4", - "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e" - }, - { - "31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw", - "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37" - } -}; + {"1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu", + "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"}, + {"1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR", + "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"}, + {"16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb", + "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"}, + {"3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC", + "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"}, + {"3LDsS579y7sruadqu11beEJoTjdFiFCdX4", + "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"}, + {"31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw", + "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"}}; -START_TEST(test_cashaddr) -{ - size_t i; - for (i = 0; i < sizeof(valid_cashchecksum) / sizeof(valid_cashchecksum[0]); ++i) { - uint8_t data[82]; - char rebuild[92]; - char hrp[84]; - size_t data_len; - int res = cash_decode(hrp, data, &data_len, valid_cashchecksum[i]); - ck_assert_int_eq(res, 1); - res = cash_encode(rebuild, hrp, data, data_len); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashchecksum[i], 92), 0); - } - for (i = 0; i < sizeof(valid_cashaddr) / sizeof(valid_cashaddr[0]); ++i) { - uint8_t prog[65]; - size_t prog_len; - const char* hrp = "bitcoincash"; - uint8_t rawdata[65]; - size_t rawdata_len; - char rebuild[93]; - int ret = cash_addr_decode(prog, &prog_len, hrp, valid_cashaddr[i].cashaddress); - ck_assert_int_eq(ret, 1); - ck_assert_int_eq(prog_len, 21); - rawdata_len = base58_decode_check(valid_cashaddr[i].legacy, HASHER_SHA2D, rawdata, sizeof(rawdata)); - ck_assert_int_eq(rawdata_len, 21); - ck_assert_int_eq(prog[0], rawdata[0] == 0 ? 0x00 : rawdata[0] == 5 ? 0x08 : -1); - ck_assert_int_eq(memcmp(rawdata + 1, prog + 1, 20), 0); - ret = cash_addr_encode(rebuild, hrp, prog, 21); - ck_assert_int_eq(ret, 1); - ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashaddr[i].cashaddress, 92), 0); - } +START_TEST(test_cashaddr) { + size_t i; + for (i = 0; i < sizeof(valid_cashchecksum) / sizeof(valid_cashchecksum[0]); + ++i) { + uint8_t data[82]; + char rebuild[92]; + char hrp[84]; + size_t data_len; + int res = cash_decode(hrp, data, &data_len, valid_cashchecksum[i]); + ck_assert_int_eq(res, 1); + res = cash_encode(rebuild, hrp, data, data_len); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashchecksum[i], 92), 0); + } + for (i = 0; i < sizeof(valid_cashaddr) / sizeof(valid_cashaddr[0]); ++i) { + uint8_t prog[65]; + size_t prog_len; + const char* hrp = "bitcoincash"; + uint8_t rawdata[65]; + size_t rawdata_len; + char rebuild[93]; + int ret = + cash_addr_decode(prog, &prog_len, hrp, valid_cashaddr[i].cashaddress); + ck_assert_int_eq(ret, 1); + ck_assert_int_eq(prog_len, 21); + rawdata_len = base58_decode_check(valid_cashaddr[i].legacy, HASHER_SHA2D, + rawdata, sizeof(rawdata)); + ck_assert_int_eq(rawdata_len, 21); + ck_assert_int_eq(prog[0], + rawdata[0] == 0 ? 0x00 : rawdata[0] == 5 ? 0x08 : -1); + ck_assert_int_eq(memcmp(rawdata + 1, prog + 1, 20), 0); + ret = cash_addr_encode(rebuild, hrp, prog, 21); + ck_assert_int_eq(ret, 1); + ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashaddr[i].cashaddress, 92), + 0); + } } END_TEST diff --git a/tests/test_check_monero.h b/tests/test_check_monero.h index 86e355d2a..80ad1eb8a 100644 --- a/tests/test_check_monero.h +++ b/tests/test_check_monero.h @@ -1,1225 +1,1180 @@ #if USE_MONERO -START_TEST(test_xmr_base58) -{ - static const struct { - uint64_t tag; - char *v1; - char *v2; - } tests[] = { - {0x12, - "3bec484c5d7f0246af520aab550452b5b6013733feabebd681c4a60d457b7fc12d5918e31d3c003da3c778592c07b398ad6f961a67082a75fd49394d51e69bbe", - "43tpGG9PKbwCpjRvNLn1jwXPpnacw2uVUcszAtgmDiVcZK4VgHwjJT9BJz1WGF9eMxSYASp8yNMkuLjeQfWqJn3CNWdWfzV" - }, - {0x12, - "639050436fa36c8288706771412c5972461578d564188cd7fc6f81d6973d064fa461afe66fb23879936d7225051bebbf7f3ae0c801a90bb99fbb346b2fd4d702", - "45PwgoUKaDHNqLL8o3okzLL7biv7GqPVmd8LTcTrYVrMEKdSYwFcyJfMLSRpfU3nh8Z2m81FJD4sUY3nXCdGe61k1HAp8T1" - }, - {53, - "5a10cca900ee47a7f412cd661b29f5ab356d6a1951884593bb170b5ec8b6f2e83b1da411527d062c9fedeb2dad669f2f5585a00a88462b8c95c809a630e5734c", - "9vacMKaj8JJV6MnwDzh2oNVdwTLJfTDyNRiB6NzV9TT7fqvzLivH2dB8Tv7VYR3ncn8vCb3KdNMJzQWrPAF1otYJ9cPKpkr" - }, - }; - - uint8_t rawn[512]; - char strn[512]; - int r; - uint64_t tag; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - const char *raw = tests[i].v1; - const char *str = tests[i].v2; - const size_t len = strlen(raw) / 2; - - memcpy(rawn, fromhex(raw), len); - - r = xmr_base58_addr_encode_check(tests[i].tag, rawn, len, strn, sizeof(strn)); - ck_assert_int_eq((size_t) r, strlen(str)); - ck_assert_mem_eq(strn, str, r); - - r = xmr_base58_addr_decode_check(strn, r, &tag, rawn, len); - ck_assert_int_eq(r, len); - ck_assert_mem_eq(rawn, fromhex(raw), len); - } +START_TEST(test_xmr_base58) { + static const struct { + uint64_t tag; + char *v1; + char *v2; + } tests[] = { + {0x12, + "3bec484c5d7f0246af520aab550452b5b6013733feabebd681c4a60d457b7fc12d5918e" + "31d3c003da3c778592c07b398ad6f961a67082a75fd49394d51e69bbe", + "43tpGG9PKbwCpjRvNLn1jwXPpnacw2uVUcszAtgmDiVcZK4VgHwjJT9BJz1WGF9eMxSYASp" + "8yNMkuLjeQfWqJn3CNWdWfzV"}, + {0x12, + "639050436fa36c8288706771412c5972461578d564188cd7fc6f81d6973d064fa461afe" + "66fb23879936d7225051bebbf7f3ae0c801a90bb99fbb346b2fd4d702", + "45PwgoUKaDHNqLL8o3okzLL7biv7GqPVmd8LTcTrYVrMEKdSYwFcyJfMLSRpfU3nh8Z2m81" + "FJD4sUY3nXCdGe61k1HAp8T1"}, + {53, + "5a10cca900ee47a7f412cd661b29f5ab356d6a1951884593bb170b5ec8b6f2e83b1da41" + "1527d062c9fedeb2dad669f2f5585a00a88462b8c95c809a630e5734c", + "9vacMKaj8JJV6MnwDzh2oNVdwTLJfTDyNRiB6NzV9TT7fqvzLivH2dB8Tv7VYR3ncn8vCb3" + "KdNMJzQWrPAF1otYJ9cPKpkr"}, + }; + + uint8_t rawn[512]; + char strn[512]; + int r; + uint64_t tag; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + const char *raw = tests[i].v1; + const char *str = tests[i].v2; + const size_t len = strlen(raw) / 2; + + memcpy(rawn, fromhex(raw), len); + + r = xmr_base58_addr_encode_check(tests[i].tag, rawn, len, strn, + sizeof(strn)); + ck_assert_int_eq((size_t)r, strlen(str)); + ck_assert_mem_eq(strn, str, r); + + r = xmr_base58_addr_decode_check(strn, r, &tag, rawn, len); + ck_assert_int_eq(r, len); + ck_assert_mem_eq(rawn, fromhex(raw), len); + } } END_TEST - -START_TEST(test_xmr_getset256_modm) -{ - static const struct { - uint64_t val; - int r; - char *a; - } tests[] = { - {0x0, 1, - "0000000000000000000000000000000000000000000000000000000000000000"}, - {0x7fffffffULL, 1, - "ffffff7f00000000000000000000000000000000000000000000000000000000"}, - {0x7fffffffffffffffULL, 1, - "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, - {0xdeadc0deULL, 1, - "dec0adde00000000000000000000000000000000000000000000000000000000"}, - {0x0, 0, - "dec0adde000000000000000000000000000000000000000000000000000000ff"}, - {0x0, 0, - "ffffffffffffffffff0000000000000000000000000000000000000000000000"}, - }; - - uint8_t rawn[32]; - uint64_t v1; - bignum256modm a1 = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - int get_res = tests[i].r; - if (get_res) { - set256_modm(a1, tests[i].val); - ck_assert_int_eq(get256_modm(&v1, a1), 1); - ck_assert(v1 == tests[i].val); - - contract256_modm(rawn, a1); - ck_assert_mem_eq(rawn, fromhex(tests[i].a), 32); - - } else { - expand256_modm(a1, fromhex(tests[i].a), 32); - ck_assert_int_eq(get256_modm(&v1, a1), 0); - } - } +START_TEST(test_xmr_getset256_modm) { + static const struct { + uint64_t val; + int r; + char *a; + } tests[] = { + {0x0, 1, + "0000000000000000000000000000000000000000000000000000000000000000"}, + {0x7fffffffULL, 1, + "ffffff7f00000000000000000000000000000000000000000000000000000000"}, + {0x7fffffffffffffffULL, 1, + "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, + {0xdeadc0deULL, 1, + "dec0adde00000000000000000000000000000000000000000000000000000000"}, + {0x0, 0, + "dec0adde000000000000000000000000000000000000000000000000000000ff"}, + {0x0, 0, + "ffffffffffffffffff0000000000000000000000000000000000000000000000"}, + }; + + uint8_t rawn[32]; + uint64_t v1; + bignum256modm a1 = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + int get_res = tests[i].r; + if (get_res) { + set256_modm(a1, tests[i].val); + ck_assert_int_eq(get256_modm(&v1, a1), 1); + ck_assert(v1 == tests[i].val); + + contract256_modm(rawn, a1); + ck_assert_mem_eq(rawn, fromhex(tests[i].a), 32); + + } else { + expand256_modm(a1, fromhex(tests[i].a), 32); + ck_assert_int_eq(get256_modm(&v1, a1), 0); + } + } } END_TEST - -START_TEST(test_xmr_cmp256_modm) -{ - static const struct { - char *a; - char *b; - int res_eq; - int res_cmp; - int res_is_zero_a; - } tests[] = { - { - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - 1, 0, 1 - }, - { - "0000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - 0, -1, 1 - }, - { - "dec0adde00000000000000000000000000000000000000000000000000000000", - "dec0adde00000000000000000000000000000000000000000000000000000000", - 1, 0, 0 - }, - { - "863346d8863c461cde2ec7c2759352c2b952228f33a86ca06bb79574bbe5c30d", - "3ddbd65a6d3ba5e2ab120603685a353a27ce3fd21dfdbea7952d2dd26f1ca00a", - 0, 1, 0 - }, - { - "f7667f392edbea6e224b1aa9fbf2a3b238b4f977fb4a8f39130cc45f49b5c40a", - "b41b9b1e7e80be71cf290ed4bded58924086b8ac6bdfa1faa0c80c255f074d07", - 0, 1, 0 - }, - { - "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27501", - "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", - 0, -1, 0 - }, - { - "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", - "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", - 1, 0, 0 - }, - { - "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", - "0e4005c7826de8f9978749903f41efd140e4ae6d3bed09e558fcce8367b27504", - 0, -1, 0 - }, - }; - - bignum256modm a1 = {0}, a2 = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a1, fromhex(tests[i].a), 32); - expand256_modm(a2, fromhex(tests[i].b), 32); - - ck_assert_int_eq(eq256_modm(a1, a2), tests[i].res_eq); - ck_assert_int_eq(cmp256_modm(a1, a2), tests[i].res_cmp); - ck_assert_int_eq(iszero256_modm(a1), tests[i].res_is_zero_a); - } +START_TEST(test_xmr_cmp256_modm) { + static const struct { + char *a; + char *b; + int res_eq; + int res_cmp; + int res_is_zero_a; + } tests[] = { + {"0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", 1, 0, + 1}, + {"0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", 0, + -1, 1}, + {"dec0adde00000000000000000000000000000000000000000000000000000000", + "dec0adde00000000000000000000000000000000000000000000000000000000", 1, 0, + 0}, + {"863346d8863c461cde2ec7c2759352c2b952228f33a86ca06bb79574bbe5c30d", + "3ddbd65a6d3ba5e2ab120603685a353a27ce3fd21dfdbea7952d2dd26f1ca00a", 0, 1, + 0}, + {"f7667f392edbea6e224b1aa9fbf2a3b238b4f977fb4a8f39130cc45f49b5c40a", + "b41b9b1e7e80be71cf290ed4bded58924086b8ac6bdfa1faa0c80c255f074d07", 0, 1, + 0}, + {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27501", + "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 0, + -1, 0}, + {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", + "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 1, 0, + 0}, + {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", + "0e4005c7826de8f9978749903f41efd140e4ae6d3bed09e558fcce8367b27504", 0, + -1, 0}, + }; + + bignum256modm a1 = {0}, a2 = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a1, fromhex(tests[i].a), 32); + expand256_modm(a2, fromhex(tests[i].b), 32); + + ck_assert_int_eq(eq256_modm(a1, a2), tests[i].res_eq); + ck_assert_int_eq(cmp256_modm(a1, a2), tests[i].res_cmp); + ck_assert_int_eq(iszero256_modm(a1), tests[i].res_is_zero_a); + } } END_TEST - -START_TEST(test_xmr_copy_check_modm) -{ - static const struct { - int check; - char *a; - } tests[] = { - {0, - "0000000000000000000000000000000000000000000000000000000000000000"}, - {1, - "ffffff7f00000000000000000000000000000000000000000000000000000000"}, - {1, - "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, - {1, - "dec0adde00000000000000000000000000000000000000000000000000000000"}, - {0, - "dec0adde000000000000000000000fffffffffffffffffffffffffffffffffff"}, - }; - - bignum256modm a1 = {0}, a2 = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand_raw256_modm(a1, fromhex(tests[i].a)); - copy256_modm(a2, a1); - ck_assert_int_eq(eq256_modm(a1, a2), 1); - ck_assert_int_eq(check256_modm(a1), tests[i].check); - } - +START_TEST(test_xmr_copy_check_modm) { + static const struct { + int check; + char *a; + } tests[] = { + {0, "0000000000000000000000000000000000000000000000000000000000000000"}, + {1, "ffffff7f00000000000000000000000000000000000000000000000000000000"}, + {1, "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, + {1, "dec0adde00000000000000000000000000000000000000000000000000000000"}, + {0, "dec0adde000000000000000000000fffffffffffffffffffffffffffffffffff"}, + }; + + bignum256modm a1 = {0}, a2 = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand_raw256_modm(a1, fromhex(tests[i].a)); + copy256_modm(a2, a1); + ck_assert_int_eq(eq256_modm(a1, a2), 1); + ck_assert_int_eq(check256_modm(a1), tests[i].check); + } } END_TEST - -START_TEST(test_xmr_mulsub256_modm) -{ - static const struct { - char *a; - char *b; - char *c; - char *r; - } tests[] = { - { - "713c199348cf7d14b67ae6265ea49c02c8647f07afcbcb6f8d3254b3db972e02", - "4e48a7b7a03ab1106fdfa9441a03c97c644395a12ac4b8effac7344e0719c200", - "1a5711b8c43bcab0161a620368d82727e1d027dc248f420d9bb4db2486c16405", - "6edcc08aa6ec3a5b3d333b5f826be7de9c268be8aaf9521586fbcccbed3b1c0c", - }, - { - "d4ade2c62d34af8cfd9daec6f46bf7e57962a8aa46935cb11fab64fa599b4700", - "22ea7989a9f4d34cd8c9442e03b5062dfe8493757cd18a63411cb1a25e44960f", - "772053e613f0859387badcefeb7fbe551a05b00b9337539c8d72661de5929806", - "a5063258df4520b33e97c0a46d80feeace5c251fc7ef7a938d160b8f25795106", - }, - { - "01fd2ef25c8221277a2b6daf1f1642bacb8d6ac0dd4f62731cdd73e26eb77900", - "0611b9357530aa638428002769ce0ad553421e971bea1f10d7009bf26d9af805", - "dfece232068b2f8059ca569f345baaed13ab464eb3bebb99de5625dc90a8cf03", - "85752e62bd8085c7c02d5edeb74969d22f1a5bb34349258d2e96de300176bb07", - }, - }; - - bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i].a), 32); - expand256_modm(b, fromhex(tests[i].b), 32); - expand256_modm(c, fromhex(tests[i].c), 32); - expand256_modm(r, fromhex(tests[i].r), 32); - mulsub256_modm(r2, a, b, c); - ck_assert_int_eq(eq256_modm(r, r2), 1); - } +START_TEST(test_xmr_mulsub256_modm) { + static const struct { + char *a; + char *b; + char *c; + char *r; + } tests[] = { + { + "713c199348cf7d14b67ae6265ea49c02c8647f07afcbcb6f8d3254b3db972e02", + "4e48a7b7a03ab1106fdfa9441a03c97c644395a12ac4b8effac7344e0719c200", + "1a5711b8c43bcab0161a620368d82727e1d027dc248f420d9bb4db2486c16405", + "6edcc08aa6ec3a5b3d333b5f826be7de9c268be8aaf9521586fbcccbed3b1c0c", + }, + { + "d4ade2c62d34af8cfd9daec6f46bf7e57962a8aa46935cb11fab64fa599b4700", + "22ea7989a9f4d34cd8c9442e03b5062dfe8493757cd18a63411cb1a25e44960f", + "772053e613f0859387badcefeb7fbe551a05b00b9337539c8d72661de5929806", + "a5063258df4520b33e97c0a46d80feeace5c251fc7ef7a938d160b8f25795106", + }, + { + "01fd2ef25c8221277a2b6daf1f1642bacb8d6ac0dd4f62731cdd73e26eb77900", + "0611b9357530aa638428002769ce0ad553421e971bea1f10d7009bf26d9af805", + "dfece232068b2f8059ca569f345baaed13ab464eb3bebb99de5625dc90a8cf03", + "85752e62bd8085c7c02d5edeb74969d22f1a5bb34349258d2e96de300176bb07", + }, + }; + + bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i].a), 32); + expand256_modm(b, fromhex(tests[i].b), 32); + expand256_modm(c, fromhex(tests[i].c), 32); + expand256_modm(r, fromhex(tests[i].r), 32); + mulsub256_modm(r2, a, b, c); + ck_assert_int_eq(eq256_modm(r, r2), 1); + } } END_TEST - -START_TEST(test_xmr_muladd256_modm) -{ - static const struct { - char *a; - char *b; - char *c; - char *r; - } tests[] = { - { - "7c3fd8abfbe2be3739d91679ac8dbda086961b941e0d4a00561f758927d8aa09", - "ac2d8d37e4f344aa4040d0f0fc29d45423ab7e69ecacb94ca9fc36819e0e990e", - "2f03f1bac09bc7d002848b68be069dc98b2db028390ae37e13a5166fcae08105", - "dce113add3392f08e3b38b7d31e237eba5066e5a95a1fdbf755b92d05e1ec70b", - }, - { - "6979b70f6198d043f4b14e2069f7b89cc9f09e3465e71d472946443989e0e80c", - "8dd5177bc8d7c5bd58c0be74b336952a73ac259ebb812ac8cd755773c6aab807", - "d7658e508a7454ccfb29e2890d6156ac10e18ebe6e00cc5a2d2d87a5080c7f06", - "51b33f6263772781cdbab26ef48870eaf94899894a437dac39496f15b9d0ae00", - }, - { - "ebfdb4eabedb1fb9a45b3204735b0511871e20358392fa16a851c519e3a29b09", - "59d98831e9f9e24260158986c4d4035438de9b8876cc11bdcf4c364c75f72908", - "93bce4764eee97dc67f2e37da40bc5641f2cdc637285d273287a3d4383b68f02", - "21547ca6855c85d5adcd673b9d801d0cb0f10dced8f8b68a8c2f74163defde0e", - }, - }; - - bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i].a), 32); - expand256_modm(b, fromhex(tests[i].b), 32); - expand256_modm(c, fromhex(tests[i].c), 32); - expand256_modm(r, fromhex(tests[i].r), 32); - muladd256_modm(r2, a, b, c); - ck_assert_int_eq(eq256_modm(r, r2), 1); - } - +START_TEST(test_xmr_muladd256_modm) { + static const struct { + char *a; + char *b; + char *c; + char *r; + } tests[] = { + { + "7c3fd8abfbe2be3739d91679ac8dbda086961b941e0d4a00561f758927d8aa09", + "ac2d8d37e4f344aa4040d0f0fc29d45423ab7e69ecacb94ca9fc36819e0e990e", + "2f03f1bac09bc7d002848b68be069dc98b2db028390ae37e13a5166fcae08105", + "dce113add3392f08e3b38b7d31e237eba5066e5a95a1fdbf755b92d05e1ec70b", + }, + { + "6979b70f6198d043f4b14e2069f7b89cc9f09e3465e71d472946443989e0e80c", + "8dd5177bc8d7c5bd58c0be74b336952a73ac259ebb812ac8cd755773c6aab807", + "d7658e508a7454ccfb29e2890d6156ac10e18ebe6e00cc5a2d2d87a5080c7f06", + "51b33f6263772781cdbab26ef48870eaf94899894a437dac39496f15b9d0ae00", + }, + { + "ebfdb4eabedb1fb9a45b3204735b0511871e20358392fa16a851c519e3a29b09", + "59d98831e9f9e24260158986c4d4035438de9b8876cc11bdcf4c364c75f72908", + "93bce4764eee97dc67f2e37da40bc5641f2cdc637285d273287a3d4383b68f02", + "21547ca6855c85d5adcd673b9d801d0cb0f10dced8f8b68a8c2f74163defde0e", + }, + }; + + bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i].a), 32); + expand256_modm(b, fromhex(tests[i].b), 32); + expand256_modm(c, fromhex(tests[i].c), 32); + expand256_modm(r, fromhex(tests[i].r), 32); + muladd256_modm(r2, a, b, c); + ck_assert_int_eq(eq256_modm(r, r2), 1); + } } END_TEST - -START_TEST(test_xmr_curve25519_set) -{ - static const struct { - uint32_t val; - char *a; - } tests[] = { - {0x0, - "0000000000000000000000000000000000000000000000000000000000000000"}, - {0x1, - "0100000000000000000000000000000000000000000000000000000000000000"}, - {0xdeadc0deUL, - "dec0adde00000000000000000000000000000000000000000000000000000000"}, - }; - - unsigned char buff[32]; - bignum25519 a = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - curve25519_set(a, tests[i].val); - curve25519_contract(buff, a); - ck_assert_mem_eq(buff, fromhex(tests[i].a), 32); - } +START_TEST(test_xmr_curve25519_set) { + static const struct { + uint32_t val; + char *a; + } tests[] = { + {0x0, "0000000000000000000000000000000000000000000000000000000000000000"}, + {0x1, "0100000000000000000000000000000000000000000000000000000000000000"}, + {0xdeadc0deUL, + "dec0adde00000000000000000000000000000000000000000000000000000000"}, + }; + + unsigned char buff[32]; + bignum25519 a = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + curve25519_set(a, tests[i].val); + curve25519_contract(buff, a); + ck_assert_mem_eq(buff, fromhex(tests[i].a), 32); + } } END_TEST +START_TEST(test_xmr_curve25519_consts) { + char *d = "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"; + char *d2 = "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624"; + char *sqrtneg1 = + "b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"; -START_TEST(test_xmr_curve25519_consts) -{ - char *d = "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"; - char *d2 = "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624"; - char *sqrtneg1 = "b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"; - - unsigned char buff[32]; - bignum25519 a = {0}; + unsigned char buff[32]; + bignum25519 a = {0}; - curve25519_set_d(a); - curve25519_contract(buff, a); - ck_assert_mem_eq(buff, fromhex(d), 32); + curve25519_set_d(a); + curve25519_contract(buff, a); + ck_assert_mem_eq(buff, fromhex(d), 32); - curve25519_set_2d(a); - curve25519_contract(buff, a); - ck_assert_mem_eq(buff, fromhex(d2), 32); + curve25519_set_2d(a); + curve25519_contract(buff, a); + ck_assert_mem_eq(buff, fromhex(d2), 32); - curve25519_set_sqrtneg1(a); - curve25519_contract(buff, a); - ck_assert_mem_eq(buff, fromhex(sqrtneg1), 32); + curve25519_set_sqrtneg1(a); + curve25519_contract(buff, a); + ck_assert_mem_eq(buff, fromhex(sqrtneg1), 32); } END_TEST - -START_TEST(test_xmr_curve25519_tests) -{ - static const struct { - char *a; - int res_neg; - int res_nonzero; - } tests[] = { - { - "0000000000000000000000000000000000000000000000000000000000000000", - 0, 0, - }, - { - "0100000000000000000000000000000000000000000000000000000000000000", - 1, 1, - }, - { - "05737aa6100ee54283dc0d483b8e39e61846f6b3736908243d0c824d250b3139", - 1, 1, - }, - { - "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", - 1, 1, - }, - { - "02587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", - 0, 1, - }, - }; - - bignum25519 a = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - curve25519_expand(a, fromhex(tests[i].a)); - ck_assert_int_eq(curve25519_isnegative(a), tests[i].res_neg); - ck_assert_int_eq(curve25519_isnonzero(a), tests[i].res_nonzero); - } +START_TEST(test_xmr_curve25519_tests) { + static const struct { + char *a; + int res_neg; + int res_nonzero; + } tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + 0, + 0, + }, + { + "0100000000000000000000000000000000000000000000000000000000000000", + 1, + 1, + }, + { + "05737aa6100ee54283dc0d483b8e39e61846f6b3736908243d0c824d250b3139", + 1, + 1, + }, + { + "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", + 1, + 1, + }, + { + "02587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", + 0, + 1, + }, + }; + + bignum25519 a = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + curve25519_expand(a, fromhex(tests[i].a)); + ck_assert_int_eq(curve25519_isnegative(a), tests[i].res_neg); + ck_assert_int_eq(curve25519_isnonzero(a), tests[i].res_nonzero); + } } END_TEST - -START_TEST(test_xmr_curve25519_expand_reduce) -{ - static const struct { - char *a; - char *b; - } tests[] = { - { - "dec0adde00000000000000000000000000000000000000000000000000000000", - "dec0adde00000000000000000000000000000000000000000000000000000000" - }, - { - "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", - "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15" - }, - { - "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bcff", - "a8587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc7f" - }, - { - "95587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bcff", - "a8587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bc7f" - }, - }; - - unsigned char buff[32]; - bignum25519 a = {0}; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - curve25519_expand_reduce(a, fromhex(tests[i].a)); - curve25519_contract(buff, a); - ck_assert_mem_eq(buff, fromhex(tests[i].b), 32); - } - +START_TEST(test_xmr_curve25519_expand_reduce) { + static const struct { + char *a; + char *b; + } tests[] = { + {"dec0adde00000000000000000000000000000000000000000000000000000000", + "dec0adde00000000000000000000000000000000000000000000000000000000"}, + {"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", + "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15"}, + {"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bcff", + "a8587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc7f"}, + {"95587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bcff", + "a8587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bc7f"}, + }; + + unsigned char buff[32]; + bignum25519 a = {0}; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + curve25519_expand_reduce(a, fromhex(tests[i].a)); + curve25519_contract(buff, a); + ck_assert_mem_eq(buff, fromhex(tests[i].b), 32); + } } END_TEST - -START_TEST(test_xmr_ge25519_base) -{ - unsigned char buff[32]; - char *base = "5866666666666666666666666666666666666666666666666666666666666666"; - ge25519 b; - ge25519_set_base(&b); - ge25519_pack(buff, &b); - ck_assert_mem_eq(buff, fromhex(base), 32); +START_TEST(test_xmr_ge25519_base) { + unsigned char buff[32]; + char *base = + "5866666666666666666666666666666666666666666666666666666666666666"; + ge25519 b; + ge25519_set_base(&b); + ge25519_pack(buff, &b); + ck_assert_mem_eq(buff, fromhex(base), 32); } END_TEST - -START_TEST(test_xmr_ge25519_check) -{ - static const struct { - char *x; - char *y; - char *z; - char *t; - int r; - } tests[] = { - { - "4ff97748221f954414f836d84e8e7e207786bcd20eb67044756dca307e792c60", - "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", - "0100000000000000000000000000000000000000000000000000000000000000", - "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 1 - }, - { - "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", - "ca48045f790145a1eec3946dfd73747fde0fdb4238607e0a203f8ef5bef90e0e", - "0100000000000000000000000000000000000000000000000000000000000000", - "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 1 - }, - { - "4ff97748221f954414f836d84e8e7e207786bcd20eb6704475ffca307e792c60", - "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", - "0100000000000000000000000000000000000000000000000000000000000000", - "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 0 - }, - { - "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", - "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", - "0100000000000000000000000000000000000000000000000000000000000000", - "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0 - }, - { - "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", - "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", - "0100000000000000000000000000000000000000000000000000000000000000", - "6c5e5ffae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0 - }, - }; - - struct ge25519_t p; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - curve25519_expand_reduce(p.x, fromhex(tests[i].x)); - curve25519_expand_reduce(p.y, fromhex(tests[i].y)); - curve25519_expand_reduce(p.z, fromhex(tests[i].z)); - curve25519_expand_reduce(p.t, fromhex(tests[i].t)); - ck_assert_int_eq(ge25519_check(&p), tests[i].r); - } +START_TEST(test_xmr_ge25519_check) { + static const struct { + char *x; + char *y; + char *z; + char *t; + int r; + } tests[] = { + {"4ff97748221f954414f836d84e8e7e207786bcd20eb67044756dca307e792c60", + "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", + "0100000000000000000000000000000000000000000000000000000000000000", + "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 1}, + {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", + "ca48045f790145a1eec3946dfd73747fde0fdb4238607e0a203f8ef5bef90e0e", + "0100000000000000000000000000000000000000000000000000000000000000", + "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 1}, + {"4ff97748221f954414f836d84e8e7e207786bcd20eb6704475ffca307e792c60", + "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", + "0100000000000000000000000000000000000000000000000000000000000000", + "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 0}, + {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", + "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", + "0100000000000000000000000000000000000000000000000000000000000000", + "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0}, + {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", + "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", + "0100000000000000000000000000000000000000000000000000000000000000", + "6c5e5ffae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0}, + }; + + struct ge25519_t p; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + curve25519_expand_reduce(p.x, fromhex(tests[i].x)); + curve25519_expand_reduce(p.y, fromhex(tests[i].y)); + curve25519_expand_reduce(p.z, fromhex(tests[i].z)); + curve25519_expand_reduce(p.t, fromhex(tests[i].t)); + ck_assert_int_eq(ge25519_check(&p), tests[i].r); + } } END_TEST - -START_TEST(test_xmr_ge25519_scalarmult_base_wrapper) -{ - static const struct { - char *sc; - char *pt; - } tests[] = { - { - "40be740e26bd1c84f5a8fec737c0ed30e87bd45adfcd91e320f8dfb68b1a870e", - "b7a8b2f3dbfd41b38d20aec733a316dbfc2633503799cd36f38570cafc8ea887", - }, - { - "1b3746add992215d427e43a58354c11ff9e6dfa1c187250938f7f9334fa41d05", - "e2a1bfbe38a9749fe6ede79d923b778fa4c89393473d633bec01fa68617d0828", - }, - { - "69af25c54090a9746d3f6043348452429ffd53c1530fa114fd0055b70d61020f", - "6bf1783b0a7495d5f6c36605dca95e723ca120a306c255084787f09b12771124", - }, - { - "0000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - "0100000000000000000000000000000000000000000000000000000000000000", - "5866666666666666666666666666666666666666666666666666666666666666", - }, - { - "0800000000000000000000000000000000000000000000000000000000000000", - "b4b937fca95b2f1e93e41e62fc3c78818ff38a66096fad6e7973e5c90006d321", - }, - { - "ffffffffffffffff000000000000000000000000000000000000000000000000", - "e185757a3fdc6519a6e7bebd97aa52bdc999e4c87d5c3aad0d995763ab6c6985", - }, - }; - - ge25519 pt, pt2; - bignum256modm sc; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(sc, fromhex(tests[i].sc), 32); - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - ge25519_scalarmult_base_wrapper(&pt2, sc); - ck_assert_int_eq(ge25519_eq(&pt, &pt2), 1); - } +START_TEST(test_xmr_ge25519_scalarmult_base_wrapper) { + static const struct { + char *sc; + char *pt; + } tests[] = { + { + "40be740e26bd1c84f5a8fec737c0ed30e87bd45adfcd91e320f8dfb68b1a870e", + "b7a8b2f3dbfd41b38d20aec733a316dbfc2633503799cd36f38570cafc8ea887", + }, + { + "1b3746add992215d427e43a58354c11ff9e6dfa1c187250938f7f9334fa41d05", + "e2a1bfbe38a9749fe6ede79d923b778fa4c89393473d633bec01fa68617d0828", + }, + { + "69af25c54090a9746d3f6043348452429ffd53c1530fa114fd0055b70d61020f", + "6bf1783b0a7495d5f6c36605dca95e723ca120a306c255084787f09b12771124", + }, + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "0100000000000000000000000000000000000000000000000000000000000000", + "5866666666666666666666666666666666666666666666666666666666666666", + }, + { + "0800000000000000000000000000000000000000000000000000000000000000", + "b4b937fca95b2f1e93e41e62fc3c78818ff38a66096fad6e7973e5c90006d321", + }, + { + "ffffffffffffffff000000000000000000000000000000000000000000000000", + "e185757a3fdc6519a6e7bebd97aa52bdc999e4c87d5c3aad0d995763ab6c6985", + }, + }; + + ge25519 pt, pt2; + bignum256modm sc; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(sc, fromhex(tests[i].sc), 32); + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + ge25519_scalarmult_base_wrapper(&pt2, sc); + ck_assert_int_eq(ge25519_eq(&pt, &pt2), 1); + } } END_TEST - -START_TEST(test_xmr_ge25519_scalarmult) -{ - static const struct { - char *sc; - char *pt; - char *pt2; - } tests[] = { - { - "0000000000000000000000000000000000000000000000000000000000000000", - "5cbb3b2784c16f0e7eb4f2a7f93288552bb24ec51c5e01504c1e6885cfbca6d0", - "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - "0100000000000000000000000000000000000000000000000000000000000000", - "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", - "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", - }, - { - "3930000000000000000000000000000000000000000000000000000000000000", - "2835b3983e3cc01a640fd188bf6bbbafbf997a3344d800eed22e4e82a412941c", - "2fe8b2dd0f23e02fca6989e170135584d684583c0a44f6a7d3ebd964685d36c7", - }, - { - "ffffffffffffffff000000000000000000000000000000000000000000000000", - "bb8af7a53a8f1b477c810e833a84cdc789a6b81a6b6417be4f97ffd9ae0fe0b8", - "3a5c9a7dacca9dd8827881f38c36aad7d402a5efc2cab58c7553b903876e1491", - }, - { - "864203a09e1c788a482685c739af07355ebb2c840b7de6af87eff5f19ee3b807", - "d404a9bbf351e7320ea6d11cdeeccaf505f706731cb5e5d839b950edb7ba6286", - "11e09c89e0be7663e0e2d4a01fb05d6a3fd84a78a6fa4fd7daaacf2d19311a38", - }, - { - "3e01f05920a238e33766814d10f0c3a3e975072399ad90a823d4808db1d85209", - "52a2d35798a0ac209b8fa194fe398b869aba5f20d80ee3d8ca77759a8e0bae0d", - "4256addc2f036150f3fdc0a7905f01285239d6dd4eecc4be8e3b134eef4639fe", - }, - { - "ad63d591716a9e89a024a074bc6ce661268d1bb3665f91e8b981f189b1a49507", - "3928bde7a92e1341c3dfee35a66fa5639204f5b9747963278af430145028648d", - "9c959003ba91004956df98800a5024d94031db5ac659675b26350657d93c34f9", - }, - }; - - ge25519 pt, pt2, pt3; - bignum256modm sc; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(sc, fromhex(tests[i].sc), 32); - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - ge25519_unpack_vartime(&pt2, fromhex(tests[i].pt2)); - ge25519_scalarmult(&pt3, &pt, sc); - ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); - } +START_TEST(test_xmr_ge25519_scalarmult) { + static const struct { + char *sc; + char *pt; + char *pt2; + } tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "5cbb3b2784c16f0e7eb4f2a7f93288552bb24ec51c5e01504c1e6885cfbca6d0", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "0100000000000000000000000000000000000000000000000000000000000000", + "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", + "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", + }, + { + "3930000000000000000000000000000000000000000000000000000000000000", + "2835b3983e3cc01a640fd188bf6bbbafbf997a3344d800eed22e4e82a412941c", + "2fe8b2dd0f23e02fca6989e170135584d684583c0a44f6a7d3ebd964685d36c7", + }, + { + "ffffffffffffffff000000000000000000000000000000000000000000000000", + "bb8af7a53a8f1b477c810e833a84cdc789a6b81a6b6417be4f97ffd9ae0fe0b8", + "3a5c9a7dacca9dd8827881f38c36aad7d402a5efc2cab58c7553b903876e1491", + }, + { + "864203a09e1c788a482685c739af07355ebb2c840b7de6af87eff5f19ee3b807", + "d404a9bbf351e7320ea6d11cdeeccaf505f706731cb5e5d839b950edb7ba6286", + "11e09c89e0be7663e0e2d4a01fb05d6a3fd84a78a6fa4fd7daaacf2d19311a38", + }, + { + "3e01f05920a238e33766814d10f0c3a3e975072399ad90a823d4808db1d85209", + "52a2d35798a0ac209b8fa194fe398b869aba5f20d80ee3d8ca77759a8e0bae0d", + "4256addc2f036150f3fdc0a7905f01285239d6dd4eecc4be8e3b134eef4639fe", + }, + { + "ad63d591716a9e89a024a074bc6ce661268d1bb3665f91e8b981f189b1a49507", + "3928bde7a92e1341c3dfee35a66fa5639204f5b9747963278af430145028648d", + "9c959003ba91004956df98800a5024d94031db5ac659675b26350657d93c34f9", + }, + }; + + ge25519 pt, pt2, pt3; + bignum256modm sc; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(sc, fromhex(tests[i].sc), 32); + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + ge25519_unpack_vartime(&pt2, fromhex(tests[i].pt2)); + ge25519_scalarmult(&pt3, &pt, sc); + ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); + } } END_TEST - -START_TEST(test_xmr_ge25519_ops) -{ - int tests[] = {1, 2, 7, 8, 637, 9912, 12345}; - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - struct ge25519_t a, b, c, d; - bignum256modm s1 = {0}, s2 = {0}, s3 = {0}, s4 = {0}; - - set256_modm(s1, tests[i]); - set256_modm(s2, 8 * tests[i]); - set256_modm(s3, 8); - set256_modm(s4, 2); - - ge25519_scalarmult_base_niels(&a, ge25519_niels_base_multiples, s1); - ge25519_scalarmult_base_niels(&b, ge25519_niels_base_multiples, s2); - ge25519_scalarmult(&c, &a, s4); - ge25519_scalarmult(&c, &c, s4); - ge25519_scalarmult(&c, &c, s4); - ck_assert_int_eq(ge25519_eq(&c, &b), 1); - ck_assert_int_eq(ge25519_eq(&a, &b), 0); - - ge25519_scalarmult_base_wrapper(&a, s1); - ge25519_mul8(&b, &a); - ge25519_scalarmult_base_wrapper(&c, s2); - ck_assert_int_eq(ge25519_eq(&b, &c), 1); - - ge25519_scalarmult(&d, &a, s3); - ck_assert_int_eq(ge25519_eq(&d, &c), 1); - - ge25519_copy(&a, &b); - ge25519_neg_full(&b); - ck_assert_int_eq(ge25519_eq(&b, &c), 0); - - ge25519_add(&c, &a, &b, 0); - set256_modm(s2, 0); - ge25519_scalarmult_base_wrapper(&a, s2); - ck_assert_int_eq(ge25519_eq(&a, &c), 1); - } +START_TEST(test_xmr_ge25519_ops) { + int tests[] = {1, 2, 7, 8, 637, 9912, 12345}; + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + struct ge25519_t a, b, c, d; + bignum256modm s1 = {0}, s2 = {0}, s3 = {0}, s4 = {0}; + + set256_modm(s1, tests[i]); + set256_modm(s2, 8 * tests[i]); + set256_modm(s3, 8); + set256_modm(s4, 2); + + ge25519_scalarmult_base_niels(&a, ge25519_niels_base_multiples, s1); + ge25519_scalarmult_base_niels(&b, ge25519_niels_base_multiples, s2); + ge25519_scalarmult(&c, &a, s4); + ge25519_scalarmult(&c, &c, s4); + ge25519_scalarmult(&c, &c, s4); + ck_assert_int_eq(ge25519_eq(&c, &b), 1); + ck_assert_int_eq(ge25519_eq(&a, &b), 0); + + ge25519_scalarmult_base_wrapper(&a, s1); + ge25519_mul8(&b, &a); + ge25519_scalarmult_base_wrapper(&c, s2); + ck_assert_int_eq(ge25519_eq(&b, &c), 1); + + ge25519_scalarmult(&d, &a, s3); + ck_assert_int_eq(ge25519_eq(&d, &c), 1); + + ge25519_copy(&a, &b); + ge25519_neg_full(&b); + ck_assert_int_eq(ge25519_eq(&b, &c), 0); + + ge25519_add(&c, &a, &b, 0); + set256_modm(s2, 0); + ge25519_scalarmult_base_wrapper(&a, s2); + ck_assert_int_eq(ge25519_eq(&a, &c), 1); + } } END_TEST - -START_TEST(test_xmr_check_point) -{ - static const struct { - char *p; - bool on; - } tests[] = { - {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", true}, - {"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5", true}, - {"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808", true}, - {"00000000000000c60073ec000000000000ff0000000000000000000000000080", false}, - {"00000000000000004e0000000000000000000000000000000000000000000000", false}, - {"0000008b0000000000000000b200000000000000000000000000000000000080", false}, - {"a0953eebe2f676256c37af4f6f84f32d397aaf3b73606e96c5ddfcecbb1ceec8", false}, - {"a82cd837efee505ec8425769ea925bee869ec3c78a57708c64c2ef2bd6ad3b88", false}, - {"031c56cfc99758f6f025630e77c6dea0b853c3ab0bf6cf8c8dab03d1a4618178", false}, - }; - - ge25519 tmp; - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - int res = ge25519_unpack_negative_vartime(&tmp, fromhex(tests[i].p)); - ck_assert_int_eq(ge25519_check(&tmp), tests[i].on); - ck_assert_int_eq(res, tests[i].on); - } +START_TEST(test_xmr_check_point) { + static const struct { + char *p; + bool on; + } tests[] = { + {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", + true}, + {"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5", + true}, + {"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808", + true}, + {"00000000000000c60073ec000000000000ff0000000000000000000000000080", + false}, + {"00000000000000004e0000000000000000000000000000000000000000000000", + false}, + {"0000008b0000000000000000b200000000000000000000000000000000000080", + false}, + {"a0953eebe2f676256c37af4f6f84f32d397aaf3b73606e96c5ddfcecbb1ceec8", + false}, + {"a82cd837efee505ec8425769ea925bee869ec3c78a57708c64c2ef2bd6ad3b88", + false}, + {"031c56cfc99758f6f025630e77c6dea0b853c3ab0bf6cf8c8dab03d1a4618178", + false}, + }; + + ge25519 tmp; + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + int res = ge25519_unpack_negative_vartime(&tmp, fromhex(tests[i].p)); + ck_assert_int_eq(ge25519_check(&tmp), tests[i].on); + ck_assert_int_eq(res, tests[i].on); + } } END_TEST - -START_TEST(test_xmr_h) -{ - char *H = "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"; - ge25519 H2, Z; - ge25519_p1p1 P_11; - ge25519_pniels P_ni; - uint8_t buff[32] = {0}; - - ge25519_pack(buff, &xmr_h); - ck_assert_mem_eq(buff, fromhex(H), 32); - - int res = ge25519_unpack_vartime(&H2, buff); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(ge25519_eq(&xmr_h, &xmr_h), 1); - ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); - - res = ge25519_unpack_negative_vartime(&H2, buff); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 0); - ge25519_neg_full(&H2); - ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); - - ge25519_full_to_pniels(&P_ni, &xmr_h); - ge25519_pnielsadd_p1p1(&P_11, &H2, &P_ni, 1); - ge25519_p1p1_to_full(&H2, &P_11); - ge25519_set_neutral(&Z); - ck_assert_int_eq(ge25519_eq(&Z, &H2), 1); +START_TEST(test_xmr_h) { + char *H = "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"; + ge25519 H2, Z; + ge25519_p1p1 P_11; + ge25519_pniels P_ni; + uint8_t buff[32] = {0}; + + ge25519_pack(buff, &xmr_h); + ck_assert_mem_eq(buff, fromhex(H), 32); + + int res = ge25519_unpack_vartime(&H2, buff); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(ge25519_eq(&xmr_h, &xmr_h), 1); + ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); + + res = ge25519_unpack_negative_vartime(&H2, buff); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 0); + ge25519_neg_full(&H2); + ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); + + ge25519_full_to_pniels(&P_ni, &xmr_h); + ge25519_pnielsadd_p1p1(&P_11, &H2, &P_ni, 1); + ge25519_p1p1_to_full(&H2, &P_11); + ge25519_set_neutral(&Z); + ck_assert_int_eq(ge25519_eq(&Z, &H2), 1); } END_TEST - -START_TEST(test_xmr_fast_hash) -{ - uint8_t hash[32]; - char tests[][2][65] = { - {"", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"}, - {"00", "bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"}, - {"000102", "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, - {"000102030405", "51e8babe8b42352100dffa7f7b3843c95245d3d545c6cbf5052e80258ae80627"}, - {"000102030406", "74e7a0111ee2390dc68269a549a76dcfb553ca1260035eae982d669ff6494f32"}, - {"000102030407", "3a81c5d02a87786343f88414aae150a09f6933b1d3bb660d0a9ac54e12e5cd86"}, - {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", "7fb4d1c8e32f7414fe8c7b2774ec05bff6845e4278565d17f95559513a244da2"}, - {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "2998fe52f8b9883149babd9c546912c3edfbd3cd98896a0e57b1b5929fa5ff7b"}, - }; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - xmr_fast_hash(hash, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); - ck_assert_mem_eq(hash, fromhex(tests[i][1]), 32); - } +START_TEST(test_xmr_fast_hash) { + uint8_t hash[32]; + char tests[][2][65] = { + {"", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"}, + {"00", + "bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"}, + {"000102", + "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, + {"000102030405", + "51e8babe8b42352100dffa7f7b3843c95245d3d545c6cbf5052e80258ae80627"}, + {"000102030406", + "74e7a0111ee2390dc68269a549a76dcfb553ca1260035eae982d669ff6494f32"}, + {"000102030407", + "3a81c5d02a87786343f88414aae150a09f6933b1d3bb660d0a9ac54e12e5cd86"}, + {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", + "7fb4d1c8e32f7414fe8c7b2774ec05bff6845e4278565d17f95559513a244da2"}, + {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", + "2998fe52f8b9883149babd9c546912c3edfbd3cd98896a0e57b1b5929fa5ff7b"}, + }; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + xmr_fast_hash(hash, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); + ck_assert_mem_eq(hash, fromhex(tests[i][1]), 32); + } } END_TEST - -START_TEST(test_xmr_hasher) -{ - Hasher hasher; - uint8_t hash[32]; - - static const struct { - char * chunk[3]; - char * hash; - } tests[] = { - { {"00", "01", "02"}, - "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, - { {"001122334455667788", "00", ""}, - "72a228ee8d0d01c815f112ce315cfc215a0594abcec24162304ae0ffda139d9e"}, - { {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", "", "00112233445566"}, - "c3deafd96ff10cc190c6024548c344f6401cfe5151ab2fcd40df7cc501147e01"}, - }; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - xmr_hasher_init(&hasher); - for(int j = 0; j < 3; j++){ - xmr_hasher_update(&hasher, fromhex(tests[i].chunk[j]), strlen(tests[i].chunk[j]) / 2); - } - xmr_hasher_final(&hasher, hash); - ck_assert_mem_eq(hash, fromhex(tests[i].hash), 32); - } +START_TEST(test_xmr_hasher) { + Hasher hasher; + uint8_t hash[32]; + + static const struct { + char *chunk[3]; + char *hash; + } tests[] = { + {{"00", "01", "02"}, + "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, + {{"001122334455667788", "00", ""}, + "72a228ee8d0d01c815f112ce315cfc215a0594abcec24162304ae0ffda139d9e"}, + {{"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", "", + "00112233445566"}, + "c3deafd96ff10cc190c6024548c344f6401cfe5151ab2fcd40df7cc501147e01"}, + }; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + xmr_hasher_init(&hasher); + for (int j = 0; j < 3; j++) { + xmr_hasher_update(&hasher, fromhex(tests[i].chunk[j]), + strlen(tests[i].chunk[j]) / 2); + } + xmr_hasher_final(&hasher, hash); + ck_assert_mem_eq(hash, fromhex(tests[i].hash), 32); + } } END_TEST - -START_TEST(test_xmr_hash_to_scalar) -{ - bignum256modm a1; - unsigned char out[32]; - char tests[][2][65] = { - {"", "4a078e76cd41a3d3b534b83dc6f2ea2de500b653ca82273b7bfad8045d85a400"}, - {"00", "5497c9b6a7059553835f85118dc089d66512f7b477d66591ff96a9e064bcc90a"}, - {"000102", "5727ca206dbafa2e099b022ed528f5bdf7874e3ec09c8f012159dfeeaab2b106"}, - {"000102030405", "7740cf04577c107153a50b3abe44859f5245d3d545c6cbf5052e80258ae80607"}, - {"000102030406", "ad6bbffaceb8020543ac82bcadb9d090b553ca1260035eae982d669ff6494f02"}, - {"000102030407", "d2e116e9576ee5a29011c8fcb41259f99e6933b1d3bb660d0a9ac54e12e5cd06"}, - {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", "3d6d3727dc50bca39e6ccfc9c12950eef5845e4278565d17f95559513a244d02"}, - {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "aecc45c83f0408c96c70f8273e94f930edfbd3cd98896a0e57b1b5929fa5ff0b"}, - }; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - xmr_hash_to_scalar(a1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); - contract256_modm(out, a1); - ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); - } +START_TEST(test_xmr_hash_to_scalar) { + bignum256modm a1; + unsigned char out[32]; + char tests[][2][65] = { + {"", "4a078e76cd41a3d3b534b83dc6f2ea2de500b653ca82273b7bfad8045d85a400"}, + {"00", + "5497c9b6a7059553835f85118dc089d66512f7b477d66591ff96a9e064bcc90a"}, + {"000102", + "5727ca206dbafa2e099b022ed528f5bdf7874e3ec09c8f012159dfeeaab2b106"}, + {"000102030405", + "7740cf04577c107153a50b3abe44859f5245d3d545c6cbf5052e80258ae80607"}, + {"000102030406", + "ad6bbffaceb8020543ac82bcadb9d090b553ca1260035eae982d669ff6494f02"}, + {"000102030407", + "d2e116e9576ee5a29011c8fcb41259f99e6933b1d3bb660d0a9ac54e12e5cd06"}, + {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", + "3d6d3727dc50bca39e6ccfc9c12950eef5845e4278565d17f95559513a244d02"}, + {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", + "aecc45c83f0408c96c70f8273e94f930edfbd3cd98896a0e57b1b5929fa5ff0b"}, + }; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + xmr_hash_to_scalar(a1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); + contract256_modm(out, a1); + ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); + } } END_TEST - -START_TEST(test_xmr_hash_to_ec) -{ - ge25519 p1; - unsigned char out[32]; - char tests[][2][65] = { - {"", "d6d7d783ab18e1be65586adb7902a4175b737ef0b902875e1d1d5c5cf0478c0b"}, - {"00", "8e2fecb36320bc4e192e10ef54afc7c83fbeb0c38b7debd4fea51301f0bd4f3d"}, - {"000102", "73b233e2e75d81b9657a857e38e7ab2bc3600e5c56622b9fe4b976ff312220fa"}, - {"000102030405", "bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808"}, - {"000102030406", "525567a6a40a94f2d916bc1efea234bbd3b9162403ec2faba871a90f8d0d487e"}, - {"000102030407", "99b1be2a92cbd22b24b48fb7a9daadd4d13a56915c4f6ed696f271ad5bdbc149"}, - {"42f6835bf83114a1f5f6076fe79bdfa0bd67c74b88f127d54572d3910dd09201", "54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5"}, - {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608"}, - }; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - xmr_hash_to_ec(&p1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); - ge25519_pack(out, &p1); - ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); - } +START_TEST(test_xmr_hash_to_ec) { + ge25519 p1; + unsigned char out[32]; + char tests[][2][65] = { + {"", "d6d7d783ab18e1be65586adb7902a4175b737ef0b902875e1d1d5c5cf0478c0b"}, + {"00", + "8e2fecb36320bc4e192e10ef54afc7c83fbeb0c38b7debd4fea51301f0bd4f3d"}, + {"000102", + "73b233e2e75d81b9657a857e38e7ab2bc3600e5c56622b9fe4b976ff312220fa"}, + {"000102030405", + "bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808"}, + {"000102030406", + "525567a6a40a94f2d916bc1efea234bbd3b9162403ec2faba871a90f8d0d487e"}, + {"000102030407", + "99b1be2a92cbd22b24b48fb7a9daadd4d13a56915c4f6ed696f271ad5bdbc149"}, + {"42f6835bf83114a1f5f6076fe79bdfa0bd67c74b88f127d54572d3910dd09201", + "54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5"}, + {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", + "001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608"}, + }; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + xmr_hash_to_ec(&p1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); + ge25519_pack(out, &p1); + ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); + } } END_TEST - -START_TEST(test_xmr_derivation_to_scalar) -{ - static const struct { - char *pt; - uint32_t idx; - char *sc; - } tests[] = { - { - "c655b2d9d2670a1c9f26f7586b6d6b1ec5173b8b33bca64c3d305a42d66738b1", 0, - "ca7ce31b273dd1ac00dc3553e654fb66036804800e27c826bd2b78649243900b", - }, - { - "2b1dbd7a007dcc4d729fa8359705595599737fcef60afb36b379fe033095dca7", 1, - "60afd5a63b14845d3b92d16eac386713e4ff617fdc5c1a07c3212098c1f5610c", - }, - { - "a48ed3797225dab4b4316b5e40107b6bd63e5f4dc517ba602774d703576ec771", 24, - "fe81804091e50a5c2233faa6277360fbe1948ea15dddbae62c1d40bbd1918606", - }, - { - "fa27b5b39741f5341b4e89269e3a05ff7e76ec7739843872468fc4bec8475410", 65537, - "1ba36841f57aa8b799c4dd02b39d53e5fb7780d3f09f91a57a86dcb418d8d506", - }, - }; - - ge25519 pt; - bignum256modm sc, sc2; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(sc, fromhex(tests[i].sc), 32); - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - - xmr_derivation_to_scalar(sc2, &pt, tests[i].idx); - ck_assert_int_eq(eq256_modm(sc, sc2), 1); - - xmr_derivation_to_scalar(sc2, &pt, tests[i].idx + 1); - ck_assert_int_eq(eq256_modm(sc, sc2), 0); - } +START_TEST(test_xmr_derivation_to_scalar) { + static const struct { + char *pt; + uint32_t idx; + char *sc; + } tests[] = { + { + "c655b2d9d2670a1c9f26f7586b6d6b1ec5173b8b33bca64c3d305a42d66738b1", + 0, + "ca7ce31b273dd1ac00dc3553e654fb66036804800e27c826bd2b78649243900b", + }, + { + "2b1dbd7a007dcc4d729fa8359705595599737fcef60afb36b379fe033095dca7", + 1, + "60afd5a63b14845d3b92d16eac386713e4ff617fdc5c1a07c3212098c1f5610c", + }, + { + "a48ed3797225dab4b4316b5e40107b6bd63e5f4dc517ba602774d703576ec771", + 24, + "fe81804091e50a5c2233faa6277360fbe1948ea15dddbae62c1d40bbd1918606", + }, + { + "fa27b5b39741f5341b4e89269e3a05ff7e76ec7739843872468fc4bec8475410", + 65537, + "1ba36841f57aa8b799c4dd02b39d53e5fb7780d3f09f91a57a86dcb418d8d506", + }, + }; + + ge25519 pt; + bignum256modm sc, sc2; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(sc, fromhex(tests[i].sc), 32); + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + + xmr_derivation_to_scalar(sc2, &pt, tests[i].idx); + ck_assert_int_eq(eq256_modm(sc, sc2), 1); + + xmr_derivation_to_scalar(sc2, &pt, tests[i].idx + 1); + ck_assert_int_eq(eq256_modm(sc, sc2), 0); + } } END_TEST - -START_TEST(test_xmr_generate_key_derivation) -{ - static const struct { - char *pt; - char *sc; - char *r; - } tests[] = { - { - "38f94f27c8037aff025e365275ed1029fd636dda5f69e5f98fdcf92e0a28f31a", - "8f1c73ee5327a43264a7b60b9e7882312b582f33e89846a8694dbf094bb3a90a", - "1fbfe4dcc8c824c274649545f297fa320cd4c1689b1d0ff4887567c4d4a75649", - }, - { - "26785c3941a32f194228eb659c5ee305e63868896defc50ee6c4e0e92d1e246a", - "dbbffec4686ba8ab25e2f1b04c0e7ae51c5143c91353bfb5998430ebe365a609", - "cca34db8dd682ec164d8973b555253934596b77849ef7709d9321121c25aba02", - }, - { - "43505a8ce7248f70d3aae4f57fb59c254ce2b2a0cc2bcf50f2344e51d59b36b3", - "19a802e35f6ff94efe96ec016effe04e635bbd9c1ce2612d5ba2ee4659456b06", - "fc6c93a93f77ff89c18b9abf95b28ec8591ab97eee8e4afee93aa766a4bd3934", - }, - }; - - ge25519 pt, pt2, pt3; - bignum256modm sc; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(sc, fromhex(tests[i].sc), 32); - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - ge25519_unpack_vartime(&pt2, fromhex(tests[i].r)); - xmr_generate_key_derivation(&pt3, &pt, sc); - ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); - ck_assert_int_eq(ge25519_eq(&pt3, &pt), 0); - } +START_TEST(test_xmr_generate_key_derivation) { + static const struct { + char *pt; + char *sc; + char *r; + } tests[] = { + { + "38f94f27c8037aff025e365275ed1029fd636dda5f69e5f98fdcf92e0a28f31a", + "8f1c73ee5327a43264a7b60b9e7882312b582f33e89846a8694dbf094bb3a90a", + "1fbfe4dcc8c824c274649545f297fa320cd4c1689b1d0ff4887567c4d4a75649", + }, + { + "26785c3941a32f194228eb659c5ee305e63868896defc50ee6c4e0e92d1e246a", + "dbbffec4686ba8ab25e2f1b04c0e7ae51c5143c91353bfb5998430ebe365a609", + "cca34db8dd682ec164d8973b555253934596b77849ef7709d9321121c25aba02", + }, + { + "43505a8ce7248f70d3aae4f57fb59c254ce2b2a0cc2bcf50f2344e51d59b36b3", + "19a802e35f6ff94efe96ec016effe04e635bbd9c1ce2612d5ba2ee4659456b06", + "fc6c93a93f77ff89c18b9abf95b28ec8591ab97eee8e4afee93aa766a4bd3934", + }, + }; + + ge25519 pt, pt2, pt3; + bignum256modm sc; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(sc, fromhex(tests[i].sc), 32); + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + ge25519_unpack_vartime(&pt2, fromhex(tests[i].r)); + xmr_generate_key_derivation(&pt3, &pt, sc); + ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); + ck_assert_int_eq(ge25519_eq(&pt3, &pt), 0); + } } END_TEST - -START_TEST(test_xmr_derive_private_key) -{ - static const struct { - char *pt; - uint32_t idx; - char *base; - char *r; - } tests[] = { - { - "0541d8f069e5e80a892e39bbf1944ef578008cf9ecf1d100760a05858c1b709e", 0, - "76967eeb0a3d181bb0b384be71c680a4287599f27b2ddbd07f8e06ab6f2c880e", - "45728c5cb658e470790f124a01699d2126832b7e5c6b7760b6f11119b96ad603", - }, - { - "fc6e0bd785a84e62c9ac8a97e0e604a79494bc2cf7b3b38ef8af7791c87b5bb8", 1, - "32fbe149562b7ccb34bc4105b87b2a834024799336c8eea5e94df77f1ae9a807", - "64508e83bbadf63f8ecfae4d9dcdd39a4ba23508a545e1a37026f0fa2539d601", - }, - { - "f6bd7a72dc9444dc7e09a0eb4d312d36fe173693d6405b132a5b090297a04ea9", 65537, - "333a8fcce6726457e4222a87b9b475c1fcf985f756c2029fcb39184c0a5c4804", - "37c16a22da4c0082ebf4bf807403b169f75142a9bd8560ed45f3f9347218260e", - }, - }; - - ge25519 pt; - bignum256modm base, res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(base, fromhex(tests[i].base), 32); - expand256_modm(res_exp, fromhex(tests[i].r), 32); - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - - xmr_derive_private_key(res, &pt, tests[i].idx, base); - ck_assert_int_eq(eq256_modm(res, res_exp), 1); - ck_assert_int_eq(eq256_modm(res, base), 0); - } +START_TEST(test_xmr_derive_private_key) { + static const struct { + char *pt; + uint32_t idx; + char *base; + char *r; + } tests[] = { + { + "0541d8f069e5e80a892e39bbf1944ef578008cf9ecf1d100760a05858c1b709e", + 0, + "76967eeb0a3d181bb0b384be71c680a4287599f27b2ddbd07f8e06ab6f2c880e", + "45728c5cb658e470790f124a01699d2126832b7e5c6b7760b6f11119b96ad603", + }, + { + "fc6e0bd785a84e62c9ac8a97e0e604a79494bc2cf7b3b38ef8af7791c87b5bb8", + 1, + "32fbe149562b7ccb34bc4105b87b2a834024799336c8eea5e94df77f1ae9a807", + "64508e83bbadf63f8ecfae4d9dcdd39a4ba23508a545e1a37026f0fa2539d601", + }, + { + "f6bd7a72dc9444dc7e09a0eb4d312d36fe173693d6405b132a5b090297a04ea9", + 65537, + "333a8fcce6726457e4222a87b9b475c1fcf985f756c2029fcb39184c0a5c4804", + "37c16a22da4c0082ebf4bf807403b169f75142a9bd8560ed45f3f9347218260e", + }, + }; + + ge25519 pt; + bignum256modm base, res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(base, fromhex(tests[i].base), 32); + expand256_modm(res_exp, fromhex(tests[i].r), 32); + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + + xmr_derive_private_key(res, &pt, tests[i].idx, base); + ck_assert_int_eq(eq256_modm(res, res_exp), 1); + ck_assert_int_eq(eq256_modm(res, base), 0); + } } END_TEST - -START_TEST(test_xmr_derive_public_key) -{ - static const struct { - char *pt; - uint32_t idx; - char *base; - char *r; - } tests[] = { - { - "653f03e7766d472826aa49793bc0cfde698e6745ae5e4217980ba307739f2ed9", 0, - "2a393f0858732970ac8dea003b17e1ce9371f0a045bd9b7af0d998262739f4cc", - "f7a3db27c45f265f6a68a30137ca44289a6cf1a6db2cf482c59ebfb0142ad419", - }, - { - "338e93f61e6470a5cc71c07b8caedd1a9a28da037aab65c1ca5538501b012c81", 1, - "af3a1d39397d778731c4510110fd117dc02f756e390713d58f94a06203ce39eb", - "779e2a043c881f06aba1952741fd753098615c4fafa8f62748467ab9bac43241", - }, - { - "7735e9476440927b89b18d7a1e0645b218a1a6d28c642aebb16c1dba0926d5e4", 65537, - "62c3eed062bd602f7f2164c69ad0b5a8eb3ea560c930f6b41abfc1c4839ea432", - "6da4ebd29498d16c4e813abb3e328c83f9b01a7ba1da6e818071f8ec563626c8", - }, - }; - - ge25519 pt, base, res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); - ge25519_unpack_vartime(&base, fromhex(tests[i].base)); - ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); - - xmr_derive_public_key(&res, &pt, tests[i].idx, &base); - - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - ck_assert_int_eq(ge25519_eq(&res, &base), 0); - } +START_TEST(test_xmr_derive_public_key) { + static const struct { + char *pt; + uint32_t idx; + char *base; + char *r; + } tests[] = { + { + "653f03e7766d472826aa49793bc0cfde698e6745ae5e4217980ba307739f2ed9", + 0, + "2a393f0858732970ac8dea003b17e1ce9371f0a045bd9b7af0d998262739f4cc", + "f7a3db27c45f265f6a68a30137ca44289a6cf1a6db2cf482c59ebfb0142ad419", + }, + { + "338e93f61e6470a5cc71c07b8caedd1a9a28da037aab65c1ca5538501b012c81", + 1, + "af3a1d39397d778731c4510110fd117dc02f756e390713d58f94a06203ce39eb", + "779e2a043c881f06aba1952741fd753098615c4fafa8f62748467ab9bac43241", + }, + { + "7735e9476440927b89b18d7a1e0645b218a1a6d28c642aebb16c1dba0926d5e4", + 65537, + "62c3eed062bd602f7f2164c69ad0b5a8eb3ea560c930f6b41abfc1c4839ea432", + "6da4ebd29498d16c4e813abb3e328c83f9b01a7ba1da6e818071f8ec563626c8", + }, + }; + + ge25519 pt, base, res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); + ge25519_unpack_vartime(&base, fromhex(tests[i].base)); + ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); + + xmr_derive_public_key(&res, &pt, tests[i].idx, &base); + + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + ck_assert_int_eq(ge25519_eq(&res, &base), 0); + } } END_TEST - -START_TEST(test_xmr_add_keys2) -{ - static const struct { - char *a; - char *b; - char *B; - char *r; - } tests[] = { - { - "631238da9578d7cb8db16fc4322671bfcb251cc5228b060664800ec1895be608", - "f9a73fca0be058415a148f9e2871be59e1fc7ae6f6193199125237e0d7c1630f", - "ef5ca4fc90f330e825adcdc953da0b3becd853aa819219842790bb39775f2255", - "06623fd0e7a3d787a4d224f6ca2fdab2dcd9d1221578515974b9c4dee65fdcf5", - }, - { - "dac2e629e5c75c312253b19d1d3a0a423158fdd9cdcf4c7a7bf2717d0b748602", - "0483d98d750d4977b499cefd558a0a61580823a37da2b011501e24718e6c7f0a", - "51fd3cd2f1a603ec7be3b35da9c105d91c4304e6a63facf48d7730712cedc0ee", - "f7a5d645ba01a5b7ccbe9636d14422bb587fc529317b23761f0e39222b783b87", - }, - { - "817c4d2fd3e841d860bdab6b7ccf098f3e637eca468d0a3825c50b71f61d0e0c", - "1f6c4795d7fb0d53b5775874ac4c0963607d2b7bd11a7c5d10735badc4a27207", - "bef0e0ed09d602bbe1dd38358b5f8fca27fcad60a69440f104441c3fc68df9c7", - "bc0fc824d74eca0e10eacd0bc2f3322e0bcb02a44ce53f2f5f1fc472f99be8d2", - }, - }; - - bignum256modm a, b; - ge25519 B, res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i].a), 32); - expand256_modm(b, fromhex(tests[i].b), 32); - ge25519_unpack_vartime(&B, fromhex(tests[i].B)); - ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); - - xmr_add_keys2(&res, a, b, &B); - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - ck_assert_int_eq(ge25519_eq(&res, &B), 0); - - xmr_add_keys2_vartime(&res, a, b, &B); - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - ck_assert_int_eq(ge25519_eq(&res, &B), 0); - } +START_TEST(test_xmr_add_keys2) { + static const struct { + char *a; + char *b; + char *B; + char *r; + } tests[] = { + { + "631238da9578d7cb8db16fc4322671bfcb251cc5228b060664800ec1895be608", + "f9a73fca0be058415a148f9e2871be59e1fc7ae6f6193199125237e0d7c1630f", + "ef5ca4fc90f330e825adcdc953da0b3becd853aa819219842790bb39775f2255", + "06623fd0e7a3d787a4d224f6ca2fdab2dcd9d1221578515974b9c4dee65fdcf5", + }, + { + "dac2e629e5c75c312253b19d1d3a0a423158fdd9cdcf4c7a7bf2717d0b748602", + "0483d98d750d4977b499cefd558a0a61580823a37da2b011501e24718e6c7f0a", + "51fd3cd2f1a603ec7be3b35da9c105d91c4304e6a63facf48d7730712cedc0ee", + "f7a5d645ba01a5b7ccbe9636d14422bb587fc529317b23761f0e39222b783b87", + }, + { + "817c4d2fd3e841d860bdab6b7ccf098f3e637eca468d0a3825c50b71f61d0e0c", + "1f6c4795d7fb0d53b5775874ac4c0963607d2b7bd11a7c5d10735badc4a27207", + "bef0e0ed09d602bbe1dd38358b5f8fca27fcad60a69440f104441c3fc68df9c7", + "bc0fc824d74eca0e10eacd0bc2f3322e0bcb02a44ce53f2f5f1fc472f99be8d2", + }, + }; + + bignum256modm a, b; + ge25519 B, res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i].a), 32); + expand256_modm(b, fromhex(tests[i].b), 32); + ge25519_unpack_vartime(&B, fromhex(tests[i].B)); + ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); + + xmr_add_keys2(&res, a, b, &B); + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + ck_assert_int_eq(ge25519_eq(&res, &B), 0); + + xmr_add_keys2_vartime(&res, a, b, &B); + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + ck_assert_int_eq(ge25519_eq(&res, &B), 0); + } } END_TEST - -START_TEST(test_xmr_add_keys3) -{ - static const struct { - char *a; - char *A; - char *b; - char *B; - char *r; - } tests[] = { - { - "7048b8c4603ae194c502fa458b0e11a4c7a330852bbef66b7c1d67e9f919f509", - "9167c5b182758699baeb421e7f1200272fc775e4c7c7c183cc47261dccbb569f", - "c2cb2bc0249fc7be8eb9b3bed7d37aa6f2c3f433abb3a4a00b13bed64b61f30b", - "b3ec53b07a1be70ac8d0fa365b86f0d6d4cbf98641e7704b3d684558e2ea59ef", - "4dc016d702d599bde5eaeb2bf0c2d0d3f6b9cede961bc539bcb369c3b3086358", - }, - { - "e9794a6652940474958936f07f3904d514228553247633cfb7ae8ffa9fa0f406", - "0e51cea6df2f6f56a9935689364f0d295a7c89f51d40efb2518c17d1b9db792b", - "c132e7be08afdd93984c52c6e1c596edc6b8fc8f1faed95f55e2f819ee806706", - "1a0e03c6858f6cf1b43f4b8456c03144af553bbbd050e152834fd1615b577cb3", - "088f19c6727f8704373d391a36c230395d386f69edb4151ecf8afcd27793fff5", - }, - { - "88920b0c96b15cc04e879f53a76f85f3c7a2a5f275b2772b5b74ee83372aea00", - "e95731ab61a98fedcded475cf21b4ecf2ef9f1adecefba8fdc476a5bb1cf60f9", - "c86026b66c1045fb69e4f24ff6c15d4fad4d565e646938a2ffb7db37ccb4100d", - "d80cbf2986c12e4c7ebac1e55abbdfc4212c00aec8bc90c965becf863262a074", - "047cebaeb3ec2132e7386ba52531b04070206ba1106565c0fbd7d7280694568a", - }, - }; - - bignum256modm a, b; - ge25519 A, B, res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i].a), 32); - expand256_modm(b, fromhex(tests[i].b), 32); - ge25519_unpack_vartime(&A, fromhex(tests[i].A)); - ge25519_unpack_vartime(&B, fromhex(tests[i].B)); - ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); - - xmr_add_keys3(&res, a, &A, b, &B); - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - ck_assert_int_eq(ge25519_eq(&res, &B), 0); - - xmr_add_keys3_vartime(&res, a, &A, b, &B); - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - ck_assert_int_eq(ge25519_eq(&res, &B), 0); - } +START_TEST(test_xmr_add_keys3) { + static const struct { + char *a; + char *A; + char *b; + char *B; + char *r; + } tests[] = { + { + "7048b8c4603ae194c502fa458b0e11a4c7a330852bbef66b7c1d67e9f919f509", + "9167c5b182758699baeb421e7f1200272fc775e4c7c7c183cc47261dccbb569f", + "c2cb2bc0249fc7be8eb9b3bed7d37aa6f2c3f433abb3a4a00b13bed64b61f30b", + "b3ec53b07a1be70ac8d0fa365b86f0d6d4cbf98641e7704b3d684558e2ea59ef", + "4dc016d702d599bde5eaeb2bf0c2d0d3f6b9cede961bc539bcb369c3b3086358", + }, + { + "e9794a6652940474958936f07f3904d514228553247633cfb7ae8ffa9fa0f406", + "0e51cea6df2f6f56a9935689364f0d295a7c89f51d40efb2518c17d1b9db792b", + "c132e7be08afdd93984c52c6e1c596edc6b8fc8f1faed95f55e2f819ee806706", + "1a0e03c6858f6cf1b43f4b8456c03144af553bbbd050e152834fd1615b577cb3", + "088f19c6727f8704373d391a36c230395d386f69edb4151ecf8afcd27793fff5", + }, + { + "88920b0c96b15cc04e879f53a76f85f3c7a2a5f275b2772b5b74ee83372aea00", + "e95731ab61a98fedcded475cf21b4ecf2ef9f1adecefba8fdc476a5bb1cf60f9", + "c86026b66c1045fb69e4f24ff6c15d4fad4d565e646938a2ffb7db37ccb4100d", + "d80cbf2986c12e4c7ebac1e55abbdfc4212c00aec8bc90c965becf863262a074", + "047cebaeb3ec2132e7386ba52531b04070206ba1106565c0fbd7d7280694568a", + }, + }; + + bignum256modm a, b; + ge25519 A, B, res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i].a), 32); + expand256_modm(b, fromhex(tests[i].b), 32); + ge25519_unpack_vartime(&A, fromhex(tests[i].A)); + ge25519_unpack_vartime(&B, fromhex(tests[i].B)); + ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); + + xmr_add_keys3(&res, a, &A, b, &B); + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + ck_assert_int_eq(ge25519_eq(&res, &B), 0); + + xmr_add_keys3_vartime(&res, a, &A, b, &B); + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + ck_assert_int_eq(ge25519_eq(&res, &B), 0); + } } END_TEST - -START_TEST(test_xmr_get_subaddress_secret_key) -{ - static const struct { - uint32_t major, minor; - char *m; - char *r; - } tests[] = { - { - 0, 0, - "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", - "8a510a9fe1824b49abbae05958084f9c9098775f29e15427309177882471cf01", - }, - { - 0, 1, - "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", - "2bbc9366c04abb0523e2b2d6e709670ffe6645bacedfee968d9c6bc8eefe9c0f", - }, - { - 100, 100, - "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", - "c3837d41fedeaed126cf4fc1a5ea47b8b7f38f6a64aa534e3dd45a3c93f37600", - }, - }; - - bignum256modm m, res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(m, fromhex(tests[i].m), 32); - expand256_modm(res_exp, fromhex(tests[i].r), 32); - xmr_get_subaddress_secret_key(res, tests[i].major, tests[i].minor, m); - - ck_assert_int_eq(eq256_modm(res, res_exp), 1); - ck_assert_int_eq(eq256_modm(res, m), 0); - } +START_TEST(test_xmr_get_subaddress_secret_key) { + static const struct { + uint32_t major, minor; + char *m; + char *r; + } tests[] = { + { + 0, + 0, + "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", + "8a510a9fe1824b49abbae05958084f9c9098775f29e15427309177882471cf01", + }, + { + 0, + 1, + "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", + "2bbc9366c04abb0523e2b2d6e709670ffe6645bacedfee968d9c6bc8eefe9c0f", + }, + { + 100, + 100, + "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", + "c3837d41fedeaed126cf4fc1a5ea47b8b7f38f6a64aa534e3dd45a3c93f37600", + }, + }; + + bignum256modm m, res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(m, fromhex(tests[i].m), 32); + expand256_modm(res_exp, fromhex(tests[i].r), 32); + xmr_get_subaddress_secret_key(res, tests[i].major, tests[i].minor, m); + + ck_assert_int_eq(eq256_modm(res, res_exp), 1); + ck_assert_int_eq(eq256_modm(res, m), 0); + } } END_TEST - -START_TEST(test_xmr_gen_c) -{ - static const struct { - char *a; - uint64_t amount; - char *r; - } tests[] = { - { - "e3e6558c291bbb98aa691d068b67d59dc520afb23fdd51bf65283626fc2ad903", 0, - "ef19d73bdf3749240b80ee7695f53ad7c2fc2cf868a93209799f41212d099750", - }, - { - "6788c9579c377f3228680bd0e6d01b1ee0c763b35ed39d36fa2146cc2ee16e0e", 1, - "4913b9af4f2725d87a4404c22cf366597d1c1e6a1f510ae14081d8b7c5a9de77", - }, - { - "ad9e89d67012935540427c241756d6a9d260c5e134603c41d31e24f8651bef08", 65537, - "f005721da08f24e68314abed3ddfd94165e4be3813398fb126e3f366820b9c90", - }, - { - "fdbb70ff07be24d98de3bffa0a33756646497224318fb7fe136f0e7789d12607", 0xffffffffffffffffULL, - "a9c38927f299c5f14c98a1a9c9981e59c606ff597274b9b709e1356f12e1498c", - }, - }; - - bignum256modm a; - ge25519 res, res_exp; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - expand256_modm(a, fromhex(tests[i].a), 32); - ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); - xmr_gen_c(&res, a, tests[i].amount); - - ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); - } +START_TEST(test_xmr_gen_c) { + static const struct { + char *a; + uint64_t amount; + char *r; + } tests[] = { + { + "e3e6558c291bbb98aa691d068b67d59dc520afb23fdd51bf65283626fc2ad903", + 0, + "ef19d73bdf3749240b80ee7695f53ad7c2fc2cf868a93209799f41212d099750", + }, + { + "6788c9579c377f3228680bd0e6d01b1ee0c763b35ed39d36fa2146cc2ee16e0e", + 1, + "4913b9af4f2725d87a4404c22cf366597d1c1e6a1f510ae14081d8b7c5a9de77", + }, + { + "ad9e89d67012935540427c241756d6a9d260c5e134603c41d31e24f8651bef08", + 65537, + "f005721da08f24e68314abed3ddfd94165e4be3813398fb126e3f366820b9c90", + }, + { + "fdbb70ff07be24d98de3bffa0a33756646497224318fb7fe136f0e7789d12607", + 0xffffffffffffffffULL, + "a9c38927f299c5f14c98a1a9c9981e59c606ff597274b9b709e1356f12e1498c", + }, + }; + + bignum256modm a; + ge25519 res, res_exp; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + expand256_modm(a, fromhex(tests[i].a), 32); + ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); + xmr_gen_c(&res, a, tests[i].amount); + + ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); + } } END_TEST - -START_TEST(test_xmr_varint) -{ - static const struct { - uint64_t x; - char *r; - } tests[] = { - { - 0, - "00", - }, - { - 24, - "18", - }, - { - 65535, - "ffff03", - }, - { - 65537, - "818004", - }, - { - 0x7fffffffULL, - "ffffffff07", - }, - { - 0xffffffffULL, - "ffffffff0f", - }, - { - 0xffffffffffffffffULL, - "ffffffffffffffffff01", - }, - { - 0xdeadc0deULL, - "de81b7f50d", - }, - }; - - uint64_t val; - unsigned char buff[64]; - - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - int s1 = xmr_size_varint(tests[i].x); - int written = 0; - int read = 0; - - ck_assert_int_eq(s1, strlen(tests[i].r)/2); - written = xmr_write_varint(buff, sizeof(buff), tests[i].x); - ck_assert_int_eq(s1, written); - ck_assert_mem_eq(buff, fromhex(tests[i].r), strlen(tests[i].r)/2); - - read = xmr_read_varint(buff, sizeof(buff), &val); - ck_assert_int_eq(read, written); - ck_assert(tests[i].x == val); - } +START_TEST(test_xmr_varint) { + static const struct { + uint64_t x; + char *r; + } tests[] = { + { + 0, + "00", + }, + { + 24, + "18", + }, + { + 65535, + "ffff03", + }, + { + 65537, + "818004", + }, + { + 0x7fffffffULL, + "ffffffff07", + }, + { + 0xffffffffULL, + "ffffffff0f", + }, + { + 0xffffffffffffffffULL, + "ffffffffffffffffff01", + }, + { + 0xdeadc0deULL, + "de81b7f50d", + }, + }; + + uint64_t val; + unsigned char buff[64]; + + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + int s1 = xmr_size_varint(tests[i].x); + int written = 0; + int read = 0; + + ck_assert_int_eq(s1, strlen(tests[i].r) / 2); + written = xmr_write_varint(buff, sizeof(buff), tests[i].x); + ck_assert_int_eq(s1, written); + ck_assert_mem_eq(buff, fromhex(tests[i].r), strlen(tests[i].r) / 2); + + read = xmr_read_varint(buff, sizeof(buff), &val); + ck_assert_int_eq(read, written); + ck_assert(tests[i].x == val); + } } END_TEST +START_TEST(test_xmr_gen_range_sig) { + uint64_t tests[] = { + 0, 1, 65535, 65537, 0xffffffffffffffffULL, 0xdeadc0deULL, + }; -START_TEST(test_xmr_gen_range_sig) -{ - uint64_t tests[] = { - 0, 1, 65535, 65537, 0xffffffffffffffffULL, 0xdeadc0deULL, - }; - - unsigned char buff[32]; - xmr_range_sig_t sig; - ge25519 C, Ctmp, Cb, Ch, P1, P2, LL; - bignum256modm mask, hsh, ee, s, ee_comp; - Hasher hasher; + unsigned char buff[32]; + xmr_range_sig_t sig; + ge25519 C, Ctmp, Cb, Ch, P1, P2, LL; + bignum256modm mask, hsh, ee, s, ee_comp; + Hasher hasher; - for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { - xmr_gen_range_sig(&sig, &C, mask, tests[i], NULL); + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + xmr_gen_range_sig(&sig, &C, mask, tests[i], NULL); - ge25519_set_neutral(&Ctmp); - for(int j = 0; j < XMR_ATOMS; j++){ - ge25519_unpack_vartime(&Cb, sig.Ci[j]); - ge25519_add(&Ctmp, &Ctmp, &Cb, 0); - } + ge25519_set_neutral(&Ctmp); + for (int j = 0; j < XMR_ATOMS; j++) { + ge25519_unpack_vartime(&Cb, sig.Ci[j]); + ge25519_add(&Ctmp, &Ctmp, &Cb, 0); + } - ck_assert_int_eq(ge25519_eq(&C, &Ctmp), 1); + ck_assert_int_eq(ge25519_eq(&C, &Ctmp), 1); - xmr_hasher_init(&hasher); - ge25519_set_xmr_h(&Ch); - expand256_modm(ee, sig.asig.ee, 32); + xmr_hasher_init(&hasher); + ge25519_set_xmr_h(&Ch); + expand256_modm(ee, sig.asig.ee, 32); - for(int j = 0; j < XMR_ATOMS; j++){ - ge25519_unpack_vartime(&P1, sig.Ci[j]); - ge25519_add(&P2, &P1, &Ch, 1); - expand256_modm(s, sig.asig.s0[j], 32); + for (int j = 0; j < XMR_ATOMS; j++) { + ge25519_unpack_vartime(&P1, sig.Ci[j]); + ge25519_add(&P2, &P1, &Ch, 1); + expand256_modm(s, sig.asig.s0[j], 32); - xmr_add_keys2(&LL, s, ee, &P1); - ge25519_pack(buff, &LL); - xmr_hash_to_scalar(hsh, buff, 32); + xmr_add_keys2(&LL, s, ee, &P1); + ge25519_pack(buff, &LL); + xmr_hash_to_scalar(hsh, buff, 32); - expand256_modm(s, sig.asig.s1[j], 32); - xmr_add_keys2(&LL, s, hsh, &P2); + expand256_modm(s, sig.asig.s1[j], 32); + xmr_add_keys2(&LL, s, hsh, &P2); - ge25519_pack(buff, &LL); - xmr_hasher_update(&hasher, buff, 32); + ge25519_pack(buff, &LL); + xmr_hasher_update(&hasher, buff, 32); - ge25519_double(&Ch, &Ch); - } + ge25519_double(&Ch, &Ch); + } - xmr_hasher_final(&hasher, buff); - expand256_modm(ee_comp, buff, 32); - ck_assert_int_eq(eq256_modm(ee, ee_comp), 1); - } + xmr_hasher_final(&hasher, buff); + expand256_modm(ee_comp, buff, 32); + ck_assert_int_eq(eq256_modm(ee, ee_comp), 1); + } } END_TEST #endif diff --git a/tests/test_check_segwit.h b/tests/test_check_segwit.h index c0b7ef403..89dcaf9ae 100644 --- a/tests/test_check_segwit.h +++ b/tests/test_check_segwit.h @@ -1,184 +1,160 @@ #include "segwit_addr.h" static const char* valid_checksum[] = { - "A12UEL5L", - "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", - "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", - "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", - "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", + "A12UEL5L", + "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedchar" + "actersbio1tt5tgs", + "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + "qqqqqqqqqqc8247j", + "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", }; static const char* invalid_checksum[] = { - " 1nwldj5", - "\x7f""1axkwrx", - "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", - "pzry9x0s0muk", - "1pzry9x0s0muk", - "x1b4n0q5v", - "li1dgmt3", - "de1lg7wt\xff", + " 1nwldj5", + "\x7f" + "1axkwrx", + "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcha" + "ractersbio1569pvx", + "pzry9x0s0muk", + "1pzry9x0s0muk", + "x1b4n0q5v", + "li1dgmt3", + "de1lg7wt\xff", }; struct valid_address_data { - const char* address; - size_t scriptPubKeyLen; - const uint8_t scriptPubKey[42]; + const char* address; + size_t scriptPubKeyLen; + const uint8_t scriptPubKey[42]; }; struct invalid_address_data { - const char* hrp; - int version; - size_t program_length; + const char* hrp; + int version; + size_t program_length; }; static struct valid_address_data valid_address[] = { - { - "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", - 22, { - 0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, - 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6 - } - }, - { - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", - 34, { - 0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04, - 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78, - 0xcd, 0x4d, 0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, - 0x62 - } - }, - { - "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", - 42, { - 0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, - 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6, - 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, - 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6 - } - }, - { - "BC1SW50QA3JX3S", - 4, { - 0x60, 0x02, 0x75, 0x1e - } - }, - { - "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", - 18, { - 0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, - 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23 - } - }, - { - "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", - 34, { - 0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, - 0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, - 0xe9, 0x1c, 0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, - 0x33 - } - } -}; + {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", + 22, + {0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, + 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}}, + {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", + 34, + {0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04, 0xbd, + 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, + 0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}}, + {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grpl" + "x", + 42, + {0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, + 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6, + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, + 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}}, + {"BC1SW50QA3JX3S", 4, {0x60, 0x02, 0x75, 0x1e}}, + {"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", + 18, + {0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23}}, + {"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", + 34, + {0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, 0xb2, + 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c, + 0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}}}; static const char* invalid_address[] = { - "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", - "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", - "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", - "bc1rw5uspcuh", - "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", - "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7", - "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", - "bc1gmk9yu", + "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", + "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", + "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", + "bc1rw5uspcuh", + "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs" + "90", + "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7", + "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", + "bc1gmk9yu", }; static struct invalid_address_data invalid_address_enc[] = { - {"BC", 0, 20}, - {"bc", 0, 21}, - {"bc", 17, 32}, - {"bc", 1, 1}, - {"bc", 16, 41}, + {"BC", 0, 20}, {"bc", 0, 21}, {"bc", 17, 32}, {"bc", 1, 1}, {"bc", 16, 41}, }; -static void segwit_scriptpubkey(uint8_t* scriptpubkey, size_t* scriptpubkeylen, int witver, const uint8_t* witprog, size_t witprog_len) { - scriptpubkey[0] = witver ? (0x50 + witver) : 0; - scriptpubkey[1] = witprog_len; - memcpy(scriptpubkey + 2, witprog, witprog_len); - *scriptpubkeylen = witprog_len + 2; -} - -int my_strncasecmp(const char *s1, const char *s2, size_t n) { - size_t i = 0; - while (i < n) { - char c1 = s1[i]; - char c2 = s2[i]; - if (c1 >= 'A' && c1 <= 'Z') c1 = (c1 - 'A') + 'a'; - if (c2 >= 'A' && c2 <= 'Z') c2 = (c2 - 'A') + 'a'; - if (c1 < c2) return -1; - if (c1 > c2) return 1; - if (c1 == 0) return 0; - ++i; - } - return 0; +static void segwit_scriptpubkey(uint8_t* scriptpubkey, size_t* scriptpubkeylen, + int witver, const uint8_t* witprog, + size_t witprog_len) { + scriptpubkey[0] = witver ? (0x50 + witver) : 0; + scriptpubkey[1] = witprog_len; + memcpy(scriptpubkey + 2, witprog, witprog_len); + *scriptpubkeylen = witprog_len + 2; } -START_TEST(test_segwit) -{ - size_t i; - for (i = 0; i < sizeof(valid_checksum) / sizeof(valid_checksum[0]); ++i) { - uint8_t data[82]; - char rebuild[92]; - char hrp[84]; - size_t data_len; - int res = bech32_decode(hrp, data, &data_len, valid_checksum[i]); - ck_assert_int_eq(res, 1); - res = bech32_encode(rebuild, hrp, data, data_len); - ck_assert_int_eq(res, 1); - ck_assert_int_eq(my_strncasecmp(rebuild, valid_checksum[i], 92), 0); - } - for (i = 0; i < sizeof(invalid_checksum) / sizeof(invalid_checksum[0]); ++i) { - uint8_t data[82]; - char hrp[84]; - size_t data_len; - int res = bech32_decode(hrp, data, &data_len, invalid_checksum[i]); - ck_assert_int_eq(res, 0); - } - for (i = 0; i < sizeof(valid_address) / sizeof(valid_address[0]); ++i) { - uint8_t witprog[40]; - size_t witprog_len; - int witver; - const char* hrp = "bc"; - uint8_t scriptpubkey[42]; - size_t scriptpubkey_len; - char rebuild[93]; - int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, valid_address[i].address); - if (!ret) { - hrp = "tb"; - ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, valid_address[i].address); - } - ck_assert_int_eq(ret, 1); - segwit_scriptpubkey(scriptpubkey, &scriptpubkey_len, witver, witprog, witprog_len); - ck_assert_int_eq(scriptpubkey_len, valid_address[i].scriptPubKeyLen); - ck_assert_int_eq(memcmp(scriptpubkey, valid_address[i].scriptPubKey, scriptpubkey_len), 0); - ck_assert_int_eq(segwit_addr_encode(rebuild, hrp, witver, witprog, witprog_len), 1); - ck_assert_int_eq(my_strncasecmp(valid_address[i].address, rebuild, 93), 0); - } - for (i = 0; i < sizeof(invalid_address) / sizeof(invalid_address[0]); ++i) { - uint8_t witprog[40]; - size_t witprog_len; - int witver; - int ret = segwit_addr_decode(&witver, witprog, &witprog_len, "bc", invalid_address[i]); - ck_assert_int_eq(ret, 0); - ret = segwit_addr_decode(&witver, witprog, &witprog_len, "tb", invalid_address[i]); - ck_assert_int_eq(ret, 0); - } - for (i = 0; i < sizeof(invalid_address_enc) / sizeof(invalid_address_enc[0]); ++i) { - char rebuild[93]; - static const uint8_t program[42] = {0}; - int ret = segwit_addr_encode(rebuild, invalid_address_enc[i].hrp, invalid_address_enc[i].version, program, invalid_address_enc[i].program_length); - ck_assert_int_eq(ret, 0); - } +START_TEST(test_segwit) { + size_t i; + for (i = 0; i < sizeof(valid_checksum) / sizeof(valid_checksum[0]); ++i) { + uint8_t data[82]; + char rebuild[92]; + char hrp[84]; + size_t data_len; + int res = bech32_decode(hrp, data, &data_len, valid_checksum[i]); + ck_assert_int_eq(res, 1); + res = bech32_encode(rebuild, hrp, data, data_len); + ck_assert_int_eq(res, 1); + ck_assert_int_eq(my_strncasecmp(rebuild, valid_checksum[i], 92), 0); + } + for (i = 0; i < sizeof(invalid_checksum) / sizeof(invalid_checksum[0]); ++i) { + uint8_t data[82]; + char hrp[84]; + size_t data_len; + int res = bech32_decode(hrp, data, &data_len, invalid_checksum[i]); + ck_assert_int_eq(res, 0); + } + for (i = 0; i < sizeof(valid_address) / sizeof(valid_address[0]); ++i) { + uint8_t witprog[40]; + size_t witprog_len; + int witver; + const char* hrp = "bc"; + uint8_t scriptpubkey[42]; + size_t scriptpubkey_len; + char rebuild[93]; + int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, + valid_address[i].address); + if (!ret) { + hrp = "tb"; + ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, + valid_address[i].address); + } + ck_assert_int_eq(ret, 1); + segwit_scriptpubkey(scriptpubkey, &scriptpubkey_len, witver, witprog, + witprog_len); + ck_assert_int_eq(scriptpubkey_len, valid_address[i].scriptPubKeyLen); + ck_assert_int_eq( + memcmp(scriptpubkey, valid_address[i].scriptPubKey, scriptpubkey_len), + 0); + ck_assert_int_eq( + segwit_addr_encode(rebuild, hrp, witver, witprog, witprog_len), 1); + ck_assert_int_eq(my_strncasecmp(valid_address[i].address, rebuild, 93), 0); + } + for (i = 0; i < sizeof(invalid_address) / sizeof(invalid_address[0]); ++i) { + uint8_t witprog[40]; + size_t witprog_len; + int witver; + int ret = segwit_addr_decode(&witver, witprog, &witprog_len, "bc", + invalid_address[i]); + ck_assert_int_eq(ret, 0); + ret = segwit_addr_decode(&witver, witprog, &witprog_len, "tb", + invalid_address[i]); + ck_assert_int_eq(ret, 0); + } + for (i = 0; i < sizeof(invalid_address_enc) / sizeof(invalid_address_enc[0]); + ++i) { + char rebuild[93]; + static const uint8_t program[42] = {0}; + int ret = segwit_addr_encode(rebuild, invalid_address_enc[i].hrp, + invalid_address_enc[i].version, program, + invalid_address_enc[i].program_length); + ck_assert_int_eq(ret, 0); + } } END_TEST diff --git a/tests/test_openssl.c b/tests/test_openssl.c index d0a80f074..c6ce47894 100644 --- a/tests/test_openssl.c +++ b/tests/test_openssl.c @@ -27,118 +27,117 @@ #include #include #include -#include #include +#include #undef SHA256_CTX #undef SHA512_CTX -#include #include +#include #include #include "ecdsa.h" -#include "rand.h" #include "hasher.h" +#include "rand.h" #include "nist256p1.h" #include "secp256k1.h" #include "memzero.h" -void openssl_check(unsigned int iterations, int nid, const ecdsa_curve *curve) -{ - uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256], hash[32]; - struct SHA256state_st sha256; - EC_GROUP *ecgroup; - - ecgroup = EC_GROUP_new_by_curve_name(nid); - - for (unsigned int iter = 0; iter < iterations; iter++) { - - // random message len between 1 and 256 - int msg_len = (random32() & 0xFF) + 1; - // create random message - random_buffer(msg, msg_len); - - // new ECDSA key - EC_KEY *eckey = EC_KEY_new(); - EC_KEY_set_group(eckey, ecgroup); - - // generate the key - EC_KEY_generate_key(eckey); - // copy key to buffer - const BIGNUM *K = EC_KEY_get0_private_key(eckey); - int bn_off = sizeof(priv_key) - BN_num_bytes(K); - memzero(priv_key, bn_off); - BN_bn2bin(K, priv_key + bn_off); - - // use our ECDSA signer to sign the message with the key - if (ecdsa_sign(curve, HASHER_SHA2, priv_key, msg, msg_len, sig, NULL, NULL) != 0) { - printf("trezor-crypto signing failed\n"); - return; - } - - // generate public key from private key - ecdsa_get_public_key33(curve, priv_key, pub_key33); - ecdsa_get_public_key65(curve, priv_key, pub_key65); - - // use our ECDSA verifier to verify the message signature - if (ecdsa_verify(curve, HASHER_SHA2, pub_key65, sig, msg, msg_len) != 0) { - printf("trezor-crypto verification failed (pub_key_len = 65)\n"); - return; - } - if (ecdsa_verify(curve, HASHER_SHA2, pub_key33, sig, msg, msg_len) != 0) { - printf("trezor-crypto verification failed (pub_key_len = 33)\n"); - return; - } - - // copy signature to the OpenSSL struct - ECDSA_SIG *signature = ECDSA_SIG_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - BN_bin2bn(sig, 32, signature->r); - BN_bin2bn(sig + 32, 32, signature->s); +void openssl_check(unsigned int iterations, int nid, const ecdsa_curve *curve) { + uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256], + hash[32]; + struct SHA256state_st sha256; + EC_GROUP *ecgroup; + + ecgroup = EC_GROUP_new_by_curve_name(nid); + + for (unsigned int iter = 0; iter < iterations; iter++) { + // random message len between 1 and 256 + int msg_len = (random32() & 0xFF) + 1; + // create random message + random_buffer(msg, msg_len); + + // new ECDSA key + EC_KEY *eckey = EC_KEY_new(); + EC_KEY_set_group(eckey, ecgroup); + + // generate the key + EC_KEY_generate_key(eckey); + // copy key to buffer + const BIGNUM *K = EC_KEY_get0_private_key(eckey); + int bn_off = sizeof(priv_key) - BN_num_bytes(K); + memzero(priv_key, bn_off); + BN_bn2bin(K, priv_key + bn_off); + + // use our ECDSA signer to sign the message with the key + if (ecdsa_sign(curve, HASHER_SHA2, priv_key, msg, msg_len, sig, NULL, + NULL) != 0) { + printf("trezor-crypto signing failed\n"); + return; + } + + // generate public key from private key + ecdsa_get_public_key33(curve, priv_key, pub_key33); + ecdsa_get_public_key65(curve, priv_key, pub_key65); + + // use our ECDSA verifier to verify the message signature + if (ecdsa_verify(curve, HASHER_SHA2, pub_key65, sig, msg, msg_len) != 0) { + printf("trezor-crypto verification failed (pub_key_len = 65)\n"); + return; + } + if (ecdsa_verify(curve, HASHER_SHA2, pub_key33, sig, msg, msg_len) != 0) { + printf("trezor-crypto verification failed (pub_key_len = 33)\n"); + return; + } + + // copy signature to the OpenSSL struct + ECDSA_SIG *signature = ECDSA_SIG_new(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + BN_bin2bn(sig, 32, signature->r); + BN_bin2bn(sig + 32, 32, signature->s); #else - BIGNUM *R = BN_bin2bn(sig, 32, NULL); - BIGNUM *S = BN_bin2bn(sig + 32, 32, NULL); - ECDSA_SIG_set0(signature, R, S); + BIGNUM *R = BN_bin2bn(sig, 32, NULL); + BIGNUM *S = BN_bin2bn(sig + 32, 32, NULL); + ECDSA_SIG_set0(signature, R, S); #endif - // compute the digest of the message - // note: these are OpenSSL functions, not our own - SHA256_Init(&sha256); - SHA256_Update(&sha256, msg, msg_len); - SHA256_Final(hash, &sha256); - - // verify all went well, i.e. we can decrypt our signature with OpenSSL - int v = ECDSA_do_verify(hash, 32, signature, eckey); - if (v != 1) { - printf("OpenSSL verification failed (%d)\n", v); - return; - } - - ECDSA_SIG_free(signature); - EC_KEY_free(eckey); - if (((iter + 1) % 100) == 0) printf("Passed ... %d\n", iter + 1); - } - EC_GROUP_free(ecgroup); - printf("All OK\n"); + // compute the digest of the message + // note: these are OpenSSL functions, not our own + SHA256_Init(&sha256); + SHA256_Update(&sha256, msg, msg_len); + SHA256_Final(hash, &sha256); + + // verify all went well, i.e. we can decrypt our signature with OpenSSL + int v = ECDSA_do_verify(hash, 32, signature, eckey); + if (v != 1) { + printf("OpenSSL verification failed (%d)\n", v); + return; + } + + ECDSA_SIG_free(signature); + EC_KEY_free(eckey); + if (((iter + 1) % 100) == 0) printf("Passed ... %d\n", iter + 1); + } + EC_GROUP_free(ecgroup); + printf("All OK\n"); } -int main(int argc, char *argv[]) -{ - if (argc != 2) { - printf("Usage: test_openssl iterations\n"); - return 1; - } +int main(int argc, char *argv[]) { + if (argc != 2) { + printf("Usage: test_openssl iterations\n"); + return 1; + } - unsigned int iterations; - sscanf(argv[1], "%u", &iterations); + unsigned int iterations; + sscanf(argv[1], "%u", &iterations); - printf("Testing secp256k1:\n"); - openssl_check(iterations, NID_secp256k1, &secp256k1); + printf("Testing secp256k1:\n"); + openssl_check(iterations, NID_secp256k1, &secp256k1); - printf("Testing nist256p1:\n"); - openssl_check(iterations, NID_X9_62_prime256v1, &nist256p1); + printf("Testing nist256p1:\n"); + openssl_check(iterations, NID_X9_62_prime256v1, &nist256p1); - return 0; + return 0; } diff --git a/tests/test_speed.c b/tests/test_speed.c index 592186fbb..c9e67b5ee 100644 --- a/tests/test_speed.c +++ b/tests/test_speed.c @@ -1,215 +1,233 @@ -#include #include -#include -#include #include +#include +#include +#include +#include "bip32.h" #include "curves.h" #include "ecdsa.h" -#include "bip32.h" -#include "secp256k1.h" -#include "nist256p1.h" #include "ed25519-donna/ed25519.h" #include "hasher.h" +#include "nist256p1.h" +#include "secp256k1.h" static uint8_t msg[256]; -void prepare_msg(void) -{ - for (size_t i = 0; i < sizeof(msg); i++) { - msg[i] = i * 1103515245; - } +void prepare_msg(void) { + for (size_t i = 0; i < sizeof(msg); i++) { + msg[i] = i * 1103515245; + } } -void bench_sign_secp256k1(int iterations) -{ - uint8_t sig[64], priv[32], pby; +void bench_sign_secp256k1(int iterations) { + uint8_t sig[64], priv[32], pby; - const ecdsa_curve *curve = &secp256k1; + const ecdsa_curve *curve = &secp256k1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); - for (int i = 0 ; i < iterations; i++) { - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - } + for (int i = 0; i < iterations; i++) { + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + } } -void bench_sign_nist256p1(int iterations) -{ - uint8_t sig[64], priv[32], pby; +void bench_sign_nist256p1(int iterations) { + uint8_t sig[64], priv[32], pby; - const ecdsa_curve *curve = &nist256p1; + const ecdsa_curve *curve = &nist256p1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); - for (int i = 0 ; i < iterations; i++) { - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - } + for (int i = 0; i < iterations; i++) { + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + } } -void bench_sign_ed25519(int iterations) -{ - ed25519_public_key pk; - ed25519_secret_key sk; - ed25519_signature sig; +void bench_sign_ed25519(int iterations) { + ed25519_public_key pk; + ed25519_secret_key sk; + ed25519_signature sig; - memcpy(pk, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ed25519_publickey(sk, pk); + memcpy(pk, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ed25519_publickey(sk, pk); - for (int i = 0 ; i < iterations; i++) { - ed25519_sign(msg, sizeof(msg), sk, pk, sig); - } + for (int i = 0; i < iterations; i++) { + ed25519_sign(msg, sizeof(msg), sk, pk, sig); + } } -void bench_verify_secp256k1_33(int iterations) -{ - uint8_t sig[64], pub[33], priv[32], pby; +void bench_verify_secp256k1_33(int iterations) { + uint8_t sig[64], pub[33], priv[32], pby; - const ecdsa_curve *curve = &secp256k1; + const ecdsa_curve *curve = &secp256k1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ecdsa_get_public_key33(curve, priv, pub); - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ecdsa_get_public_key33(curve, priv, pub); + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - for (int i = 0 ; i < iterations; i++) { - ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); - } + for (int i = 0; i < iterations; i++) { + ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); + } } -void bench_verify_secp256k1_65(int iterations) -{ - uint8_t sig[64], pub[65], priv[32], pby; +void bench_verify_secp256k1_65(int iterations) { + uint8_t sig[64], pub[65], priv[32], pby; - const ecdsa_curve *curve = &secp256k1; + const ecdsa_curve *curve = &secp256k1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ecdsa_get_public_key65(curve, priv, pub); - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ecdsa_get_public_key65(curve, priv, pub); + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - for (int i = 0 ; i < iterations; i++) { - ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); - } + for (int i = 0; i < iterations; i++) { + ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); + } } -void bench_verify_nist256p1_33(int iterations) -{ - uint8_t sig[64], pub[33], priv[32], pby; +void bench_verify_nist256p1_33(int iterations) { + uint8_t sig[64], pub[33], priv[32], pby; - const ecdsa_curve *curve = &nist256p1; + const ecdsa_curve *curve = &nist256p1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ecdsa_get_public_key33(curve, priv, pub); - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ecdsa_get_public_key33(curve, priv, pub); + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - for (int i = 0 ; i < iterations; i++) { - ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); - } + for (int i = 0; i < iterations; i++) { + ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); + } } -void bench_verify_nist256p1_65(int iterations) -{ - uint8_t sig[64], pub[65], priv[32], pby; +void bench_verify_nist256p1_65(int iterations) { + uint8_t sig[64], pub[65], priv[32], pby; - const ecdsa_curve *curve = &nist256p1; + const ecdsa_curve *curve = &nist256p1; - memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ecdsa_get_public_key65(curve, priv, pub); - ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); + memcpy(priv, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ecdsa_get_public_key65(curve, priv, pub); + ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL); - for (int i = 0 ; i < iterations; i++) { - ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); - } + for (int i = 0; i < iterations; i++) { + ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg)); + } } -void bench_verify_ed25519(int iterations) -{ - ed25519_public_key pk; - ed25519_secret_key sk; - ed25519_signature sig; - - memcpy(pk, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - ed25519_publickey(sk, pk); - ed25519_sign(msg, sizeof(msg), sk, pk, sig); - - for (int i = 0 ; i < iterations; i++) { - ed25519_sign_open(msg, sizeof(msg), pk, sig); - } +void bench_verify_ed25519(int iterations) { + ed25519_public_key pk; + ed25519_secret_key sk; + ed25519_signature sig; + + memcpy(pk, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + ed25519_publickey(sk, pk); + ed25519_sign(msg, sizeof(msg), sk, pk, sig); + + for (int i = 0; i < iterations; i++) { + ed25519_sign_open(msg, sizeof(msg), pk, sig); + } } -void bench_multiply_curve25519(int iterations) -{ - uint8_t result[32]; - uint8_t secret[32]; - uint8_t basepoint[32]; - - memcpy(secret, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); - memcpy(basepoint, "\x96\x47\xda\xbe\x1e\xea\xaf\x25\x47\x1e\x68\x0b\x4d\x7c\x6f\xd1\x14\x38\x76\xbb\x77\x59\xd8\x3d\x0f\xf7\xa2\x49\x08\xfd\xda\xbc", 32); - - for (int i = 0 ; i < iterations; i++) { - curve25519_scalarmult(result, secret, basepoint); - } +void bench_multiply_curve25519(int iterations) { + uint8_t result[32]; + uint8_t secret[32]; + uint8_t basepoint[32]; + + memcpy(secret, + "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3" + "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", + 32); + memcpy(basepoint, + "\x96\x47\xda\xbe\x1e\xea\xaf\x25\x47\x1e\x68\x0b\x4d\x7c\x6f\xd1\x14" + "\x38\x76\xbb\x77\x59\xd8\x3d\x0f\xf7\xa2\x49\x08\xfd\xda\xbc", + 32); + + for (int i = 0; i < iterations; i++) { + curve25519_scalarmult(result, secret, basepoint); + } } static HDNode root; -void prepare_node(void) -{ - hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root); - hdnode_fill_public_key(&root); +void prepare_node(void) { + hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root); + hdnode_fill_public_key(&root); } -void bench_ckd_normal(int iterations) -{ - char addr[MAX_ADDR_SIZE]; - HDNode node; - for (int i = 0; i < iterations; i++) { - memcpy(&node, &root, sizeof(HDNode)); - hdnode_public_ckd(&node, i); - hdnode_fill_public_key(&node); - ecdsa_get_address(node.public_key, HASHER_SHA2, HASHER_SHA2D, 0, addr, sizeof(addr)); - } +void bench_ckd_normal(int iterations) { + char addr[MAX_ADDR_SIZE]; + HDNode node; + for (int i = 0; i < iterations; i++) { + memcpy(&node, &root, sizeof(HDNode)); + hdnode_public_ckd(&node, i); + hdnode_fill_public_key(&node); + ecdsa_get_address(node.public_key, HASHER_SHA2, HASHER_SHA2D, 0, addr, + sizeof(addr)); + } } -void bench_ckd_optimized(int iterations) -{ - char addr[MAX_ADDR_SIZE]; - curve_point pub; - ecdsa_read_pubkey(&secp256k1, root.public_key, &pub); - for (int i = 0; i < iterations; i++) { - hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0, HASHER_SHA2, HASHER_SHA2D, addr, sizeof(addr), false); - } +void bench_ckd_optimized(int iterations) { + char addr[MAX_ADDR_SIZE]; + curve_point pub; + ecdsa_read_pubkey(&secp256k1, root.public_key, &pub); + for (int i = 0; i < iterations; i++) { + hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0, + HASHER_SHA2, HASHER_SHA2D, addr, + sizeof(addr), false); + } } -void bench(void (*func)(int), const char *name, int iterations) -{ - clock_t t = clock(); - func(iterations); - float speed = iterations / ((float)(clock() - t) / CLOCKS_PER_SEC); - printf("%25s: %8.2f ops/s\n", name, speed); +void bench(void (*func)(int), const char *name, int iterations) { + clock_t t = clock(); + func(iterations); + float speed = iterations / ((float)(clock() - t) / CLOCKS_PER_SEC); + printf("%25s: %8.2f ops/s\n", name, speed); } #define BENCH(FUNC, ITER) bench(FUNC, #FUNC, ITER) int main(void) { + prepare_msg(); - prepare_msg(); - - BENCH(bench_sign_secp256k1, 500); - BENCH(bench_verify_secp256k1_33, 500); - BENCH(bench_verify_secp256k1_65, 500); + BENCH(bench_sign_secp256k1, 500); + BENCH(bench_verify_secp256k1_33, 500); + BENCH(bench_verify_secp256k1_65, 500); - BENCH(bench_sign_nist256p1, 500); - BENCH(bench_verify_nist256p1_33, 500); - BENCH(bench_verify_nist256p1_65, 500); + BENCH(bench_sign_nist256p1, 500); + BENCH(bench_verify_nist256p1_33, 500); + BENCH(bench_verify_nist256p1_65, 500); - BENCH(bench_sign_ed25519, 4000); - BENCH(bench_verify_ed25519, 4000); + BENCH(bench_sign_ed25519, 4000); + BENCH(bench_verify_ed25519, 4000); - BENCH(bench_multiply_curve25519, 4000); + BENCH(bench_multiply_curve25519, 4000); - prepare_node(); + prepare_node(); - BENCH(bench_ckd_normal, 1000); - BENCH(bench_ckd_optimized, 1000); + BENCH(bench_ckd_normal, 1000); + BENCH(bench_ckd_optimized, 1000); - return 0; + return 0; } diff --git a/tools/bip39bruteforce.c b/tools/bip39bruteforce.c index be2fa5b76..723343fe2 100644 --- a/tools/bip39bruteforce.c +++ b/tools/bip39bruteforce.c @@ -1,10 +1,10 @@ #include -#include #include -#include "bip39.h" +#include #include "bip32.h" -#include "ecdsa.h" +#include "bip39.h" #include "curves.h" +#include "ecdsa.h" #include "secp256k1.h" char iter[256]; @@ -26,63 +26,64 @@ clock_t start; // address: "1N3uJ5AU3FTYQ1ZQgTMtYmgSvMBmQiGVBS" // passphrase: "testing" -int main(int argc, char **argv) -{ - if (argc != 2 && argc != 3) { - fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n"); - return 1; - } - const char *address = argv[1]; - const char *mnemonic, *item; - if (argc == 3) { - mnemonic = argv[2]; - item = "passphrase"; - } else { - mnemonic = NULL; - item = "mnemonic"; - } - if (mnemonic && !mnemonic_check(mnemonic)) { - fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic); - return 2; - } - if (!ecdsa_address_decode(address, 0, secp256k1_info.hasher_base58, addr)) { - fprintf(stderr, "\"%s\" is not a valid address\n", address); - return 3; - } - printf("Reading %ss from stdin ...\n", item); - start = clock(); - for (;;) { - if (fgets(iter, 256, stdin) == NULL) break; - int len = strlen(iter); - if (len <= 0) { - continue; - } - count++; - iter[len - 1] = 0; - if (mnemonic) { - mnemonic_to_seed(mnemonic, iter, seed, NULL); - } else { - mnemonic_to_seed(iter, "", seed, NULL); - } - hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node); - hdnode_private_ckd_prime(&node, 44); - hdnode_private_ckd_prime(&node, 0); - hdnode_private_ckd_prime(&node, 0); - hdnode_private_ckd(&node, 0); - hdnode_private_ckd(&node, 0); - hdnode_fill_public_key(&node); - ecdsa_get_pubkeyhash(node.public_key, secp256k1_info.hasher_pubkey, pubkeyhash); - if (memcmp(addr + 1, pubkeyhash, 20) == 0) { - found = 1; - break; - } - } - float dur = (float)(clock() - start) / CLOCKS_PER_SEC; - printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur, (float)count/dur); - if (found) { - printf("Correct %s found! :-)\n\"%s\"\n", item, iter); - return 0; - } - printf("Correct %s not found. :-(\n", item); - return 4; +int main(int argc, char **argv) { + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n"); + return 1; + } + const char *address = argv[1]; + const char *mnemonic, *item; + if (argc == 3) { + mnemonic = argv[2]; + item = "passphrase"; + } else { + mnemonic = NULL; + item = "mnemonic"; + } + if (mnemonic && !mnemonic_check(mnemonic)) { + fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic); + return 2; + } + if (!ecdsa_address_decode(address, 0, secp256k1_info.hasher_base58, addr)) { + fprintf(stderr, "\"%s\" is not a valid address\n", address); + return 3; + } + printf("Reading %ss from stdin ...\n", item); + start = clock(); + for (;;) { + if (fgets(iter, 256, stdin) == NULL) break; + int len = strlen(iter); + if (len <= 0) { + continue; + } + count++; + iter[len - 1] = 0; + if (mnemonic) { + mnemonic_to_seed(mnemonic, iter, seed, NULL); + } else { + mnemonic_to_seed(iter, "", seed, NULL); + } + hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node); + hdnode_private_ckd_prime(&node, 44); + hdnode_private_ckd_prime(&node, 0); + hdnode_private_ckd_prime(&node, 0); + hdnode_private_ckd(&node, 0); + hdnode_private_ckd(&node, 0); + hdnode_fill_public_key(&node); + ecdsa_get_pubkeyhash(node.public_key, secp256k1_info.hasher_pubkey, + pubkeyhash); + if (memcmp(addr + 1, pubkeyhash, 20) == 0) { + found = 1; + break; + } + } + float dur = (float)(clock() - start) / CLOCKS_PER_SEC; + printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur, + (float)count / dur); + if (found) { + printf("Correct %s found! :-)\n\"%s\"\n", item, iter); + return 0; + } + printf("Correct %s not found. :-(\n", item); + return 4; } diff --git a/tools/mktable.c b/tools/mktable.c index 01ec375c9..f9ab1c653 100644 --- a/tools/mktable.c +++ b/tools/mktable.c @@ -1,8 +1,8 @@ -#include #include +#include #include "bignum.h" -#include "ecdsa.h" #include "bip32.h" +#include "ecdsa.h" #include "rand.h" /* @@ -11,58 +11,58 @@ * where G is the generator of the specified elliptic curve. */ int main(int argc, char **argv) { - int i,j,k; - if (argc != 2) { - printf("Usage: %s CURVE_NAME\n", argv[0]); - return 1; - } - const char *name = argv[1]; - const curve_info *info = get_curve_by_name(name); - const ecdsa_curve *curve = info->params; - if (curve == 0) { - printf("Unknown curve '%s'\n", name); - return 1; - } + int i, j, k; + if (argc != 2) { + printf("Usage: %s CURVE_NAME\n", argv[0]); + return 1; + } + const char *name = argv[1]; + const curve_info *info = get_curve_by_name(name); + const ecdsa_curve *curve = info->params; + if (curve == 0) { + printf("Unknown curve '%s'\n", name); + return 1; + } - curve_point ng = curve->G; - curve_point pow2ig = curve->G; - for (i = 0; i < 64; i++) { - // invariants: - // pow2ig = 16^i * G - // ng = pow2ig - printf("\t{\n"); - for (j = 0; j < 8; j++) { - // invariants: - // pow2ig = 16^i * G - // ng = (2*j+1) * 16^i * G + curve_point ng = curve->G; + curve_point pow2ig = curve->G; + for (i = 0; i < 64; i++) { + // invariants: + // pow2ig = 16^i * G + // ng = pow2ig + printf("\t{\n"); + for (j = 0; j < 8; j++) { + // invariants: + // pow2ig = 16^i * G + // ng = (2*j+1) * 16^i * G #ifndef NDEBUG - curve_point checkresult; - bignum256 a; - bn_zero(&a); - a.val[(4*i) / 30] = ((uint32_t) 2*j+1) << ((4*i) % 30); - bn_normalize(&a); - point_multiply(curve, &a, &curve->G, &checkresult); - assert(point_is_equal(&checkresult, &ng)); + curve_point checkresult; + bignum256 a; + bn_zero(&a); + a.val[(4 * i) / 30] = ((uint32_t)2 * j + 1) << ((4 * i) % 30); + bn_normalize(&a); + point_multiply(curve, &a, &curve->G, &checkresult); + assert(point_is_equal(&checkresult, &ng)); #endif - printf("\t\t/* %2d*16^%d*G: */\n\t\t{{{", 2*j + 1, i); - // print x coordinate - for (k = 0; k < 9; k++) { - printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.x.val[k]); - } - printf("}},\n\t\t {{"); - // print y coordinate - for (k = 0; k < 9; k++) { - printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.y.val[k]); - } - if (j == 7) { - printf("}}}\n\t},\n"); - } else { - printf("}}},\n"); - point_add(curve, &pow2ig, &ng); - } - point_add(curve, &pow2ig, &ng); - } - pow2ig = ng; - } - return 0; + printf("\t\t/* %2d*16^%d*G: */\n\t\t{{{", 2 * j + 1, i); + // print x coordinate + for (k = 0; k < 9; k++) { + printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.x.val[k]); + } + printf("}},\n\t\t {{"); + // print y coordinate + for (k = 0; k < 9; k++) { + printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.y.val[k]); + } + if (j == 7) { + printf("}}}\n\t},\n"); + } else { + printf("}}},\n"); + point_add(curve, &pow2ig, &ng); + } + point_add(curve, &pow2ig, &ng); + } + pow2ig = ng; + } + return 0; } diff --git a/tools/xpubaddrgen.c b/tools/xpubaddrgen.c index 54c5ebc98..fd5e83fd7 100644 --- a/tools/xpubaddrgen.c +++ b/tools/xpubaddrgen.c @@ -1,47 +1,49 @@ +#include +#include #include #include -#include -#include #include "bip32.h" #include "curves.h" #include "ecdsa.h" -#define VERSION_PUBLIC 0x0488b21e +#define VERSION_PUBLIC 0x0488b21e #define VERSION_PRIVATE 0x0488ade4 -void process_job(uint32_t jobid, const char *xpub, uint32_t change, uint32_t from, uint32_t to) -{ - HDNode node, child; - if (change > 1 || to <= from || hdnode_deserialize(xpub, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node, NULL) != 0) { - printf("%d error\n", jobid); - return; - } - hdnode_public_ckd(&node, change); - uint32_t i; - char address[36]; - for (i = from; i < to; i++) { - memcpy(&child, &node, sizeof(HDNode)); - hdnode_public_ckd(&child, i); - ecdsa_get_address(child.public_key, 0, HASHER_SHA2, HASHER_SHA2D, address, sizeof(address)); - printf("%d %d %s\n", jobid, i, address); - } +void process_job(uint32_t jobid, const char *xpub, uint32_t change, + uint32_t from, uint32_t to) { + HDNode node, child; + if (change > 1 || to <= from || + hdnode_deserialize(xpub, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, + &node, NULL) != 0) { + printf("%d error\n", jobid); + return; + } + hdnode_public_ckd(&node, change); + uint32_t i; + char address[36]; + for (i = from; i < to; i++) { + memcpy(&child, &node, sizeof(HDNode)); + hdnode_public_ckd(&child, i); + ecdsa_get_address(child.public_key, 0, HASHER_SHA2, HASHER_SHA2D, address, + sizeof(address)); + printf("%d %d %s\n", jobid, i, address); + } } -int main(void) -{ - char line[1024], xpub[1024]; - uint32_t jobid, change, from, to; - int r; - for (;;) { - if (!fgets(line, sizeof(line), stdin)) break; - r = sscanf(line, "%u %s %u %u %u\n", &jobid, xpub, &change, &from, &to); - if (r < 1) { - printf("error\n"); - } else if (r != 5) { - printf("%d error\n", jobid); - } else { - process_job(jobid, xpub, change, from, to); - } - } - return 0; +int main(void) { + char line[1024], xpub[1024]; + uint32_t jobid, change, from, to; + int r; + for (;;) { + if (!fgets(line, sizeof(line), stdin)) break; + r = sscanf(line, "%u %s %u %u %u\n", &jobid, xpub, &change, &from, &to); + if (r < 1) { + printf("error\n"); + } else if (r != 5) { + printf("%d error\n", jobid); + } else { + process_job(jobid, xpub, change, from, to); + } + } + return 0; }