diff --git a/_includes/guide_wallets.md b/_includes/guide_wallets.md
index b9cf1848..e6eb779f 100644
--- a/_includes/guide_wallets.md
+++ b/_includes/guide_wallets.md
@@ -158,7 +158,7 @@ As illustrated above, HD key derivation takes four inputs:
* The [index][key index]{:#term-key-index}{:.term} number is a 32-bit integer specified by the program.
In the normal form shown in the above illustration, the parent chain
-code and the index number are fed into a one-way cryptographic hash
+code, the parent public key, and the index number are fed into a one-way cryptographic hash
([HMAC-SHA512][]) to produce 512 bits of
deterministically-generated-but-seemingly-random data. The
seemingly-random 256 bits on the righthand side of the hash output are
@@ -218,14 +218,14 @@ which makes them special.
Deriving [child extended keys][child extended key]{:#term-child-extended-key}{:.term} from parent extended keys is more nuanced
than described earlier due to the presence of two extended private key
derivation formulas. The normal formula, described above, combines
-together only the index number and the parent chain code to create the
+together the index number, the parent chain code, and the parent public key to create the
child chain code and the integer value which is combined with the parent
private key to create the child private key.

The hardened formula, illustrated above, combines together the index
-number, the parent chain code, and also the parent private key to create
+number, the parent chain code, and the parent private key to create
the data used to generate the child chain code and child private key.
This formula makes it impossible to create child public keys without
knowing the parent private key. In other words, parent extended public
@@ -235,13 +235,22 @@ Because of that, a [hardened extended private
key][]{:#term-hardened-extended-private-key}{:.term} is much less
useful than a normal extended private key---however, it's more secure
against multi-level key compromise. If an attacker gets a normal parent
-chain code, he can brute-force find all 231 normal chain
+chain code and parent public key, he can brute-force find all 231 normal chain
codes deriving from it. If the attacker also obtains a child, grandchild, or
further-descended private key, he can use the chain code to generate all
-of the extended private keys descending from that private key.
+of the extended private keys descending from that private key, as
+shown in the grandchild and great-grandchild generations of the illustration below.

+Perhaps worse, the attacker can reverse the normal child private key
+derivation formula and subtract a parent chain code from a child private
+key to recover the parent private key, as shown in the child and
+parent generations of the illustration above. This means an attacker
+who acquires an extended public key and any private key descended from
+it can recover that public key's private key and all keys descended from
+it.
+
For this reason, the chain code part of an extended public key should be
better secured than standard public keys and users should be advised
against exporting even non-extended private keys to
diff --git a/en/developer-reference.md b/en/developer-reference.md
index 83e250fa..c93aa32c 100644
--- a/en/developer-reference.md
+++ b/en/developer-reference.md
@@ -22,7 +22,6 @@ title: "Developer Reference - Bitcoin"
{% include ref_block_chain.md %}
{% include ref_transactions.md %}
{% include ref_wallets.md %}
-{% include ref_payment_processing.md %}
## Bitcoin Core APIs
diff --git a/img/dev/en-hd-cross-generational-key-compromise.dot b/img/dev/en-hd-cross-generational-key-compromise.dot
index a41b9105..dead1601 100644
--- a/img/dev/en-hd-cross-generational-key-compromise.dot
+++ b/img/dev/en-hd-cross-generational-key-compromise.dot
@@ -3,47 +3,73 @@ digraph extended {
size=6.25;
rankdir=LR;
penwidth=1.75;
-node [ penwidth = 1.75, shape = "box" ];
-edge [ penwidth = 1.75 ];
+node [ fontname="Sans", penwidth = 1.75, shape = "box" ];
+edge [ fontname="Sans", penwidth = 1.75, style = "" ];
+graph [ fontname="Sans" ];
nodesep=0.15;
-splines = ortho;
+splines = false;
ranksep = 0.7;
subgraph cluster_parent {
- attacker_parent_private_key [ label = "Private", style = "invis" ];
- attacker_parent_chain_code [ label = "Chain", style = "filled" ];
- attacker_parent_public_key [ label = "Public", style = "invis" ];
+ parent_private_key [ label = "Private", style = "" ];
+ parent_chain_code [ label = "Chain", style = "filled" ];
+ parent_public_key [ label = "Public", style = "filled" ];
- label = "Parent"
+ label = "Parent\n "
}
subgraph cluster_child {
- attacker_child_private_key [ label = "Private", style = "filled" ];
- attacker_child_chain_code [ label = "Chain" ];
- attacker_child_public_key [ label = "Public" ];
+ child_private_key [ label = "Private" ];
+ child_chain_code [ label = "Chain" ];
+ child_public_key [ label = "Public" ];
- label = "Child"
+ label = "Child\n "
}
subgraph cluster_grandchild {
- attacker_grandchild_private_key [ label = "Private" ];
- attacker_grandchild_chain_code [ label = "Chain" ];
- attacker_grandchild_public_key [ label = "Public" ];
+ grandchild_private_key [ label = "Private", style = "filled" ];
+ grandchild_chain_code [ label = "Chain" ];
+ grandchild_public_key [ label = "Public" ];
- label = "Grandchild"
+ label = "Grandchild\n "
+}
+
+subgraph cluster_greatgrandchild {
+ greatgrandchild_private_key [ label = "Private" ];
+ greatgrandchild_chain_code [ label = "Chain" ];
+ greatgrandchild_public_key [ label = "Public" ];
+
+ label = "Great-\nGrandchild"
}
+parent_public_key -> child_public_key;
+parent_public_key -> child_chain_code;
+parent_chain_code -> child_chain_code [ label = "Normal Child\nKey Derivation", weight = 100 ];
+parent_chain_code -> child_public_key;
+parent_chain_code -> child_private_key [ style = "invis" ];
+parent_private_key -> child_private_key [ dir = "back", style = "", label = "Parent Key\nDerivation" ];
-attacker_parent_public_key -> attacker_child_public_key [ style = "invis" ];
-attacker_parent_chain_code -> attacker_child_chain_code;
-attacker_parent_chain_code -> attacker_child_public_key [ style = "invis" ];
-attacker_parent_private_key -> attacker_child_private_key [style = "invis" ];
+parent_chain_code -> parent_private_key [ constraint = false ];
+
+child_private_key -> grandchild_private_key [ dir = "back", style = "" ];
+child_public_key -> grandchild_chain_code;
+child_public_key -> grandchild_public_key;
+child_chain_code -> grandchild_private_key [ style = "invis" ];
+child_chain_code -> grandchild_public_key;
+child_chain_code -> grandchild_chain_code [ weight = 100 ];
+
+child_chain_code -> child_private_key [ constraint = false ]
+
+grandchild_private_key -> greatgrandchild_private_key;
+grandchild_public_key -> greatgrandchild_chain_code;
+grandchild_public_key -> greatgrandchild_public_key;
+grandchild_chain_code -> greatgrandchild_private_key;
+grandchild_chain_code -> greatgrandchild_public_key;
+grandchild_chain_code -> greatgrandchild_chain_code [ weight = 100 ];
+
+grandchild_chain_code -> grandchild_private_key [ constraint = false, style = "invis" ]
+greatgrandchild_chain_code -> greatgrandchild_private_key [ constraint = false, style = "invis" ]
-attacker_child_private_key -> attacker_grandchild_private_key;
-attacker_child_public_key -> attacker_grandchild_public_key;
-attacker_child_chain_code -> attacker_grandchild_private_key;
-attacker_child_chain_code -> attacker_grandchild_public_key;
-attacker_child_chain_code -> attacker_grandchild_chain_code;
label = "Cross-Generational Key Compromise"
}
diff --git a/img/dev/en-hd-cross-generational-key-compromise.png b/img/dev/en-hd-cross-generational-key-compromise.png
index b44c0819..8869dcf0 100644
Binary files a/img/dev/en-hd-cross-generational-key-compromise.png and b/img/dev/en-hd-cross-generational-key-compromise.png differ
diff --git a/img/dev/en-hd-cross-generational-key-compromise.svg b/img/dev/en-hd-cross-generational-key-compromise.svg
index bd0c21ca..c0bb8e18 100644
--- a/img/dev/en-hd-cross-generational-key-compromise.svg
+++ b/img/dev/en-hd-cross-generational-key-compromise.svg
@@ -4,93 +4,189 @@
-
diff --git a/img/dev/en-hd-private-parent-to-private-child.dot b/img/dev/en-hd-private-parent-to-private-child.dot
index 2bc81dfa..ddbd46d8 100644
--- a/img/dev/en-hd-private-parent-to-private-child.dot
+++ b/img/dev/en-hd-private-parent-to-private-child.dot
@@ -3,12 +3,14 @@ digraph extended {
size=6.25;
rankdir=LR;
penwidth=1.75;
-node [ penwidth = 1.75, shape = "box" ];
-edge [ penwidth = 1.75 ];
+node [ fontname="Sans", penwidth = 1.75, shape = "box" ];
+edge [ fontname="Sans", penwidth = 1.75 ];
+graph [ fontname="Sans" ];
nodesep=0.05;
-splines = ortho;
+//splines = ortho;
ranksep = 1.0;
subgraph cluster_hard {
+ style = "invis";
subgraph cluster_h_parent_extended_key {
h_parent_private_key [ label = "Parent Private Key" ];
@@ -31,18 +33,16 @@ subgraph cluster_hard {
hmac_hard -> child_private_key_hard;
hmac_hard -> child_chain_code_hard;
h_parent_private_key -> child_private_key_hard;
-
- label = "Hardened Private"
}
subgraph cluster_norm {
- //style = "invis"
- //label = "Creation Of Normal Child Extended Keys (Key + Chain Code)\nFrom Parent Extended Keys"
+ style = "invis"
subgraph cluster_n_parent_extended_key {
n_parent_private_key [ label = "Parent Private Key" ];
n_parent_chain_code [ label = "Parent Chain Code" ];
+ n_parent_public_key [ label = "Parent Public Key" ];
}
subgraph cluster_child_extended_key_norm {
@@ -53,15 +53,13 @@ subgraph cluster_norm {
i_norm [ label = "Index <0x80000000" ];
n_parent_chain_code -> hmac_norm;
+ n_parent_public_key -> hmac_norm;
i_norm -> hmac_norm;
hmac_norm -> child_private_key_norm;
hmac_norm -> child_chain_code_norm;
- n_parent_private_key -> child_private_key_norm;
-
- label = "Normal Private"
+ n_parent_private_key -> child_private_key_norm [weight = 5];
}
-
-label = "Creation Of Child Extended Private Keys (Key, Chain Code)"
+label = "Normal (Top) And Hardened (Bottom) Child Private Key Derivation";
}
diff --git a/img/dev/en-hd-private-parent-to-private-child.png b/img/dev/en-hd-private-parent-to-private-child.png
index dc66ca13..83081604 100644
Binary files a/img/dev/en-hd-private-parent-to-private-child.png and b/img/dev/en-hd-private-parent-to-private-child.png differ
diff --git a/img/dev/en-hd-private-parent-to-private-child.svg b/img/dev/en-hd-private-parent-to-private-child.svg
index 7c2fa2cc..02e85cc3 100644
--- a/img/dev/en-hd-private-parent-to-private-child.svg
+++ b/img/dev/en-hd-private-parent-to-private-child.svg
@@ -4,31 +4,23 @@
-
-
+
+
extended
-
-Creation Of Child Extended Private Keys (Key, Chain Code)
+
+Normal (Top) And Hardened (Bottom) Child Private Key Derivation
cluster_hard
-
-Hardened Private
cluster_h_parent_extended_key
-
cluster_child_extended_key_else
-
cluster_norm
-
-Normal Private
cluster_n_parent_extended_key
-
cluster_child_extended_key_norm
-
h_parent_private_key
@@ -97,63 +89,73 @@
n_parent_private_key
-
-Parent Private Key
+
+Parent Private Key
-child_private_key_norm
-
-Child Private Key
+child_private_key_norm
+
+Child Private Key
-n_parent_private_key->child_private_key_norm
-
-
+n_parent_private_key->child_private_key_norm
+
+
n_parent_chain_code
-
-Parent Chain Code
+
+Parent Chain Code
-hmac_norm
-
-
-
-
-
-One-Way
-Hash
+hmac_norm
+
+
+
+
+
+One-Way
+Hash
n_parent_chain_code->hmac_norm
-
-
+
+
+
+
+n_parent_public_key
+
+Parent Public Key
+
+
+n_parent_public_key->hmac_norm
+
+
-child_chain_code_norm
-
-Child Chain Code
+child_chain_code_norm
+
+Child Chain Code
-hmac_norm->child_private_key_norm
-
-
+hmac_norm->child_private_key_norm
+
+
-hmac_norm->child_chain_code_norm
-
-
+hmac_norm->child_chain_code_norm
+
+
-i_norm
-
-Index <0x80000000
+i_norm
+
+Index <0x80000000
-i_norm->hmac_norm
-
-
+i_norm->hmac_norm
+
+