pull/137/head
Andreas M. Antonopoulos 10 years ago
parent 51c319c54c
commit c3a755a721

@ -540,19 +540,19 @@ HD wallets offer two major advantages over random (non-deterministic) keys. Firs
The second advantage of HD wallets is that users can create a sequence of public keys without having access to the corresponding private keys. This allows HD wallets to be used on an insecure server or in a receive-only capacity, issuing a different public key for each transaction. The public keys do not need to be pre-loaded or derived in advance, yet the server doesn't have the private keys that can spend the funds.
===== Creating an HD wallet from a seed
===== HD wallet creation from a seed
HD wallets are created from a single _root seed_, which is a 128, 256 or 512 bit random number. Everything else in the HD wallet is deterministically derived from this root seed, which makes it possible to re-create the entire HD wallet from that seed in any compatible HD wallet. This makes it easy to backup, restore, export and import HD wallets containing thousands or even millions of keys by simply transferring only the root seed. The root seed is most often represented by a _mnemonic word sequence_, as described in the previous section <<mnemonic_code_words>>, to make it easier for people to transcribe and store it.
The process of creating the master keys and master chain code for an HD wallet is shown below:
[[HDWalletFromSeed]]
.Hierarchical Deterministic Wallet: Creating master keys and chain code from a root seed
.Creating master keys and chain code from a root seed
image::images/HDWalletFromRootSeed.svg["HDWalletFromRootSeed"]
The root seed is input into the HMAC-SHA512 algorithm and the resulting hash is used to create a _master private key_ (m) and a _master chain code_. The master private key (m) then generates a corresponding master public key (M), using the normal elliptic curve multiplication process +m * G+ that we saw previously in this chapter. The chain code is used to introduce entropy in the function that creates child keys from parent keys, as we will see in the next section.
===== Deriving child private keys
===== Private child key derivation
Hierarchical Deterministic wallets use a _child key derivation_ (CKD) function to derive children keys from parent keys.
@ -569,12 +569,12 @@ These three items are combined and hashed to generate children keys, as follows:
The parent public key, chain code and the index number are combined and hashed with the HMAC-SHA512 algorithm to produce a 512 bit hash. The resulting hash is split into two halfs. The right-half 256 bits of the hash output become the chain code for the child. The left-half 256 bits of the hash and the index number are added to the parent private key to produce the child private key. In the diagram below, we see this illustrated with the index set to 0 to produce the 0'th (first by index) child of the parent.
[[CKDpriv]]
.Hierarchical Deterministic Wallet: Extending a parent private key to create a child private key
.Extending a parent private key to create a child private key
image::images/ChildPrivateDerivation.svg["ChildPrivateDerivation"]
Changing the index allows us to extend the parent and create the other children in the sequence, e.g. Child 0, Child 1, Child 2 etc. Each parent key can have 2 billion children keys.
Repeating the process one level down the tree, each child can become a parent and in combination with the child chain code and an index can create it's own children, in an infinite number of generations.
Repeating the process one level down the tree, each child can in turn become a parent and create it's own children, in an infinite number of generations.
===== Using derived child keys
@ -597,13 +597,13 @@ Think of an extended key as the root of a branch in the tree structure of the HD
[TIP]
====
An extended key consists of a key and chain code and is the root of one of the branches in an HD wallet tree structure. With an extended key you can derive all the nodes in that branch.
An extended key consists of a private or public key and chain code. An extended key can create children generating its own branch in the tree structure. Sharing an extended key gives access to the entire branch.
====
[[public_key_derivation]]
===== Deriving child public keys
===== Public child key derivation
As mentioned above, a very useful characteristic of hierarchical deterministic wallets is the ability to derive public child keys from public parent keys, _without_ having the private keys. A child public key derived directly from the parent public key is exactly the same as if you first derived the child private key from the parent private key and then computed the child public key corresponding to it.
As mentioned above, a very useful characteristic of hierarchical deterministic wallets is the ability to derive public child keys from public parent keys, _without_ having the private keys. This gives us two ways to derive a child public key: either from the child private key, or directly from the parent public key.
An extended public key can be used, therefore, to derive all of the _public_ keys (and only the public keys) in that branch of the HD wallet structure.
@ -614,38 +614,42 @@ One common application of this solution is to install an extended public key on
Another common application of this solution is for cold-storage or hardware wallets. In that scenario, the extended private key can be stored on a paper wallet or hardware device (such as a Trezor hardware wallet), while the extended public key can be kept online. The user can create "receive" addresses at will, while the private keys are safely stored offline. To spend the funds, they can use the extended private key on an offline signing bitcoin client or sign transactions on the hardware wallet device (e.g. Trezor).
[[CKDpub]]
.Hierarchical Deterministic Wallet: Extending a parent public key to create a child public key
.Extending a parent public key to create a child public key
image::images/ChildPublicDerivation.svg["ChildPublicDerivation"]
===== Hardened derivation and notation
===== Hardened child key derivation
The ability to derive a branch of public keys from an extended public key is very useful, but it comes with a potential risk. Access to an extended public key does not give access to child private keys. However, because the extended public key contains the chain code, if a child private key is known, or somehow leaked, it can be used with the chain code to derive all the other child private keys. A single leaked child private key, together with a parent chain code, reveals all the private keys of all the children. Worse, the child private key together with a parent chain code can be used to deduce the parent private key.
To counter this risk, HD wallets use an alternative derivation function called _hardened derivation_, which "breaks" the relationship between parent public key and child chain code. The hardened derivation function uses the parent private key to derive the child chain code, instead of the parent public key. This creates a "firewall" in the parent/child sequence, with a chain code that cannot be used to compromise a parent or sibling private key. The hardened derivation function looks almost identical to the normal child private key derivation, except that the parent private key is used as input to the hash function, instead of the parent public key, as shown in the diagram below:
[[CKDprime]]
.Hierarchical Deterministic Wallet: Hardened derivation of a child key, omits the parent public key
.Hardened derivation of a child key, omits the parent public key
image::images/ChildHardPrivateDerivation.svg["ChildHardPrivateDerivation"]
When the hardened private derivation function is used, the resulting child private key and chain code are completely different from what would result from the normal derivation function. The resulting "branch" of keys can be used to produce extended public keys which are not vulnerable, since the chain code they contain cannot be exploited to reveal any private keys. Hardened derivation is therefore used to create a "gap" in the tree above the level where extended public keys are used. In simple terms, if you want to use the convenience of an extended public key to derive branches of public keys, without exposing yourself to the risk of a leaked chain code, you should derive it from a hardened parent, rather than a normal parent. As a best practice, the level-1 children of the master keys are always derived through the hardened derivation, to prevent compromise of the master keys.
When the hardened private derivation function is used, the resulting child private key and chain code are completely different from what would result from the normal derivation function. The resulting "branch" of keys can be used to produce extended public keys which are not vulnerable, since the chain code they contain cannot be exploited to reveal any private keys. Hardened derivation is therefore used to create a "gap" in the tree above the level where extended public keys are used.
In simple terms, if you want to use the convenience of an extended public key to derive branches of public keys, without exposing yourself to the risk of a leaked chain code, you should derive it from a hardened parent, rather than a normal parent. As a best practice, the level-1 children of the master keys are always derived through the hardened derivation, to prevent compromise of the master keys.
===== Index numbers for normal and hardened derivation
The index number used int he derivation function is a 32-bit integer. To easily distinguish between keys derived through the normal derivation function versus keys derived through hardened derivation, this index number is split into two ranges. Index numbers between 0 and 2^31^ (0x0 to 0x80000000) are used _only_ for normal derivation. Index numbers between 2^31^ and 2^32^ (0x80000000 to 0x8FFFFFFF) are used _only_ for hardened derivation. Therefore, if the index number is less than 2^31^, that means the child is normal, whereas if the index number is above 2^31^, the child is hardened.
The index number used in the derivation function is a 32-bit integer. To easily distinguish between keys derived through the normal derivation function versus keys derived through hardened derivation, this index number is split into two ranges. Index numbers between 0 and 2^31^ (0x0 to 0x80000000) are used _only_ for normal derivation. Index numbers between 2^31^ and 2^32^ (0x80000000 to 0x8FFFFFFF) are used _only_ for hardened derivation. Therefore, if the index number is less than 2^31^, that means the child is normal, whereas if the index number is above 2^31^, the child is hardened.
To make the index number easier to read and display, the index number for hardened children is displayed starting from zero, but with a prime symbol ('). The first normal child key is therefore displayed as 0, whereas the first hardened child (index 0x80000000) is displayed as 0'. In sequence then, the second hardened key would have index 0x80000001 and would be displayed as 1', and so on. When you see an HD wallet index i', that means 2^31^+i
To make the index number easier to read and display, the index number for hardened children is displayed starting from zero, but with a prime symbol. The first normal child key is therefore displayed as 0, whereas the first hardened child (index 0x80000000) is displayed as 0'. In sequence then, the second hardened key would have index 0x80000001 and would be displayed as 1', and so on. When you see an HD wallet index i', that means 2^31^+i
===== HD key identifier (path)
===== HD wallet key identifier (path)
Keys in an HD wallet are identified using a "path" naming convention, with each level of the tree separated by a slash (/) character. Private keys derived from the master private key start with "m". Public keys derived from the master public key start with "M". Each level of the tree shows the index number of the child key. The key identified by the path is the right most index with its "ancestry" read from right to left up to the master key from which it was derived. For example, identifier m/x/y/z describes the key which is the z-th child of key m/x/y, which is the y-th child of key m/x, which is the x-th child of m.
Keys in an HD wallet are identified using a "path" naming convention, with each level of the tree separated by a slash (/) character. Private keys derived from the master private key start with "m". Public keys derived from the master public key start with "M". Therefore, the first child private key of the master private key is m/0. The first child public key is M/0. The second grandchild of the first child is m/0/1 and so on.
The "ancestry" of a key is read from right to left, until you reach the master key from which it was derived. For example, identifier m/x/y/z describes the key which is the z-th child of key m/x/y, which is the y-th child of key m/x, which is the x-th child of m.
.HD wallet path indicating derived keys
.HD wallet path examples
|=======
| m/0 | The first (0) child private key from the master private key (m)
| m/0/0 | The first grandchild private key of the first child.
| m/0/0 | The first grandchild private key of the first child (m/0)
| m/0'/0 | The first normal grandchild of the first _hardened_ child (m/0')
| m/1/0 | The first grandchild private key of the second child (m/1).
| M/23/17/0/0 | The first great-great-grandchild public key of the first great-grandchild of the 18th grandchild of the 24th child.
| m/1/0 | The first grandchild private key of the second child (m/1)
| M/23/17/0/0 | The first great-great-grandchild public key of the first great-grandchild of the 18th grandchild of the 24th child
|=======
===== Navigating the HD wallet tree structure

Loading…
Cancel
Save