A non-hardened private key is derived using the equations shown below. Here small case letter represents private keys and large case represents public keys. G is the generator point, c is the chain code and i is the index number of the key generated. Kpar
and cpar
together represent the extended public key. kpar
and cpar
together represents the extended privat key.
k(i) = kpar + hash(Kpar, cpar, i)
rearranging you get, kpar = k(i) - hash(Kpar, cpar, i)
Now, let us say the attacker gets his hands on k(i)
and xpub
. You can generate public keys without the need of private keys using the xpub
with the following equation: K(i) = Kpar + hash(Kpar, cpar, i)*G
(check why this equation holds below in Appendix). The attacker is going to increment the index (i) in a loop until it generates the public key associated with k(i)
. When K(i) = k(i) * G
the attacker knows the index number.
Thus with the index in his hand, he can just calculate the kpar from the equation kpar = k(i) - hash(Kpar, cpar, i)
.
Hardened keys prevent this by using the equation: k(i) = kpar + hash(kpar, cpar, i)
. So, although you get your hands on the xpub
and the k(i)
, you will not be able to reverse engineer kpar
as that variable is in the hash function which is one-way.
Appendix:
we saw above that k(i) = kpar + hash(Kpar, cpar, i)
=> k(i) *G = kpar*g + hash(Kpar, cpar, i)*G
=> K(i) = Kpar + hash(Kpar, cpar, i)*G