/// <summary> /// Derives a new extended key in the hierarchy at the given path below the current key, /// by deriving the specified child at each step. /// </summary> public ExtKey Derive(KeyPath derivation) { ExtKey result = this; return(derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index))); }
/// <summary> /// Recreates the private key of the parent from the private key of the child /// combinated with the public key of the parent (hardened children cannot be /// used to recreate the parent). /// </summary> public ExtKey GetParentExtKey(ExtPubKey parent) { if (parent == null) { throw new ArgumentNullException("parent"); } if (Depth == 0) { throw new InvalidOperationException("This ExtKey is the root key of the HD tree"); } if (IsHardened) { throw new InvalidOperationException("This private key is hardened, so you can't get its parent"); } var expectedFingerPrint = parent.CalculateChildFingerprint(); if (parent.Depth != this.Depth - 1 || !expectedFingerPrint.SequenceEqual(vchFingerprint)) { throw new ArgumentException("The parent ExtPubKey is not the immediate parent of this ExtKey", "parent"); } byte[] l = null; byte[] ll = new byte[32]; byte[] lr = new byte[32]; var pubKey = parent.PubKey.ToBytes(); l = Hashes.BIP32Hash(parent.vchChainCode, nChild, pubKey[0], pubKey.SafeSubarray(1)); Array.Copy(l, ll, 32); Array.Copy(l, 32, lr, 0, 32); var ccChild = lr; BigInteger parse256LL = new BigInteger(1, ll); BigInteger N = ECKey.CURVE.N; if (!ccChild.SequenceEqual(vchChainCode)) { throw new InvalidOperationException("The derived chain code of the parent is not equal to this child chain code"); } var keyBytes = PrivateKey.ToBytes(); var key = new BigInteger(1, keyBytes); BigInteger kPar = key.Add(parse256LL.Negate()).Mod(N); var keyParentBytes = kPar.ToByteArrayUnsigned(); if (keyParentBytes.Length < 32) { keyParentBytes = new byte[32 - keyParentBytes.Length].Concat(keyParentBytes).ToArray(); } var parentExtKey = new ExtKey { vchChainCode = parent.vchChainCode, nDepth = parent.Depth, vchFingerprint = parent.Fingerprint, nChild = parent.nChild, key = new Key(keyParentBytes) }; return(parentExtKey); }
public bool IsParentOf(ExtKey childKey) { return(childKey.IsChildOf(this)); }