BIP32 hierarchical deterministic (HD) key derivation for Node.js and the browser. Generate and manage entire key hierarchies from a single master seed using the Bitcoin Improvement Proposal 32 standard.
- BIP32 Standard: Full compliance with BIP32 specification
- Full TypeScript support: Includes complete type definitions
- Master seed derivation: Create unlimited key hierarchies from a single seed
- Key path derivation: Support for both hardened and normal derivation paths
- Extended keys: Support for xprv and xpub extended key formats
- Cryptographic operations: Sign and verify with derived keys
- Cross-platform: Node.js and browser compatible
npm install @hyperbitjs/hdkeyimport { HDKey } from '@hyperbitjs/hdkey';
import { randomBytes } from 'crypto';
// Create from master seed (commonly from BIP39 mnemonic)
const seed = randomBytes(64);
const masterKey = HDKey.fromMasterSeed(seed);
// Access extended keys
console.log(masterKey.privateExtendedKey); // xprv...
console.log(masterKey.publicExtendedKey); // xpub...
// Derive a BIP44 path (Bitcoin account 0, address 0)
const accountKey = masterKey.derive("m/44'/0'/0'");
const changeKey = accountKey.derive('m/0/0');
// Get the key pair
console.log(changeKey.privateKey); // Buffer (32 bytes)
console.log(changeKey.publicKey); // Buffer (33 bytes compressed)Creates an HDKey from a master seed buffer. The seed should be 64 bytes (512 bits).
const seed = randomBytes(64);
const hdkey = HDKey.fromMasterSeed(seed);
console.log(hdkey.privateExtendedKey); // xprv...Creates an HDKey from an extended key string (xprv or xpub). Useful for importing previously generated keys.
const xprv = 'xprv9s21ZrQH143K3...';
const hdkey = HDKey.fromExtendedKey(xprv);
const xpub = 'xpub661MyMwAqRbc...';
const publicKey = HDKey.fromExtendedKey(xpub);Creates an HDKey from a JSON object previously created with toJSON().
const hdkey = HDKey.fromMasterSeed(seed);
const json = hdkey.toJSON();
const hdkey2 = HDKey.fromJSON(json);Derives a child key at the specified BIP32 path from the current key. Supports both hardened (') and normal paths.
const masterKey = HDKey.fromMasterSeed(seed);
// Standard derivation (account-level)
const accountKey = masterKey.derive("m/44'/0'/0'");
// Further derivation (address-level)
const addressKey = accountKey.derive('m/0/0');
// Complete BIP44 path in one call
const finalKey = masterKey.derive("m/44'/0'/0'/0/0");Common BIP44 paths:
m/44'/0'/0'/0/0- Bitcoin mainnet, first addressm/44'/60'/0'/0/0- Ethereum mainnet, first addressm/44'/1'/0'/0/0- Bitcoin testnet, first address
Signs a message hash with the private key. Returns a signature buffer.
const { createHash } = require('crypto');
const message = Buffer.from('Sign this message');
const hash = createHash('sha256').update(message).digest();
const signature = hdkey.sign(hash);Verifies a signature against the public key. Returns true if valid.
const isValid = hdkey.verify(hash, signature);Securely wipes the private key from memory. After calling this, the key will only contain public information (xpub).
const hdkey = HDKey.fromMasterSeed(seed);
hdkey.wipePrivateData();
// Now hdkey.privateKey is undefinedSerializes the key to a JSON-compatible object.
const json = hdkey.toJSON();
// { xpriv: 'xprv...', xpub: 'xpub...' }privateKey: Buffer- The 32-byte private keypublicKey: Buffer- The 33-byte compressed public keychainCode: Buffer- The 32-byte chain codeprivateExtendedKey: string- The xprv stringpublicExtendedKey: string- The xpub stringfingerprint: Buffer- The 4-byte key fingerprint
import { HDKey } from '@hyperbitjs/hdkey';
import { randomBytes } from 'crypto';
// Create master key from BIP39 seed
const seed = randomBytes(64);
const master = HDKey.fromMasterSeed(seed);
// Derive Bitcoin mainnet account 0
const bitcoin = master.derive("m/44'/0'/0'");
// Generate 5 addresses from this account
for (let i = 0; i < 5; i++) {
const address = bitcoin.derive(`m/0/${i}`);
console.log(`Address ${i}:`, address.publicKey.toString('hex'));
}// Create a public-key-only wallet (air-gapped)
const xpub = 'xpub661MyMwAqRbcF...';
const publicKey = HDKey.fromExtendedKey(xpub);
// Can derive child keys (public derivation only)
const address = publicKey.derive('m/0/0');
console.log(address.publicKey); // Works!
console.log(address.privateKey); // undefinedimport { createHash } from 'crypto';
const message = Buffer.from('Verify my identity');
const hash = createHash('sha256').update(message).digest();
// Sign with derived key
const signature = addressKey.sign(hash);
// Verify with the same key
const isValid = addressKey.verify(hash, signature);
console.log('Signature valid:', isValid);export interface IHDKey {
privateKey?: Buffer;
publicKey: Buffer;
chainCode: Buffer;
fingerprint: Buffer;
privateExtendedKey?: string;
publicExtendedKey: string;
derive(path: string): HDKey;
sign(hash: Buffer): Buffer;
verify(hash: Buffer, signature: Buffer): boolean;
wipePrivateData(): void;
toJSON(): { xpriv?: string; xpub: string };
}This library works in modern browsers. Use a bundler like Webpack, Vite, or Rollup:
<script type="module">
import { HDKey } from 'https://cdn.jsdelivr.net/npm/@hyperbitjs/hdkey/dist/index.mjs';
const xpub = 'xpub...';
const key = HDKey.fromExtendedKey(xpub);
</script>- Private key handling: Never expose private keys or xprv strings
- Key storage: Store xprv only in encrypted form
- Public-only wallets: Use xpub for watch-only wallets in untrusted environments
- Hardened derivation: Use hardened paths (
') for account-level keys - Wipe data: Use
wipePrivateData()when done with private keys
Contributions are welcome! Please read our CONTRIBUTING guide first.
# Install dependencies
npm install
# Run tests
npm run test
# Type checking
npm run type-check
# Linting
npm run lint
# Build
npm run build
# Format code
npm run formatMIT © Hyperbit
- @hyperbitjs/eckey - Elliptic curve cryptography
- @hyperbitjs/mnemonic - BIP39 seed phrases
- @hyperbitjs/chains - Blockchain network definitions
For issues, questions, or suggestions:
- Open an issue on GitHub
- Check existing documentation and examples
- Review our CHANGELOG for version history
This project lives at hdkey and is part of the broader multi-project workspace.
Description: Bitcoin BIP32 hierarchical deterministic keys
- Deliver the core capability owned by this project.
- Provide stable commands and interfaces for other apps/packages in the workspace.
- Keep implementation details localized so changes stay maintainable.
- Type: Project
- Package manager metadata source:
package.json - Runtime entry hints:
./dist/index.cjs
- Install dependencies from this directory:
npm install- Run key scripts as needed (see script table below).
| Script | Command |
|---|---|
build |
vite build |
build:watch |
vite build --watch |
dev |
vite build --watch |
type-check |
tsc --noEmit |
lint |
eslint . --max-warnings 0 |
lint:fix |
eslint . --fix |
format |
prettier --write . |
format:check |
prettier --check . |
test |
vitest --run |
test:watch |
vitest |
test:coverage |
vitest --coverage |
validate |
npm run type-check && npm run lint && npm run test |
prepublishOnly |
npm run build && npm run validate |
bs58check:^2.1.2hash.js:^1.1.7secp256k1:^5.0.1
@types/node:^20.10.0@typescript-eslint/eslint-plugin:^6.21.0@typescript-eslint/parser:^6.21.0@vitest/coverage-v8:^1.1.0eslint:^8.56.0prettier:^3.0.3secure-random:^1.1.1typescript:^5.3.3vite:^5.0.11vitest:^1.1.3
- Primary config source:
package.json - No
.env.exampledetected in this directory. - Add project-specific operational notes to
MEMORY_BANK.md.
- Make changes in focused modules.
- Run the smallest relevant script/test first.
- Run full validation scripts before merging.
- Update this README and memory bank whenever behavior/contracts change.
- Prefer script-driven checks from the table above (for example:
test,build,lint). - If this project has no tests yet, add smoke checks and document them in
MEMORY_BANK.md.
When using an LLM coding assistant in this folder, always include:
- Exact target file paths and expected behavior changes.
- Validation command(s) run after edits.
- Runtime/config assumptions (.env, API keys, ports, external services).
See MEMORY_BANK.md for operational context, commands, and troubleshooting notes.