diff --git a/base58.c b/base58.c index c4bdd2544..217264e30 100644 --- a/base58.c +++ b/base58.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2012-2014 Luke Dashjr * Copyright (c) 2013-2014 Pavol Rusnak * * Permission is hereby granted, free of charge, to any person obtaining @@ -22,117 +22,202 @@ */ #include +#include +#include #include "base58.h" #include "sha2.h" -int base58_encode_check(const uint8_t *data, int len, char *str) +static 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, +}; + +bool b58tobin(void *bin, size_t *binszp, const char *b58) { - int outlen; - switch (len) { - case 78: // xpub/xprv 78 - outlen = 111; - break; - case 34: // WIF privkey 1+32+1 - outlen = 52; + size_t binsz = *binszp; + const unsigned char *b58u = (void*)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); + + memset(outi, 0, outisz * sizeof(*outi)); + + // Leading zeros, just count + for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++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; + } + + j = 0; + switch (bytesleft) { + case 3: + *(binu++) = (outi[0] & 0xff0000) >> 16; + case 2: + *(binu++) = (outi[0] & 0xff00) >> 8; + case 1: + *(binu++) = (outi[0] & 0xff); + ++j; + default: break; - case 21: // address 1+20 - outlen = 34; + } + + 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]) break; - default: - return 0; + --*binszp; } - uint8_t mydata[82], hash[32]; - sha256_Raw(data, len, hash); - sha256_Raw(hash, 32, hash); - memcpy(mydata, data, len); - memcpy(mydata + len, hash, 4); // checksum - uint32_t rem, tmp; - const char code[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - int i, j; - for (j = 0; j < outlen; j++) { - rem = mydata[0] % 58; - mydata[0] /= 58; - for (i = 1; i < len + 4; i++) { - tmp = rem * 24 + mydata[i]; // 2^8 == 4*58 + 24 - mydata[i] = rem * 4 + (tmp / 58); - rem = tmp % 58; + *binszp += zerocount; + + return true; +} + +int b58check(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; + sha256_Raw(bin, binsz - 4, buf); + sha256_Raw(buf, 32, 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; + + return binc[0]; +} + +static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +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; + + size = (binsz - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memset(buf, 0, 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; } - str[j] = code[rem]; } - // remove duplicite 1s at the end - while (outlen > 1 && str[outlen - 1] == code[0] && str[outlen - 2] == code[0]) { - outlen--; + + for (j = 0; j < (ssize_t)size && !buf[j]; ++j); + + if (*b58sz <= zcount + size - j) + { + *b58sz = zcount + size - j + 1; + return false; } - str[outlen] = 0; - char s; - // reverse string - for (i = 0; i < outlen / 2; i++) { - s = str[i]; - str[i] = str[outlen - 1 - i]; - str[outlen - 1 - i] = s; + + 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; +} + +#include + +int base58_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); + sha256_Raw(data, datalen, hash); + sha256_Raw(hash, 32, hash); + size_t res = strsize; + if (b58enc(str, &res, buf, datalen + 4) != true) { + return 0; } - return outlen; + return res; } -int base58_decode_check(const char *str, uint8_t *data) +int base58_decode_check(const char *str, uint8_t *data, int datalen) { - const char decode[] = { - -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 - }; - int outlen; - switch (strlen(str)) { - case 111: // xpub/xprv - outlen = 78; - break; - case 52: // WIF privkey - outlen = 35; - break; - case 27: // address - case 28: - case 29: - case 30: - case 31: - case 32: - case 33: - case 34: - outlen = 21; - break; - default: - return 0; + if (datalen > 128) { + return 0; } - uint8_t mydata[82], hash[32]; - memset(mydata, 0, sizeof(mydata)); - int i, j, k; - while (*str) { - i = *str; - if (i < 0 || i >= (int)sizeof(decode)) { // invalid character - return 0; - } - k = decode[i]; - if (k == -1) { // invalid character - return 0; - } - for (j = outlen + 4 - 1; j >= 0; j--) { - k += mydata[j] * 58; - mydata[j] = k & 0xFF; - k >>= 8; - } - str++; + uint8_t d[datalen + 4]; + size_t res = datalen + 4; + if (b58tobin(d, &res, str) != true) { + return 0; } - sha256_Raw(mydata, outlen, hash); - sha256_Raw(hash, 32, hash); - if (memcmp(mydata + outlen, hash, 4)) { // wrong checksum + if (res != (size_t)datalen + 4) { + return 0; + } + if (b58check(d, res, str) < 0) { return 0; } - memcpy(data, mydata, outlen); - return outlen; + memcpy(data, d, datalen); + return datalen; } diff --git a/base58.h b/base58.h index 491f248bf..1f3eadfbc 100644 --- a/base58.h +++ b/base58.h @@ -26,7 +26,7 @@ #include -int base58_encode_check(const uint8_t *data, int len, char *str); -int base58_decode_check(const char *str, uint8_t *data); +int base58_encode_check(const uint8_t *data, int len, char *str, int strsize); +int base58_decode_check(const char *str, uint8_t *data, int datalen); #endif diff --git a/bip32.c b/bip32.c index 6af1b8840..f4a021d57 100644 --- a/bip32.c +++ b/bip32.c @@ -181,7 +181,7 @@ void hdnode_fill_public_key(HDNode *node) ecdsa_get_public_key33(node->private_key, node->public_key); } -void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, char *str) +void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, char *str, int strsize) { uint8_t node_data[78]; write_be(node_data, version); @@ -195,17 +195,17 @@ void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, cha node_data[45] = 0; memcpy(node_data + 46, node->private_key, 32); } - base58_encode_check(node_data, 78, str); + base58_encode_check(node_data, 78, str, strsize); } -void hdnode_serialize_public(const HDNode *node, char *str) +void hdnode_serialize_public(const HDNode *node, char *str, int strsize) { - hdnode_serialize(node, 0x0488B21E, 1, str); + hdnode_serialize(node, 0x0488B21E, 1, str, strsize); } -void hdnode_serialize_private(const HDNode *node, char *str) +void hdnode_serialize_private(const HDNode *node, char *str, int strsize) { - hdnode_serialize(node, 0x0488ADE4, 0, str); + hdnode_serialize(node, 0x0488ADE4, 0, str, strsize); } // check for validity of curve point in case of public data not performed @@ -213,7 +213,7 @@ int hdnode_deserialize(const char *str, HDNode *node) { uint8_t node_data[78]; memset(node, 0, sizeof(HDNode)); - if (!base58_decode_check(str, node_data)) { + if (!base58_decode_check(str, node_data, sizeof(node_data))) { return -1; } uint32_t version = read_be(node_data); diff --git a/bip32.h b/bip32.h index 33218b0db..131d005ae 100644 --- a/bip32.h +++ b/bip32.h @@ -49,9 +49,9 @@ int hdnode_public_ckd(HDNode *inout, uint32_t i); void hdnode_fill_public_key(HDNode *node); -void hdnode_serialize_public(const HDNode *node, char *str); +void hdnode_serialize_public(const HDNode *node, char *str, int strsize); -void hdnode_serialize_private(const HDNode *node, char *str); +void hdnode_serialize_private(const HDNode *node, char *str, int strsize); int hdnode_deserialize(const char *str, HDNode *node); diff --git a/ecdsa.c b/ecdsa.c index 9e16447fc..9de0531a2 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -417,26 +417,26 @@ void ecdsa_get_address_raw(const uint8_t *pub_key, uint8_t version, uint8_t *add ecdsa_get_pubkeyhash(pub_key, addr_raw + 1); } -void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr) +void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr, int addrsize) { uint8_t raw[21]; ecdsa_get_address_raw(pub_key, version, raw); - base58_encode_check(raw, 21, addr); + base58_encode_check(raw, 21, addr, addrsize); } -void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif) +void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif, int wifsize) { uint8_t data[34]; data[0] = version; memcpy(data + 1, priv_key, 32); - data[33 ] = 0x01; - base58_encode_check(data, 34, wif); + data[33] = 0x01; + base58_encode_check(data, 34, wif, wifsize); } int ecdsa_address_decode(const char *addr, uint8_t *out) { if (!addr) return 0; - return base58_decode_check(addr, out) == 21; + return base58_decode_check(addr, out, 21) == 21; } void uncompress_coords(uint8_t odd, const bignum256 *x, bignum256 *y) diff --git a/ecdsa.h b/ecdsa.h index 292aeaf58..9f57268f9 100644 --- a/ecdsa.h +++ b/ecdsa.h @@ -46,8 +46,8 @@ void ecdsa_get_public_key33(const uint8_t *priv_key, uint8_t *pub_key); void ecdsa_get_public_key65(const uint8_t *priv_key, uint8_t *pub_key); void ecdsa_get_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash); void ecdsa_get_address_raw(const uint8_t *pub_key, uint8_t version, uint8_t *addr_raw); -void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr); -void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif); +void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr, int addrsize); +void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif, int wifsize); int ecdsa_address_decode(const char *addr, uint8_t *out); int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub); int ecdsa_validate_pubkey(const curve_point *pub); diff --git a/tests.c b/tests.c index 91115ea1d..3f960d32e 100644 --- a/tests.c +++ b/tests.c @@ -29,6 +29,7 @@ #include "aes.h" #include "bignum.h" +#include "base58.h" #include "bip32.h" #include "bip39.h" #include "ecdsa.h" @@ -77,6 +78,85 @@ char *tohex(const uint8_t *bin, size_t l) #define ck_assert_mem_eq(X, Y, L) _ck_assert_mem(X, Y, L, ==) #define ck_assert_mem_ne(X, Y, L) _ck_assert_mem(X, Y, L, !=) +// 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, strn, sizeof(strn)); + ck_assert_int_eq(r, strlen(*str) + 1); + ck_assert_str_eq(strn, *str); + + r = base58_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 + + // test vector 1 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors START_TEST(test_bip32_vector_1) { @@ -92,11 +172,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"), 32); ck_assert_mem_eq(node.private_key, fromhex("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"), 32); ck_assert_mem_eq(node.public_key, fromhex("0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -109,11 +189,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"), 32); ck_assert_mem_eq(node.private_key, fromhex("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"), 32); ck_assert_mem_eq(node.public_key, fromhex("035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -126,11 +206,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"), 32); ck_assert_mem_eq(node.private_key, fromhex("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"), 32); ck_assert_mem_eq(node.public_key, fromhex("03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -143,11 +223,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"), 32); ck_assert_mem_eq(node.private_key, fromhex("cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"), 32); ck_assert_mem_eq(node.public_key, fromhex("0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -160,11 +240,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"), 32); ck_assert_mem_eq(node.private_key, fromhex("0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"), 32); ck_assert_mem_eq(node.public_key, fromhex("02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -177,11 +257,11 @@ START_TEST(test_bip32_vector_1) ck_assert_mem_eq(node.chain_code, fromhex("c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"), 32); ck_assert_mem_eq(node.private_key, fromhex("471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"), 32); ck_assert_mem_eq(node.public_key, fromhex("022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -205,11 +285,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"), 32); ck_assert_mem_eq(node.private_key, fromhex("4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"), 32); ck_assert_mem_eq(node.public_key, fromhex("03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -223,11 +303,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"), 32); ck_assert_mem_eq(node.private_key, fromhex("abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"), 32); ck_assert_mem_eq(node.public_key, fromhex("02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -241,11 +321,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"), 32); ck_assert_mem_eq(node.private_key, fromhex("877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"), 32); ck_assert_mem_eq(node.public_key, fromhex("03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -259,11 +339,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"), 32); ck_assert_mem_eq(node.private_key, fromhex("704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"), 32); ck_assert_mem_eq(node.public_key, fromhex("03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -277,11 +357,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"), 32); ck_assert_mem_eq(node.private_key, fromhex("f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"), 32); ck_assert_mem_eq(node.public_key, fromhex("02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -295,11 +375,11 @@ START_TEST(test_bip32_vector_2) ck_assert_mem_eq(node.chain_code, fromhex("9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"), 32); ck_assert_mem_eq(node.private_key, fromhex("bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"), 32); ck_assert_mem_eq(node.public_key, fromhex("024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"), 33); - hdnode_serialize_private(&node, str); + hdnode_serialize_private(&node, str, sizeof(str)); ck_assert_str_eq(str, "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); ck_assert_mem_eq(&node, &node2, sizeof(HDNode)); - hdnode_serialize_public(&node, str); + hdnode_serialize_public(&node, str, sizeof(str)); ck_assert_str_eq(str, "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0); memcpy(&node3, &node, sizeof(HDNode)); @@ -829,50 +909,50 @@ END_TEST START_TEST(test_address) { - char address[35]; + char address[36]; uint8_t pub_key[65]; memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "139MaMHp3Vjo8o4x8N1ZLWEtovLGvBsg6s"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mhfJsQNnrXB3uuYZqvywARTDfuvyjg4RBh"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "MxiimznnxsqMfLKTQBL8Z2PoY9jKpjgkCu"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LMNJqZbe89yrPbm7JVzrcXJf28hZ1rKPaH"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "139MaMHp3Vjo8o4x8N1ZLWEtovLGvBsg6s"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mhfJsQNnrXB3uuYZqvywARTDfuvyjg4RBh"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "MxiimznnxsqMfLKTQBL8Z2PoY9jKpjgkCu"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LMNJqZbe89yrPbm7JVzrcXJf28hZ1rKPaH"); memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "19Ywfm3witp6C1yBMy4NRYHY2347WCRBfQ"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mp4txp8vXvFLy8So5Y2kFTVrt2epN6YzdP"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "N58JsQYveGueiZDgdnNwe4SSkGTAToutAY"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LTmtvyMmoZ49SpfLY73fhZMJEFRPdyohKh"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "19Ywfm3witp6C1yBMy4NRYHY2347WCRBfQ"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mp4txp8vXvFLy8So5Y2kFTVrt2epN6YzdP"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "N58JsQYveGueiZDgdnNwe4SSkGTAToutAY"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LTmtvyMmoZ49SpfLY73fhZMJEFRPdyohKh"); memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "1FWE2bn3MWhc4QidcF6AvEWpK77sSi2cAP"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mv2BKes2AY8rqXCFKp4Yk9j9B6iaMfWRLN"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "NB5bEFH2GtoAawy8t4Qk8kfj3LWvQs3MhB"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LZjBHp5sSAwfKDQnnP5UCFaaXKV9YheGxQ"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "1FWE2bn3MWhc4QidcF6AvEWpK77sSi2cAP"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mv2BKes2AY8rqXCFKp4Yk9j9B6iaMfWRLN"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "NB5bEFH2GtoAawy8t4Qk8kfj3LWvQs3MhB"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LZjBHp5sSAwfKDQnnP5UCFaaXKV9YheGxQ"); memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "1yrZb8dhdevoqpUEGi2tUccUEeiMKeLcs"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mgVoreDcWf6BaxJ5wqgQiPpwLEFRLSr8U8"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "MwZDmEdcd1kVLP4yW62c6zmXCU3mNbveDo"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LLCopoSTnHtz4eWdQQhLAVgNgT1zTi4QBK"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "1yrZb8dhdevoqpUEGi2tUccUEeiMKeLcs"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mgVoreDcWf6BaxJ5wqgQiPpwLEFRLSr8U8"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "MwZDmEdcd1kVLP4yW62c6zmXCU3mNbveDo"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LLCopoSTnHtz4eWdQQhLAVgNgT1zTi4QBK"); memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "194SZbL75xCCGBbKtMsyWLE5r9s2V6mhVM"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "moaPreR5tydT3J4wbvrMLFSQi9TjPCiZc6"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "N4domEq61LHkniqqABCYirNzaPG5NRU8GH"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LTHPpodwAcSFWzHV4VsGnMHr4NEJajMnKX"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "194SZbL75xCCGBbKtMsyWLE5r9s2V6mhVM"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "moaPreR5tydT3J4wbvrMLFSQi9TjPCiZc6"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "N4domEq61LHkniqqABCYirNzaPG5NRU8GH"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LTHPpodwAcSFWzHV4VsGnMHr4NEJajMnKX"); memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "1A2WfBD4BJFwYHFPc5KgktqtbdJLBuVKc4"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mpYTxEJ2zKhCKPj1KeJ4ap4DTcu39T3uzD"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "N5bsrpi36gMW4pVtsteFyQzoKrhPE7nkxK"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LUFTvPWtFxVzo5wYnDJz2uueoqfcMYiuxH"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "1A2WfBD4BJFwYHFPc5KgktqtbdJLBuVKc4"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mpYTxEJ2zKhCKPj1KeJ4ap4DTcu39T3uzD"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "N5bsrpi36gMW4pVtsteFyQzoKrhPE7nkxK"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LUFTvPWtFxVzo5wYnDJz2uueoqfcMYiuxH"); memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65); - ecdsa_get_address(pub_key, 0, address); ck_assert_str_eq(address, "19J81hrPnQxg9UGx45ibTieCkb2ttm8CLL"); - ecdsa_get_address(pub_key, 111, address); ck_assert_str_eq(address, "mop5JkwNbSPvvakZmegyHdrXcadbjLazww"); - ecdsa_get_address(pub_key, 52, address); ck_assert_str_eq(address, "N4sVDMMNho4Eg1XTKu3AgEo7UpRwq3aNbn"); - ecdsa_get_address(pub_key, 48, address); ck_assert_str_eq(address, "LTX5GvADs5CjQGy7EDhtjjhxxoQB2Uhicd"); + ecdsa_get_address(pub_key, 0, address, sizeof(address)); ck_assert_str_eq(address, "19J81hrPnQxg9UGx45ibTieCkb2ttm8CLL"); + ecdsa_get_address(pub_key, 111, address, sizeof(address)); ck_assert_str_eq(address, "mop5JkwNbSPvvakZmegyHdrXcadbjLazww"); + ecdsa_get_address(pub_key, 52, address, sizeof(address)); ck_assert_str_eq(address, "N4sVDMMNho4Eg1XTKu3AgEo7UpRwq3aNbn"); + ecdsa_get_address(pub_key, 48, address, sizeof(address)); ck_assert_str_eq(address, "LTX5GvADs5CjQGy7EDhtjjhxxoQB2Uhicd"); } END_TEST @@ -932,16 +1012,16 @@ START_TEST(test_wif) char wif[53]; memcpy(priv_key, fromhex("1111111111111111111111111111111111111111111111111111111111111111"), 32); - ecdsa_get_wif(priv_key, 0x80, wif); ck_assert_str_eq(wif, "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp"); - ecdsa_get_wif(priv_key, 0xEF, wif); ck_assert_str_eq(wif, "cN9spWsvaxA8taS7DFMxnk1yJD2gaF2PX1npuTpy3vuZFJdwavaw"); + ecdsa_get_wif(priv_key, 0x80, wif, sizeof(wif)); ck_assert_str_eq(wif, "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp"); + ecdsa_get_wif(priv_key, 0xEF, wif, sizeof(wif)); ck_assert_str_eq(wif, "cN9spWsvaxA8taS7DFMxnk1yJD2gaF2PX1npuTpy3vuZFJdwavaw"); memcpy(priv_key, fromhex("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"), 32); - ecdsa_get_wif(priv_key, 0x80, wif); ck_assert_str_eq(wif, "L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN"); - ecdsa_get_wif(priv_key, 0xEF, wif); ck_assert_str_eq(wif, "cV1ysqy3XUVSsPeKeugH2Utm6ZC1EyeArAgvxE73SiJvfa6AJng7"); + ecdsa_get_wif(priv_key, 0x80, wif, sizeof(wif)); ck_assert_str_eq(wif, "L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN"); + ecdsa_get_wif(priv_key, 0xEF, wif, sizeof(wif)); ck_assert_str_eq(wif, "cV1ysqy3XUVSsPeKeugH2Utm6ZC1EyeArAgvxE73SiJvfa6AJng7"); memcpy(priv_key, fromhex("47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"), 32); - ecdsa_get_wif(priv_key, 0x80, wif); ck_assert_str_eq(wif, "KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq"); - ecdsa_get_wif(priv_key, 0xEF, wif); ck_assert_str_eq(wif, "cPzbT6tbXyJNWY6oKeVabbXwSvsN6qhTHV8ZrtvoDBJV5BRY1G5Q"); + ecdsa_get_wif(priv_key, 0x80, wif, sizeof(wif)); ck_assert_str_eq(wif, "KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq"); + ecdsa_get_wif(priv_key, 0xEF, wif, sizeof(wif)); ck_assert_str_eq(wif, "cPzbT6tbXyJNWY6oKeVabbXwSvsN6qhTHV8ZrtvoDBJV5BRY1G5Q"); } END_TEST @@ -1061,6 +1141,10 @@ Suite *test_suite(void) Suite *s = suite_create("trezor-crypto"); TCase *tc; + tc = tcase_create("base58"); + tcase_add_test(tc, test_base58); + 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);