1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 22:38:08 +00:00

Compute pubkey only on demand.

Remove fingerprint from hdnode structure (if you need it, call
hdnode_fingerprint on the parent hdnode).
Only compute public_key, when hdnode_fill_public_key is called.
This commit is contained in:
Jochen Hoenicke 2016-06-26 16:24:50 +02:00
parent 16f477787d
commit 3390fcf89e
3 changed files with 209 additions and 122 deletions

69
bip32.c
View File

@ -44,7 +44,7 @@ const curve_info ed25519_info = {
0
};
int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, 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)
{
const curve_info *info = get_curve_by_name(curve);
if (info == 0) {
@ -55,7 +55,6 @@ int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, c
}
out->curve = info;
out->depth = depth;
out->fingerprint = fingerprint;
out->child_num = child_num;
memcpy(out->chain_code, chain_code, 32);
MEMSET_BZERO(out->private_key, 32);
@ -63,7 +62,7 @@ int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, c
return 1;
}
int hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, 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)
{
bool failed = false;
const curve_info *info = get_curve_by_name(curve);
@ -88,11 +87,10 @@ int hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, uint32_t child_num, c
out->curve = info;
out->depth = depth;
out->fingerprint = fingerprint;
out->child_num = child_num;
memcpy(out->chain_code, chain_code, 32);
memcpy(out->private_key, private_key, 32);
hdnode_fill_public_key(out);
MEMSET_BZERO(out->public_key, sizeof(out->public_key));
return 1;
}
@ -101,7 +99,6 @@ int hdnode_from_seed(const uint8_t *seed, int seed_len, const char* curve, HDNod
uint8_t I[32 + 32];
memset(out, 0, sizeof(HDNode));
out->depth = 0;
out->fingerprint = 0x00000000;
out->child_num = 0;
out->curve = get_curve_by_name(curve);
if (out->curve == 0) {
@ -125,17 +122,28 @@ int hdnode_from_seed(const uint8_t *seed, int seed_len, const char* curve, HDNod
}
memcpy(out->private_key, I, 32);
memcpy(out->chain_code, I + 32, 32);
hdnode_fill_public_key(out);
MEMSET_BZERO(I, sizeof(I));
return 1;
}
uint32_t hdnode_fingerprint(HDNode *node)
{
uint8_t digest[32];
uint32_t fingerprint;
hdnode_fill_public_key(node);
sha256_Raw(node->public_key, 33, digest);
ripemd160(digest, 32, digest);
fingerprint = (digest[0] << 24) + (digest[1] << 16) + (digest[2] << 8) + digest[3];
MEMSET_BZERO(digest, sizeof(digest));
return fingerprint;
}
int hdnode_private_ckd(HDNode *inout, uint32_t i)
{
uint8_t data[1 + 32 + 4];
uint8_t I[32 + 32];
uint8_t fingerprint[32];
bignum256 a, b;
if (i & 0x80000000) { // private derivation
@ -145,14 +153,11 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i)
if (!inout->curve->params) {
return 0;
}
hdnode_fill_public_key(inout);
memcpy(data, inout->public_key, 33);
}
write_be(data + 33, i);
sha256_Raw(inout->public_key, 33, fingerprint);
ripemd160(fingerprint, 32, fingerprint);
inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3];
bn_read_be(inout->private_key, &a);
hmac_sha512(inout->chain_code, 32, data, sizeof(data), I);
@ -186,13 +191,12 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i)
memcpy(inout->chain_code, I + 32, 32);
inout->depth++;
inout->child_num = i;
hdnode_fill_public_key(inout);
MEMSET_BZERO(inout->public_key, sizeof(inout->public_key));
// making sure to wipe our memory
MEMSET_BZERO(&a, sizeof(a));
MEMSET_BZERO(&b, sizeof(b));
MEMSET_BZERO(I, sizeof(I));
MEMSET_BZERO(fingerprint, sizeof(fingerprint));
MEMSET_BZERO(data, sizeof(data));
return 1;
}
@ -214,11 +218,6 @@ int hdnode_public_ckd(HDNode *inout, uint32_t i)
memcpy(data, inout->public_key, 33);
}
write_be(data + 33, i);
sha256_Raw(inout->public_key, 33, fingerprint);
ripemd160(fingerprint, 32, fingerprint);
inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3];
memset(inout->private_key, 0, 32);
if (!ecdsa_read_pubkey(inout->curve->params, inout->public_key, &a)) {
@ -372,10 +371,18 @@ int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count)
#endif
void hdnode_get_address_raw(HDNode *node, uint8_t version, uint8_t *addr_raw)
{
hdnode_fill_public_key(node);
ecdsa_get_address_raw(node->public_key, version, addr_raw);
}
void hdnode_fill_public_key(HDNode *node)
{
if (node->public_key[0] != 0)
return;
if (node->curve == &ed25519_info) {
node->public_key[0] = 0;
node->public_key[0] = 1;
ed25519_publickey(node->private_key, node->public_key + 1);
} else {
ecdsa_get_public_key33(node->curve->params, node->private_key, node->public_key);
@ -384,9 +391,10 @@ void hdnode_fill_public_key(HDNode *node)
// msg is a data to be signed
// msg_len is the message length
int hdnode_sign(const HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby)
int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby)
{
if (node->curve == &ed25519_info) {
hdnode_fill_public_key(node);
ed25519_sign(msg, msg_len, node->private_key, node->public_key + 1, sig);
return 0;
} else {
@ -394,9 +402,10 @@ int hdnode_sign(const HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_
}
}
int hdnode_sign_digest(const HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby)
int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby)
{
if (node->curve == &ed25519_info) {
hdnode_fill_public_key(node);
ed25519_sign(digest, 32, node->private_key, node->public_key + 1, sig);
return 0;
} else {
@ -405,12 +414,12 @@ int hdnode_sign_digest(const HDNode *node, const uint8_t *digest, uint8_t *sig,
}
void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, char *str, int strsize)
void hdnode_serialize(const HDNode *node, uint32_t fpr, 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, node->fingerprint);
write_be(node_data + 5, fpr);
write_be(node_data + 9, node->child_num);
memcpy(node_data + 13, node->chain_code, 32);
if (use_public) {
@ -424,14 +433,14 @@ void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, cha
MEMSET_BZERO(node_data, sizeof(node_data));
}
void hdnode_serialize_public(const HDNode *node, char *str, int strsize)
void hdnode_serialize_public(const HDNode *node, uint32_t fpr, char *str, int strsize)
{
hdnode_serialize(node, 0x0488B21E, 1, str, strsize);
hdnode_serialize(node, fpr, 0x0488B21E, 1, str, strsize);
}
void hdnode_serialize_private(const HDNode *node, char *str, int strsize)
void hdnode_serialize_private(const HDNode *node, uint32_t fpr, char *str, int strsize)
{
hdnode_serialize(node, 0x0488ADE4, 0, str, strsize);
hdnode_serialize(node, fpr, 0x0488ADE4, 0, str, strsize);
}
// check for validity of curve point in case of public data not performed
@ -445,18 +454,18 @@ int hdnode_deserialize(const char *str, HDNode *node)
node->curve = get_curve_by_name(SECP256K1_NAME);
uint32_t version = read_be(node_data);
if (version == 0x0488B21E) { // public node
MEMSET_BZERO(node->private_key, sizeof(node->private_key));
memcpy(node->public_key, node_data + 45, 33);
} else if (version == 0x0488ADE4) { // private node
if (node_data[45]) { // invalid data
return -2;
}
memcpy(node->private_key, node_data + 46, 32);
hdnode_fill_public_key(node);
MEMSET_BZERO(node->public_key, sizeof(node->public_key));
} else {
return -3; // invalid version
}
node->depth = node_data[4];
node->fingerprint = read_be(node_data + 5);
node->child_num = read_be(node_data + 9);
memcpy(node->chain_code, node_data + 13, 32);
return 0;

19
bip32.h
View File

@ -36,7 +36,6 @@ typedef struct {
typedef struct {
uint32_t depth;
uint32_t fingerprint;
uint32_t child_num;
uint8_t chain_code[32];
uint8_t private_key[32];
@ -44,9 +43,9 @@ typedef struct {
const curve_info *curve;
} HDNode;
int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, 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 fingerprint, 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);
@ -64,19 +63,23 @@ int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count);
#endif
uint32_t hdnode_fingerprint(HDNode *node);
void hdnode_fill_public_key(HDNode *node);
int hdnode_sign(const HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby);
int hdnode_sign_digest(const HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby);
int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby);
int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby);
void hdnode_serialize_public(const HDNode *node, char *str, int strsize);
void hdnode_serialize_public(const HDNode *node, uint32_t fpr, char *str, int strsize);
void hdnode_serialize_private(const HDNode *node, char *str, int strsize);
void hdnode_serialize_private(const HDNode *node, uint32_t fpr, char *str, int strsize);
int hdnode_deserialize(const char *str, HDNode *node);
// Private
void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, char *str, int strsize);
void hdnode_serialize(const HDNode *node, uint32_t fpr, uint32_t version, char use_public, char *str, int strsize);
void hdnode_get_address_raw(HDNode *node, uint8_t version, uint8_t *addr_raw);
const curve_info *get_curve_by_name(const char *curve_name);

