UNPKG

j-bitcoin

Version:

Comprehensive JavaScript cryptocurrency wallet library for Bitcoin (BTC), Bitcoin Cash (BCH), and Bitcoin SV (BSV) with custodial and non-custodial wallet support, threshold signatures, and multiple address formats

232 lines (194 loc) 10.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: src/BIP32/fromSeed.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: src/BIP32/fromSeed.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * @fileoverview BIP32 master key generation from seed * * This module implements the BIP32 specification for generating master private and public keys * from a cryptographic seed. It creates the root of the hierarchical deterministic key tree * that can be used to derive all subsequent child keys deterministically. * * @see {@link https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets} * @see {@link https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki|BIP39 - Mnemonic code for generating deterministic keys} * @author yfbsei * @version 1.0.0 */ import { createHmac } from 'node:crypto'; import { Buffer } from 'node:buffer'; import { hdKey } from '../utilities/encodeKeys.js'; import { secp256k1 } from '@noble/curves/secp256k1'; /** * @typedef {Object} HDKeyPair * @property {string} HDpri - Extended private key in xprv format (Base58Check encoded) * @property {string} HDpub - Extended public key in xpub format (Base58Check encoded) */ /** * @typedef {Object} PrivateKeyInfo * @property {Buffer} key - 32-byte private key material * @property {number} versionByteNum - Version byte for WIF encoding (0x80 mainnet, 0xef testnet) */ /** * @typedef {Object} PublicKeyInfo * @property {Buffer} key - 33-byte compressed public key * @property {Point} points - Elliptic curve point representation for cryptographic operations */ /** * @typedef {Object} SerializationFormat * @property {Object} versionByte - Network-specific version bytes for key serialization * @property {number} versionByte.pubKey - Version for extended public key (xpub/tpub) * @property {number} versionByte.privKey - Version for extended private key (xprv/tprv) * @property {number} depth - Key depth in the derivation tree (0 for master) * @property {Buffer} parentFingerPrint - 4-byte fingerprint of parent key (all zeros for master) * @property {number} childIndex - Child key index (0 for master) * @property {Buffer} chainCode - 32-byte chain code for HMAC operations * @property {PrivateKeyInfo} privKey - Master private key information * @property {PublicKeyInfo} pubKey - Master public key information */ /** * @typedef {Array} MasterKeyResult * @description Array containing the HD key pair and internal serialization format * @property {HDKeyPair} 0 - HD key pair with HDpri and HDpub * @property {SerializationFormat} 1 - Internal serialization format */ /** * Generates BIP32 master keys from a cryptographic seed * * This function implements the BIP32 master key generation algorithm: * * 1. **HMAC-SHA512 Computation**: Uses "Bitcoin seed" as HMAC key and input seed as data * 2. **Key Material Split**: Divides 512-bit result into 256-bit private key (IL) and 256-bit chain code (IR) * 3. **Validation**: Ensures IL is valid (non-zero and less than curve order) * 4. **Public Key Derivation**: Computes corresponding compressed public key * 5. **Serialization**: Creates extended key format with network-specific version bytes * * The master keys serve as the root of the entire HD key tree, allowing deterministic * derivation of billions of child keys while maintaining mathematical relationships * between them for features like watch-only wallets and audit capabilities. * * @function * @param {string} seed - Hex-encoded cryptographic seed (typically 128-512 bits from BIP39) * @param {string} [net='main'] - Network type: 'main' for Bitcoin mainnet, 'test' for testnet * @returns {MasterKeyResult} Tuple containing [HD key pair, serialization format] * * @throws {Error} If seed results in invalid private key (extremely rare: ~1 in 2^127) * @throws {Error} If seed is not valid hexadecimal * @throws {Error} If network parameter is not recognized * * @example * // Generate master keys from BIP39 seed * const seed = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; * const [hdKeys, format] = fromSeed(seed, "main"); * * console.log(hdKeys.HDpri); * // "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" * * console.log(hdKeys.HDpub); * // "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" * * @example * // Generate testnet master keys * const [testKeys, testFormat] = fromSeed(seed, "test"); * console.log(testKeys.HDpri.substring(0, 4)); // "tprv" (testnet prefix) * console.log(testKeys.HDpub.substring(0, 4)); // "tpub" (testnet prefix) * * @example * // Use with BIP39 mnemonic-derived seed * import { bip39 } from '../BIP39/bip39.js'; * const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; * const bip39Seed = bip39.mnemonic2seed(mnemonic, "passphrase"); * const [masterKeys, _] = fromSeed(bip39Seed, "main"); * * @example * // Access internal key material for advanced operations * const [_, format] = fromSeed(seed, "main"); * console.log(format.privKey.key.toString('hex')); // Raw 32-byte private key * console.log(format.pubKey.key.toString('hex')); // Compressed 33-byte public key * console.log(format.chainCode.toString('hex')); // Chain code for child derivation * * @security * **Critical Security Considerations:** * - Seed must be generated with cryptographically secure randomness * - Seed should be at least 128 bits (16 bytes) for adequate security * - Store seed securely; anyone with the seed can derive all keys * - Consider using BIP39 for human-readable seed backup * - Never transmit raw seed over insecure channels * * @performance * **Performance Notes:** * - HMAC-SHA512 computation: ~0.1ms on modern hardware * - Public key derivation: ~1-2ms using elliptic curve operations * - Total function execution: ~2-3ms typically * - Results should be cached for applications requiring frequent access */ const fromSeed = (seed, net = 'main') => { // Convert hex-encoded seed to buffer for cryptographic operations seed = Buffer.from(seed, 'hex'); // Generate 512-bit HMAC using "Bitcoin seed" as key (BIP32 specification) const hashHmac = createHmac('sha512', Buffer.from("Bitcoin seed")).update(seed).digest(); // Split HMAC result: first 256 bits = private key, last 256 bits = chain code const [IL, IR] = [hashHmac.slice(0, 32), hashHmac.slice(32, 64)]; // Create master key serialization format according to BIP32 const serialization_format = { // Network-specific version bytes for extended key serialization versionByte: { pubKey: net === 'main' ? 0x0488b21e : 0x043587cf, // xpub/tpub magic bytes privKey: net === 'main' ? 0x0488ade4 : 0x04358394 // xprv/tprv magic bytes }, // Master key always has depth 0 (root of tree) depth: 0x00, // Master key has no parent, so fingerprint is all zeros parentFingerPrint: Buffer.from([0, 0, 0, 0]), // Master key index is always 0 childIndex: 0x00000000, // Chain code from HMAC (used for child key derivation) chainCode: IR, // Master private key information privKey: { key: IL, // 32-byte private key from HMAC versionByteNum: net === 'main' ? 0x80 : 0xef // WIF version byte }, // Master public key information pubKey: { key: Buffer.from(secp256k1.getPublicKey(IL, true)), // Compressed public key (33 bytes) points: secp256k1.ProjectivePoint.fromPrivateKey(IL) // Elliptic curve point for operations } }; // Return both user-friendly HD keys and internal format for further operations return [ { HDpri: hdKey('pri', serialization_format), // Extended private key (xprv/tprv) HDpub: hdKey('pub', serialization_format), // Extended public key (xpub/tpub) }, serialization_format // Internal format for child key derivation ]; } export default fromSeed;</code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Namespaces</h3><ul><li><a href="AddressFormats.html">AddressFormats</a></li><li><a href="BECH32.html">BECH32</a></li><li><a href="BIP32.html">BIP32</a></li><li><a href="BIP39.html">BIP39</a></li><li><a href="CASH_ADDR.html">CASH_ADDR</a></li><li><a href="ECDSA.html">ECDSA</a></li><li><a href="KeyDecoding.html">KeyDecoding</a></li><li><a href="Signatures.html">Signatures</a></li><li><a href="ThresholdCrypto.html">ThresholdCrypto</a></li><li><a href="Utilities.html">Utilities</a></li><li><a href="Wallets.html">Wallets</a></li><li><a href="schnorr_sig.html">schnorr_sig</a></li></ul><h3>Classes</h3><ul><li><a href="Custodial_Wallet.html">Custodial_Wallet</a></li><li><a href="Non_Custodial_Wallet.html">Non_Custodial_Wallet</a></li><li><a href="Polynomial.html">Polynomial</a></li><li><a href="ThresholdSignature.html">ThresholdSignature</a></li></ul><h3>Global</h3><ul><li><a href="global.html#CHARSET">CHARSET</a></li><li><a href="global.html#FEATURES">FEATURES</a></li><li><a href="global.html#NETWORKS">NETWORKS</a></li><li><a href="global.html#address">address</a></li><li><a href="global.html#b58encode">b58encode</a></li><li><a href="global.html#base32_encode">base32_encode</a></li><li><a href="global.html#derive">derive</a></li><li><a href="global.html#fromSeed">fromSeed</a></li><li><a href="global.html#hdKey">hdKey</a></li><li><a href="global.html#legacyAddress_decode">legacyAddress_decode</a></li><li><a href="global.html#privateKey_decode">privateKey_decode</a></li><li><a href="global.html#rmd160">rmd160</a></li><li><a href="global.html#standardKey">standardKey</a></li><li><a href="global.html#table">table</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Jun 04 2025 02:36:39 GMT-0400 (Eastern Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>