- The Different Types of Child Key Derivations
- Derivation Process with HMAC-SHA512
- Correspondence between child public and private keys
- Summary of derivation types
The derivation of child key pairs in Bitcoin HD wallets relies on a hierarchical structure that allows generating a large number of keys, while organizing these pairs into different groups through branches. Each child pair derived from a parent pair can be used either directly in a scriptPubKey to lock bitcoins, or as a starting point to generate more child keys, and so on, to create a tree of keys.
All these derivations start with the master key and the master chain code, which are the first parents at depth level 0. They are, in a way, the Adam and Eve of your wallet's keys, common ancestors of all derived keys.
Let's explore how this deterministic derivation works.
The Different Types of Child Key Derivations
As we briefly touched upon in the previous chapter, child keys are divided into two main types.
- Normal child keys (
): These are derived from the extended public key ( ), or the extended private key ( ), by first deriving the public key. - Hardened child keys (
): These can only be derived from the extended private key ( ) and are therefore invisible to observers who only have the extended public key.
Every child key pair is identified by a 32-bit index (named in our calculations). The indexes for normal keys range from to , while those for hardened keys range from to . These numbers are used to distinguish sibling key pairs during derivation. Indeed, each parent key pair must be capable of deriving multiple child key pairs. If we were to apply the same calculation systematically from the parent keys, all the sibling keys obtained would be identical, which is not desirable. The index thus introduces a variable that modifies the derivation calculation, allowing each sibling pair to be differentiated. Except for specific use in certain protocols and derivation standards, we generally start by deriving the first child key with the index
0, the second with the index 1, and so on.Derivation Process with HMAC-SHA512
The derivation of each child key is based on the HMAC-SHA512 function, which we discussed in Section 2 on hash functions. It takes two inputs: the parent chain code , and the concatenation of the parent key (either the public key or the private key , depending on the type of child key desired) with the index. The output of the HMAC-SHA512 is a 512-bit sequence, divided into two parts:
- The first 32 bytes (or
) are used to calculate the new child pair. - The last 32 bytes (or
) serve as the new chain code for the child pair.
In all our calculations, I will denote the output of the HMAC-SHA512 function.
Derivation of a Child Private Key from a Parent Private Key
To derive a child private key from a parent private key , two scenarios are possible depending on whether a hardened or normal key is desired.
For a normal child key ( ), the calculation of is as follows:
In this calculation, we observe that our HMAC function takes two inputs: first, the parent chain code, and then the concatenation of the index with the public key associated with the parent private key. The parent public key is used here because we are looking to derive a normal child key, not a hardened one.
We now have a 64-byte that we will split into 2 parts of 32 bytes each, and :
The child private key is then calculated as follows:
In this calculation, the operation consists of interpreting the first 32 bytes of the as a 256-bit integer. This number is then added to the parent private key, all taken modulo to stay within the order of the elliptic curve, as we saw in section 3 on digital signatures. Thus, to derive a normal child private key, although the parent public key is used as the basis for calculation in the inputs of the HMAC-SHA512 function, it is always necessary to have the parent private key to finalize the calculation.
From this child private key, it is possible to derive the corresponding public key by applying ECDSA or Schnorr. This way, we obtain a complete pair of keys.
Then, the second part of the is simply interpreted as being the chain code for the child key pair that we have just derived:
Here is a schematic representation of the overall derivation:
For a hardened child key ( ), the calculation of the is as follows:
In this calculation, we observe that our HMAC function takes two inputs: first, the parent chain code, and then the concatenation of the index with the parent private key. The parent private key is used here because we are looking to derive a hardened child key. Moreover, a byte equal to that we will split into 2 parts of 32 bytes each, and :
0x00 is added at the beginning of the key. This operation equalizes its length to match that of a compressed public key.
So, we now have a 64-byte The child private key is then calculated as follows:
Next, we simply interpret the second part of the as being the chain code for the pair of child keys that we have just derived:
Here is a schematic representation of the overall derivation:
We can see that normal derivation and hardened derivation function in the same way, with this difference: normal derivation uses the parent public key as input to the HMAC function, while hardened derivation uses the parent private key.
Deriving a child public key from a parent public key
If we only know the parent public key and the associated chain code , that is, an extended public key, it is possible to derive child public keys , but only for normal (non-hardened) child keys. This principle notably allows for monitoring the movements of an account in a Bitcoin wallet from the
xpub (watch-only).To perform this calculation, we will compute the with an index (normal derivation):
In this calculation, we observe that our HMAC function takes two inputs: first the parent chain code, then the concatenation of the index with the parent public key.
So, we now have a of 64 bytes that we will split into 2 parts of 32 bytes each, and :
The child public key is then calculated as follows:
If (order of the elliptic curve) or if is the point at infinity, the derivation is invalid, and another index must be chosen.
In this calculation, the operation involves interpreting the first 32 bytes of the as a 256-bit integer. This number is used to calculate a point on the elliptic curve through addition and doubling from the generator point . This point is then added to the parent public key to obtain the normal child public key. Thus, to derive a normal child public key, only the parent public key and the parent chain code are necessary; the parent private key never comes into this process, unlike the calculation of the child private key we saw earlier.
Next, the child chain code is simply:
Here is a schematic representation of the overall derivation:
Correspondence between child public and private keys
A question that may arise is how a normal child public key derived from a parent public key can correspond to a normal child private key derived from the corresponding parent private key. This link is precisely ensured by the properties of elliptic curves. Indeed, to derive a normal child public key, HMAC-SHA512 is applied in the same way, but its output is used differently:
- Normal child private key:
- Normal child public key:
Thanks to the addition and doubling operations on the elliptic curve, both methods produce consistent results: the public key derived from the child private key is identical to the child public key derived directly from the parent public key.
Summary of derivation types
To summarize, here are the different possible types of derivations:
So far you have learned to create the basic elements of an HD wallet: the mnemonic phrase, the seed, and then the master key and master chain code. You have also discovered how to derive child key pairs in this chapter. In the next chapter, we will explore how these derivations are organized in Bitcoin wallets and what structure to follow to concretely obtain the receiving addresses as well as the key pairs used in the scriptPubKey and scriptSig.
Quiz
Quiz1/5
cyp2015.3
What is the purpose of the index in deriving child keys?