BCW_API hd_private_key hd_private_key::generate_private_key(uint32_t i) const { if (!valid_) return hd_private_key(); data_chunk data; data.reserve(33 + 4); if (first_hardened_key <= i) { data.push_back(0x00); extend_data(data, k_); extend_data(data, to_big_endian(i)); } else { extend_data(data, K_); extend_data(data, to_big_endian(i)); } auto I = split(hmac_sha512_hash(data, to_data_chunk(c_))); // The child key ki is (parse256(IL) + kpar) mod n: ec_secret ki = k_; if (!ec_add(ki, I.L)) return hd_private_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_private_key(ki, I.R, lineage); }
hd_private_key hd_private_key::generate_private_key(uint32_t i) const { if (!valid_) return hd_private_key(); data_chunk data; if (first_hardened_key <= i) data = build_data({to_byte(0x00), k_, to_big_endian(i)}); else data = build_data({K_, to_big_endian(i)}); const auto I = split(hmac_sha512_hash(data, c_)); // The child key ki is (parse256(IL) + kpar) mod n: ec_secret ki = k_; if (!ec_add(ki, I.L)) return hd_private_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_private_key(ki, I.R, lineage); }
BCW_API hd_public_key hd_public_key::generate_public_key(uint32_t i) const { if (!valid_) return hd_private_key(); if (first_hardened_key <= i) return hd_public_key(); data_chunk data; data.reserve(33 + 4); extend_data(data, K_); extend_data(data, to_big_endian(i)); auto I = split(hmac_sha512_hash(data, to_data_chunk(c_))); // The returned child key Ki is point(parse256(IL)) + Kpar. ec_point Ki = K_; if (!ec_tweak_add(Ki, I.L)) return hd_public_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_public_key(Ki, I.R, lineage); }
BCW_API hd_private_key::hd_private_key(const data_chunk& seed, bool testnet) : hd_public_key() { std::string key("Bitcoin seed"); split_long_hash I = split(hmac_sha512_hash(seed, to_data_chunk(key))); // The key is invalid if parse256(IL) >= n or 0: if (!verify_private_key(I.L)) return; auto lineage = hd_key_lineage{testnet, 0, 0, 0}; *this = hd_private_key(I.L, I.R, lineage); }
hd_public_key hd_public_key::generate_public_key(uint32_t i) const { if (!valid_) return hd_private_key(); if (first_hardened_key <= i) return hd_public_key(); auto data = build_data({K_, to_big_endian(i)}); const auto I = split(hmac_sha512_hash(data, c_)); // The returned child key Ki is point(parse256(IL)) + Kpar. ec_point Ki = K_; if (!ec_add(Ki, I.L)) return hd_public_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_public_key(Ki, I.R, lineage); }