§ 04 · Keys & addresses
Extended keys
A key plus a chain code, which together grow a whole tree
On this page 6 sections
An extended keyExtended key: A key plus extra data (a chain code) that lets you derive a family of child keys from it. Pearl mainnet writes them starting with zprv (private) and zpub (public). is a key that can have children. It carries the key itself plus 32 extra bytes, the chain codeChain code: The extra 32 bytes that travel with every key in an HD wallet. Child keys need the key and the chain code, so a public key alone is not enough to find its children., and with both you can compute a whole family of related keys.
That’s how one 12-word backup covers thousands of addresses. The seed makes one master extended key. The master makes children, the children make grandchildren, and each address sits at a fixed spot in that tree. Pearl writes these keys as zprv (private) and zpub (public).
Try it
Type a phrase and watch the master key, the account key and the first addresses appear.
How is the master key made?
With one HMAC. The seed from the 12 words is hashed with HMAC-SHA512, using a fixed key, and the 64-byte result is cut in half:
Yes, the key is still the text “Bitcoin seed”. Pearl kept BIP-32’s constant unchanged. For the standard test phrase “abandon … about”:
| Value | |
|---|---|
| Seed | 5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4 |
| Master private key k (left half) | 1837c1be8e2995ec11cda2b066151be2cfb48adf9e47b151d46adab3a21cdf67 |
| Master chain code c (right half) | 7923408dadd3c7b56eed15567707ae5e5dca089de972e07f3b860450e2a3b70e |
| Master public key (compressed) | 03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494 |
| Master fingerprint | 73c5da0a |
The fingerprintKey fingerprint: The first 4 bytes of HASH160 of a compressed public key. Extended keys store their parent's fingerprint to help software find where they sit in the tree. It is one of the few places Pearl still uses RIPEMD-160. is the first 4 bytes of HASH160 (RIPEMD-160 of SHA-256) of the compressed public key. It’s one of the few places RIPEMD-160 survives in Pearl.
What’s inside an extended key?
78 bytes, always in the same order:
| Field | Size | Description |
|---|---|---|
| version | 4 | Says private or public, and which network. 04b2430c = zprv on mainnet. |
| depth | 1 | How many steps below the master: 0 for the master, 3 for an account key. |
| parent fingerprint | 4 | First 4 bytes of HASH160 of the parent's public key. Zero for the master. |
| child number | 4 | Which child of the parent this is, big-endian. Hardened children have the top bit set. |
| chain code | 32 | The extra 32 bytes needed to derive children. |
| key | 33 | 00 ‖ 32-byte private key (zprv), or the 33-byte compressed public key (zpub). |
Here is the test phrase’s master zprv, byte by byte:
| Field | Bytes | Value |
|---|---|---|
| version (zprv) | 4 @0 | 04b2430c |
| depth | 1 @4 | 0: the master |
| parent fingerprint | 4 @5 | none: the master has no parent |
| child number | 4 @9 | 00000000 |
| chain code | 32 @13 | 7923408dadd3c7b56eed15567707ae5e5dca089de972e07f3b860450e2a3b70e |
| key (00 ‖ private key) | 33 @45 | 001837c1be8e2995ec11cda2b066151be2cfb48adf9e47b151d46adab3a21cdf67 |
Add a 4-byte checksum (the first 4 bytes of SHA256d of the 78 bytes) and write it in Base58CheckBase58Check: A text encoding with 58 easy-to-read characters and a 4-byte double-SHA-256 checksum. Pearl uses it only for WIF private keys and zprv/zpub extended keys, never for addresses.:
zprvAWgYBBk7JR8Gjrh4UJQ2uJdG1r3WNRRfURiABBE3RvMXYSrRJL62XuezvGdPvG6GFBZduosCc1YP5wixPox7zhZLfiUm8aunE96BBa4Kei5
Drop the private key, put the public key in its place, switch the version to 04b24746, and you get the matching zpub:
zpub6jftahH18ngZxLmXaKw3GSZzZsszmt9WqedkyZdezFtWRFBZqsQH5hyUmb4pCEeZGmVfQuP5bedXTB8is6fTv19U1GQRyQUKQGUTzyHACMF
Why does Pearl use “z” prefixes?
Because Pearl’s developers picked existing version bytes. The comment in Pearl’s network settings reads “Using BIP-84 (SegWit) versions for Taproot-only wallet”.
| Network | Private | Public | Prefix |
|---|---|---|---|
| mainnet | 04b2430c |
04b24746 |
zprv / zpub |
| testnet, testnet2, regtest | 045f18bc |
045f1cf6 |
vprv / vpub |
| Bitcoin Taproot, for comparison | 0488ade4 |
0488b21e |
xprv / xpub |
The version bytes only change the label. Re-encode the master key above with Bitcoin’s xprv bytes and you get BIP-86’s official test-vector root, xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu. Same key, same chain code.
How are children derived?
Each child comes from one HMAC-SHA512, keyed with the parent’s chain code. There are two kinds.
-
Normal child (index below 2³¹)
Data = parent’s compressed public key ‖ index (4 bytes, big-endian). The left half of the HMAC, added to the parent private key mod n, is the child private key; the right half is the child chain code. -
Hardened child (index 2³¹ and up)
Data =00‖ parent’s private key ‖ index. Same split. Because the private key goes in, only someone holding it can derive a hardened child.
Normal children have a useful property: the same addition works on public keys. A zpub can derive every normal child’s public key without any private key. That’s what makes watch-only wallets possible.
HardenedHardened derivation: A way to make a child key that needs the parent's private key, marked with ' in a path (86'). Child numbers 2³¹ and up are hardened. A leaked child key then can't expose its siblings. children, marked with ’ in paths (86'), block that. They also limit the damage of a leak, as the next section explains. Which levels are hardened is set by the derivation path.
Pearl’s account key
Oyster’s default account sits at m/86’/808276’/0’. For the test phrase, its extended public key is:
zpub6s66goCpFBSqGDZyyD6a1Xf8C5TseQYcPFQNpjMzFeTCZpZD6ShaEzAKqv8tDiv81N1RmPyRTu1D65iQv59c7wHZyCbQmnaARE7P6UFNJeG
That’s exactly the key a real Oyster wallet stores in its database for account 0. From it, anyone can compute every receive address (/0/i) and change address (/1/i) in the account, but no private key.
What can go wrong with extended keys?
- A zprv is the whole wallet. Treat it like the 12 words.
- A zpub is your whole history. It shows every address, past and future, in its branch. Share it only with software you trust.
- A zpub plus one child private key is the whole branch. For normal (non-hardened) children, the parent’s private key is just the child’s private key minus a value anyone with the zpub can compute. BIP-32 calls this out; hardened levels contain the damage to one account.
Code: master key in JavaScript
Using @noble/hashes:
import { hmac } from '@noble/hashes/hmac.js';
import { sha512 } from '@noble/hashes/sha2.js';
const I = hmac(sha512, new TextEncoder().encode('Bitcoin seed'), seed); // seed: Uint8Array(64)
const masterKey = I.slice(0, 32); // 1837c1be… for the test phrase
const chainCode = I.slice(32); // 7923408d…