243
tests.c
View File

@ -166,6 +166,7 @@ END_TEST
START_TEST(test_bip32_vector_1)
{
HDNode node, node2, node3;
uint32_t fingerprint;
char str[112];
int r;
@ -173,15 +174,18 @@ START_TEST(test_bip32_vector_1)
hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, SECP256K1_NAME, &node);
// [Chain m]
ck_assert_int_eq(node.fingerprint, 0x00000000);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, 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);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -189,16 +193,19 @@ START_TEST(test_bip32_vector_1)
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(node.fingerprint, 0x3442193e);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -206,16 +213,19 @@ START_TEST(test_bip32_vector_1)
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(node.fingerprint, 0x5c1bd648);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -223,16 +233,19 @@ START_TEST(test_bip32_vector_1)
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(node.fingerprint, 0xbef5a2f9);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -240,16 +253,19 @@ START_TEST(test_bip32_vector_1)
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(node.fingerprint, 0xee7ab90c);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -257,16 +273,19 @@ START_TEST(test_bip32_vector_1)
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(node.fingerprint, 0xd880d7d8);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -279,6 +298,7 @@ END_TEST
START_TEST(test_bip32_vector_2)
{
HDNode node, node2, node3;
uint32_t fingerprint;
char str[112];
int r;
@ -286,15 +306,18 @@ START_TEST(test_bip32_vector_2)
hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, SECP256K1_NAME, &node);
// [Chain m]
ck_assert_int_eq(node.fingerprint, 0x00000000);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -302,17 +325,20 @@ START_TEST(test_bip32_vector_2)
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(node.fingerprint, 0xbd16bee5);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -320,17 +346,20 @@ START_TEST(test_bip32_vector_2)
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(node.fingerprint, 0x5a61ff8e);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -338,17 +367,20 @@ START_TEST(test_bip32_vector_2)
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(node.fingerprint, 0xd8ab4937);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -356,17 +388,20 @@ START_TEST(test_bip32_vector_2)
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(node.fingerprint, 0x78412e3a);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -374,17 +409,20 @@ START_TEST(test_bip32_vector_2)
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(node.fingerprint, 0x31a507b8);
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, str, sizeof(str));
hdnode_serialize_private(&node, fingerprint, str, sizeof(str));
ck_assert_str_eq(str, "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j");
r = hdnode_deserialize(str, &node2); ck_assert_int_eq(r, 0);
hdnode_fill_public_key(&node2);
ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
hdnode_serialize_public(&node, str, sizeof(str));
hdnode_serialize_public(&node, fingerprint, 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));
@ -396,11 +434,13 @@ START_TEST(test_bip32_vector_2)
// 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(node.fingerprint, 0xbd16bee5);
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
@ -411,21 +451,22 @@ START_TEST(test_bip32_compare)
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.fingerprint, node2.fingerprint);
ck_assert_int_eq(node1.fingerprint, node3.fingerprint);
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);
}
@ -512,18 +553,18 @@ START_TEST(test_bip32_nist_seed)
hdnode_from_seed(fromhex("a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446"), 32, NIST256P1_NAME, &node);
// [Chain m]
ck_assert_int_eq(node.fingerprint, 0x00000000);
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_int_eq(node.fingerprint, 0x00000000);
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
@ -531,49 +572,62 @@ 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]
ck_assert_int_eq(node.fingerprint, 0x00000000);
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(node.fingerprint, 0xbe6105b5);
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(node.fingerprint, 0x9b02312f);
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(node.fingerprint, 0xb98005c1);
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(node.fingerprint, 0x0e9f3274);
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(node.fingerprint, 0x8b2b5c4b);
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
@ -581,55 +635,68 @@ 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]
ck_assert_int_eq(node.fingerprint, 0x00000000);
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(node.fingerprint, 0x607f628f);
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(node.fingerprint, 0x946d2a54);
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(node.fingerprint, 0x218182d8);
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(node.fingerprint, 0x931223e4);
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(node.fingerprint, 0x956c4629);
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
@ -637,9 +704,10 @@ START_TEST(test_bip32_nist_vector_2)
// 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(node.fingerprint, 0x607f628f);
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);
@ -652,21 +720,22 @@ START_TEST(test_bip32_nist_compare)
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.fingerprint, node2.fingerprint);
ck_assert_int_eq(node1.fingerprint, node3.fingerprint);
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);
}
@ -676,33 +745,39 @@ 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']
// [Chain m/28578']
fingerprint = hdnode_fingerprint(&node);
r = hdnode_private_ckd_prime(&node, 28578);
ck_assert_int_eq(r, 1);
ck_assert_int_eq(node.fingerprint, 0xbe6105b5);
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(node2.fingerprint, 0x3e2b7bc6);
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));
memset(&node2.private_key, 0, 32);
r = hdnode_public_ckd(&node2, 33941);
ck_assert_int_eq(r, 1);
ck_assert_int_eq(node2.fingerprint, 0x3e2b7bc6);
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
@ -716,45 +791,45 @@ START_TEST(test_bip32_ed25519_vector_1)
hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16, ED25519_NAME, &node);
// [Chain m]
ck_assert_int_eq(node.fingerprint, 0x00000000);
ck_assert_mem_eq(node.chain_code, fromhex("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"), 32);
ck_assert_mem_eq(node.private_key, fromhex("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"), 32);
ck_assert_mem_eq(node.public_key, fromhex("00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"), 33);
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_int_eq(node.fingerprint, 0xddebc675);
ck_assert_mem_eq(node.chain_code, fromhex("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"), 32);
ck_assert_mem_eq(node.private_key, fromhex("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"), 32);
ck_assert_mem_eq(node.public_key, fromhex("008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"), 33);
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_int_eq(node.fingerprint, 0x13dab143);
ck_assert_mem_eq(node.chain_code, fromhex("a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14"), 32);
ck_assert_mem_eq(node.private_key, fromhex("b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2"), 32);
ck_assert_mem_eq(node.public_key, fromhex("001932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187"), 33);
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_int_eq(node.fingerprint, 0xebe4cb29);
ck_assert_mem_eq(node.chain_code, fromhex("2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c"), 32);
ck_assert_mem_eq(node.private_key, fromhex("92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9"), 32);
ck_assert_mem_eq(node.public_key, fromhex("00ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1"), 33);
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_int_eq(node.fingerprint, 0x316ec1c6);
ck_assert_mem_eq(node.chain_code, fromhex("8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc"), 32);
ck_assert_mem_eq(node.private_key, fromhex("30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662"), 32);
ck_assert_mem_eq(node.public_key, fromhex("008abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c"), 33);
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_int_eq(node.fingerprint, 0xd6322ccd);
ck_assert_mem_eq(node.chain_code, fromhex("68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"), 32);
ck_assert_mem_eq(node.private_key, fromhex("8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"), 32);
ck_assert_mem_eq(node.public_key, fromhex("003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"), 33);
hdnode_fill_public_key(&node);
ck_assert_mem_eq(node.public_key, fromhex("013c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"), 33);
}
END_TEST
@ -768,50 +843,50 @@ START_TEST(test_bip32_ed25519_vector_2)
hdnode_from_seed(fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"), 64, ED25519_NAME, &node);
// [Chain m]
ck_assert_int_eq(node.fingerprint, 0x00000000);
ck_assert_mem_eq(node.chain_code, fromhex("ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b"), 32);
ck_assert_mem_eq(node.private_key, fromhex("171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012"), 32);
ck_assert_mem_eq(node.public_key, fromhex("008fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a"), 33);
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_int_eq(node.fingerprint, 0x31981b50);
ck_assert_mem_eq(node.chain_code, fromhex("0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d"), 32);
ck_assert_mem_eq(node.private_key, fromhex("1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635"), 32);
ck_assert_mem_eq(node.public_key, fromhex("0086fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037"), 33);
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_int_eq(node.fingerprint, 0x1e9411b1);
ck_assert_mem_eq(node.chain_code, fromhex("138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f"), 32);
ck_assert_mem_eq(node.private_key, fromhex("ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4"), 32);
ck_assert_mem_eq(node.public_key, fromhex("005ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d"), 33);
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_int_eq(node.fingerprint, 0xfcadf38c);
ck_assert_mem_eq(node.chain_code, fromhex("73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90"), 32);
ck_assert_mem_eq(node.private_key, fromhex("3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c"), 32);
ck_assert_mem_eq(node.public_key, fromhex("002e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45"), 33);
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_int_eq(node.fingerprint, 0xaca70953);
ck_assert_mem_eq(node.chain_code, fromhex("0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a"), 32);
ck_assert_mem_eq(node.private_key, fromhex("5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72"), 32);
ck_assert_mem_eq(node.public_key, fromhex("00e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b"), 33);
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_int_eq(node.fingerprint, 0x422c654b);
ck_assert_mem_eq(node.chain_code, fromhex("5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4"), 32);
ck_assert_mem_eq(node.private_key, fromhex("551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d"), 32);
ck_assert_mem_eq(node.public_key, fromhex("0047150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0"), 33);
hdnode_fill_public_key(&node);
ck_assert_mem_eq(node.public_key, fromhex("0147150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0"), 33);
}
END_TEST