BIP-32
BIP-32 is the Bitcoin Improvement Proposal that defines exactly how a hierarchical deterministic wallet computes its tree of keys. It is the precise recipe behind the friendly idea of 'one seed restores everything'. Although it originated in Bitcoin, the same algorithm is used unchanged across Ethereum and most other secp256k1 chains, which is why one mnemonic can drive many coins.
It works like this. From the seed, the wallet computes HMAC-SHA512 with the fixed key string 'Bitcoin seed'; the 64-byte output splits into a left half that becomes the master private key and a right half called the chain code — an extra piece of entropy that stops a child key from leaking its siblings. To derive child number i, the wallet again runs HMAC-SHA512, this time keyed by the parent chain code over the parent key material concatenated with i. The left half of that output is added (modulo the curve order n) to the parent private key to give the child private key; the right half becomes the child's own chain code. Recursing this gives the full tree.
A central design choice is the index threshold at 2^31. Indices below it are 'non-hardened' and feed the parent public key into the HMAC, which has the powerful side effect that a public key plus chain code (an extended public key) can derive all non-hardened child public keys with no private key present. Indices of 2^31 and above are 'hardened' and feed the parent private key instead, severing that public-derivation link. The trade-off is real and security-critical: non-hardened branches enable watch-only address generation, but if any single non-hardened child private key leaks alongside the parent extended public key, the parent private key can be recovered — so account-level boundaries are always hardened.
// hardened child (i >= 2^31): parent PRIVATE key feeds the HMAC I = HMAC-SHA512(key = c_par, data = 0x00 || ser256(k_par) || ser32(i)) // normal child (i < 2^31): parent PUBLIC key feeds the HMAC I = HMAC-SHA512(key = c_par, data = serP(point(k_par)) || ser32(i)) IL = I[0..32]; IR = I[32..64] k_i = (parse256(IL) + k_par) mod n // child private key c_i = IR // child chain code
BIP-32 child key derivation: the only difference between hardened and normal is whether the private or public key is hashed.
BIP-32 is silent about which paths to use — that is BIP-44's job. BIP-32 only specifies the math of turning a parent key plus an index into a child key.