HD keys (BIP32)
Hierarchical deterministic (HD) keys derive a whole tree of key pairs from a single seed. A wallet only needs
to back up that one secret, and can still use a fresh Address for every payment. Bitcoin4J’s HD code is
BitcoinJ’s, unchanged. We use DeterministicKey for a node of the tree, HDKeyDerivation for deriving, and
DeterministicHierarchy for walking paths. The HD keys appendix
explains the scheme.
The examples use the seed of BIP32 test vector 1, so you can check the results against the specification.
Creating a master key
Section titled “Creating a master key”byte[] seed = Utils.HEX.decode("000102030405060708090a0b0c0d0e0f");DeterministicKey master = HDKeyDerivation.createMasterPrivateKey(seed);
String xprv = master.serializePrivB58(NetworkType.MAIN);String xpub = master.serializePubB58(NetworkType.MAIN);The seed is usually the output of a mnemonic. serializePrivB58() and
serializePubB58() give us the xprv and xpub strings for NetworkType.MAIN, and tprv and tpub for
the test networks.
Deriving children
Section titled “Deriving children”HDKeyDerivation.deriveChildKey() derives one level at a time. A ChildNumber is an index plus a hardened
flag.
// m/0H/1 is a hardened child, followed by a normal child.DeterministicKey account = HDKeyDerivation.deriveChildKey(master, new ChildNumber(0, true));DeterministicKey child = HDKeyDerivation.deriveChildKey(account, new ChildNumber(1, false));
String path = child.getPathAsString();Deriving by path
Section titled “Deriving by path”DeterministicHierarchy derives a full path in one call, and caches the keys along the way.
// Paths mark the hardened steps with H (or with ').DeterministicHierarchy hierarchy = new DeterministicHierarchy(master);DeterministicKey key = hierarchy.get(HDPath.parsePath("m/0H/1/2H/2"), false, true);In the preceding example the arguments after the path are:
relativePath, wherefalsemeans the path starts at the root,create, wheretruemeans we derive any keys that are not cached yet.
HDPath.parsePath() accepts either marker for a hardened step: H, as in m/44H/0H/0H/0/0, or the apostrophe
used by most wallets, and by BIP44 itself.
// The apostrophe that BIP44 and most wallets use marks a hardened step too.assertEquals(HDPath.parsePath("m/44H/0H/0H"), HDPath.parsePath("m/44'/0'/0'"));Deriving watch-only keys
Section titled “Deriving watch-only keys”An extended Public Key derives the public half of every non-hardened child. This means a server can
generate receiving Addresses from an account xpub without ever holding a Private Key.
// A server holding only the account xpub can derive receiving keys, but cannot sign.DeterministicKey watchOnly = DeterministicKey.deserializeB58(accountXpub, NetworkType.MAIN);DeterministicKey receiving = HDKeyDerivation.deriveChildKey(watchOnly, new ChildNumber(1, false));
boolean canSign = receiving.hasPrivKey();Do note that deriving a hardened child from a public-only key throws
IllegalArgumentException.
Using a derived key
Section titled “Using a derived key”A DeterministicKey is an ECKey, so it converts directly into the key types the rest of the library takes.
// A DeterministicKey is an ECKey, so it wraps into the key types the rest of the library uses.PrivateKey privateKey = new PrivateKey(child, true, NetworkType.MAIN);PublicKey publicKey = PublicKey.fromBytes(child.getPubKey());Address address = Address.fromKey(NetworkAddressType.MAIN_PKH, publicKey);deserializeB58(xprv, network) reads a private extended key back in, in the same way as the xpub above.

