Let’s keep in mind the problems that we want to resolve:
Prevent outdated backups.
Delegating key / address generation to an untrusted peer.
A “Deterministic” wallet would fix our backup problem. With such a wallet, you would have to save only the seed. From this seed, you can generate the same series of private keys over and over.
This is what the “Deterministic” stands for. As you can see, from the master key, I can generate new keys:
ExtKey masterKey = new ExtKey();
Console.WriteLine("Master key : " + masterKey.ToString(Network.Main));
for (int i = 0; i < 5; i++)
{
ExtKey key = masterKey.Derive((uint)i);
Console.WriteLine("Key " + i + " : " + key.ToString(Network.Main));
}
You only need to save the masterKey, since you can generate the same suite of private keys over and over.
As you can see, these keys are ExtKey and not Key as you are used to. However, this should not stop you since you have the real private key inside:
You can go back from a Key to an ExtKey by supplying the Key and the ChainCode to the ExtKey constructor. This works as follows:
ExtKey extKey = new ExtKey();
byte[] chainCode = extKey.ChainCode;
Key key = extKey.PrivateKey;
ExtKey newExtKey = new ExtKey(key, chainCode);
The base58 type equivalent of ExtKey is called BitcoinExtKey.
But how can we solve our second problem: delegating address creation to a peer that can potentially be hacked (like a payment server)?
The trick is that you can “neuter” your master key, then you have a public (without private key) version of the master key. From this neutered version, a third party can generate public keys without knowing the private key.
ExtPubKey masterPubKey = masterKey.Neuter();
for (int i = 0 ; i < 5 ; i++)
{
ExtPubKey pubkey = masterPubKey.Derive((uint)i);
Console.WriteLine("PubKey " + i + " : " + pubkey.ToString(Network.Main));
}
ExtPubKey is similar to ExtKey except that it holds a PubKey and not a Key.
Now we have seen how Deterministic keys solve our problems, let’s speak about what the “hierarchical” is for.
In the previous exercise, we have seen that by combining master key + index we could generate another key. We call this process Derivation, the master key is the parent key, and any generated keys are called child keys.
However, you can also derivate children from the child key. This is what the “hierarchical” stands for.
This is why conceptually more generally you can say: Parent Key + KeyPath => Child Key.
In this diagram, you can derivate Child(1,1) from parent in two different way:
ExtKey parent = new ExtKey();
ExtKey child11 = parent.Derive(1).Derive(1);
Or
ExtKey parent = new ExtKey();
ExtKey child11 = parent.Derive(new KeyPath("1/1"));
So in summary:
It works the same for ExtPubKey.
Why do you need hierarchical keys? Because it might be a nice way to classify the type of your keys for multiple accounts. More on BIP44.
It also permits segmenting account rights across an organization.
Imagine you are CEO of a company. You want control over all wallets, but you don’t want the Accounting department to spend the money from the Marketing department.
So your first idea would be to generate one hierarchy for each department.
However, in such a case, Accounting and Marketing would be able to recover the CEO’s private key.
We define such child keys as non-hardened.
ExtKey ceoKey = new ExtKey();
Console.WriteLine("CEO: " + ceoKey.ToString(Network.Main));
ExtKey accountingKey = ceoKey.Derive(0, hardened: false);
ExtPubKey ceoPubkey = ceoKey.Neuter();
//Recover ceo key with accounting private key and ceo public key
ExtKey ceoKeyRecovered = accountingKey.GetParentExtKey(ceoPubkey);
Console.WriteLine("CEO recovered: " + ceoKeyRecovered.ToString(Network.Main));
CEO: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC
CEO recovered: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC
In other words, a non-hardened key can “climb” the hierarchy. Non-hardened keys should only be used for categorizing accounts that belongs to a point of single control.
So in our case, the CEO should create a hardened key, so the accounting department will not be able to climb the hierarchy.