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); node_data[4] = node->depth; write_be(node_data + 5, node->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); } base58_encode_check(node_data, 78, str, strsize); }
/* nb. block is general workspace. */ static void add_aad(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK], const uint8_t *header, size_t nheader) { assert(nheader <= 0xffffffff); /* we don't support 64 bit lengths. */ /* Add length using stupidly complicated rules. */ if (nheader < 0xff00) { write_be(block, nheader, 2); cf_cbcmac_stream_update(cm, block, 2); } else { write_be(block, 0xfffe, 2); write_be(block + 2, nheader, 4); cf_cbcmac_stream_update(cm, block, 6); } cf_cbcmac_stream_update(cm, header, nheader); zero_pad(cm); }
int hdnode_public_ckd(HDNode *inout, uint32_t i) { uint8_t data[1 + 32 + 4]; uint8_t I[32 + 32]; uint8_t fingerprint[32]; curve_point a, b; bignum256 c; if (i & 0x80000000) { // private derivation return 0; } else { // public derivation 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->public_key, &a)) { return 0; } hmac_sha512(inout->chain_code, 32, data, sizeof(data), I); memcpy(inout->chain_code, I + 32, 32); bn_read_be(I, &c); if (!bn_is_less(&c, &order256k1)) { // >= order return 0; } scalar_multiply(&c, &b); // b = c * G point_add(&a, &b); // b = a + b #if USE_PUBKEY_VALIDATE if (!ecdsa_validate_pubkey(&b)) { return 0; } #endif inout->public_key[0] = 0x02 | (b.y.val[0] & 0x01); bn_write_be(&b.x, inout->public_key + 1); inout->depth++; inout->child_num = i; return 1; }
static void add_block0(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK], size_t nblock, const uint8_t *nonce, size_t nnonce, size_t L, size_t nplain, size_t nheader, size_t ntag) { /* Construct first block B_0. */ block[0] = ((nheader == 0) ? 0x00 : CCM_ADATA_PRESENT) | ((ntag - 2) / 2) << 3 | (L - 1); memcpy(block + 1, nonce, nnonce); write_be(block + 1 + nnonce, nplain, L); cf_cbcmac_stream_update(cm, block, nblock); }
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 data[0] = 0; memcpy(data + 1, inout->private_key, 32); } else { // public derivation 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); memcpy(inout->chain_code, I + 32, 32); memcpy(inout->private_key, I, 32); bn_read_be(inout->private_key, &b); if (!bn_is_less(&b, &order256k1)) { // >= order return 0; } bn_addmod(&a, &b, &order256k1); if (bn_is_zero(&a)) { return 0; } inout->depth++; inout->child_num = i; bn_write_be(&a, inout->private_key); hdnode_fill_public_key(inout); return 1; }