public ExtKey(ExtPubKey extPubKey, Key privateKey) { if(extPubKey == null) throw new ArgumentNullException("extPubKey"); if(privateKey == null) throw new ArgumentNullException("privateKey"); this.nChild = extPubKey.nChild; this.nDepth = extPubKey.nDepth; this.vchChainCode = extPubKey.vchChainCode; this.vchFingerprint = extPubKey.vchFingerprint; this.key = privateKey; }
/// <summary> /// Create the public key from this key /// </summary> /// <returns></returns> public ExtPubKey Neuter() { ExtPubKey ret = new ExtPubKey { nDepth = nDepth, vchFingerprint = vchFingerprint.ToArray(), nChild = nChild, pubkey = key.PubKey, vchChainCode = vchChainCode.ToArray() }; return ret; }
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 ExtPubKey Derive(uint index) { var result = new ExtPubKey { nDepth = (byte) (nDepth + 1), vchFingerprint = CalculateChildFingerprint(), nChild = index }; result.pubkey = pubkey.Derivate(this.vchChainCode, index, out result.vchChainCode); return result; }
public BitcoinExtPubKey(ExtPubKey key, Network network) : base(key, network) { }
public bool IsChildOf(ExtPubKey parentKey) { if(Depth != parentKey.Depth + 1) return false; return parentKey.CalculateChildFingerprint().SequenceEqual(Fingerprint); }
public bool IsParentOf(ExtPubKey childKey) { return childKey.IsChildOf(this); }
/// <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(nameof(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.PubKey.GetHDFingerPrint(); if (parent.Depth != this.Depth - 1 || expectedFingerPrint != parentFingerprint) { 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, parentFingerprint = parent.ParentFingerprint, nChild = parent.nChild, key = new Key(keyParentBytes) }; return(parentExtKey); }
public ExtPubKey Neuter() { ExtPubKey ret = new ExtPubKey(); ret.nDepth = nDepth; ret.vchFingerprint = vchFingerprint.ToArray(); ret.nChild = nChild; ret.pubkey = key.PubKey; ret.vchChainCode = vchChainCode.ToArray(); return ret; }
public ExtPubKey Derive(KeyPath derivation) { ExtPubKey result = this; return(derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index))); }
public BitcoinExtPubKey CreateBitcoinExtPubKey(ExtPubKey pubkey) { return(new BitcoinExtPubKey(pubkey, this)); }
public bool IsParentOf(ExtPubKey childKey) { return(childKey.IsChildOf(this)); }
/// <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(nameof(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.PubKey.GetHDFingerPrint(); if (parent.Depth != this.Depth - 1 || expectedFingerPrint != parentFingerprint) { throw new ArgumentException("The parent ExtPubKey is not the immediate parent of this ExtKey", "parent"); } #if HAS_SPAN Span <byte> pubkey = stackalloc byte[33]; Span <byte> l = stackalloc byte[64]; parent.PubKey.ToBytes(pubkey, out _); Hashes.BIP32Hash(parent.vchChainCode, nChild, pubkey[0], pubkey.Slice(1), l); var parse256LL = new Secp256k1.Scalar(l.Slice(0, 32), out int overflow); if (overflow != 0 || parse256LL.IsZero) { throw new InvalidOperationException("Invalid extkey (this should never happen)"); } if (!l.Slice(32, 32).SequenceEqual(vchChainCode)) { throw new InvalidOperationException("The derived chain code of the parent is not equal to this child chain code"); } var kPar = this.PrivateKey._ECKey.sec + parse256LL.Negate(); return(new ExtKey { vchChainCode = parent.vchChainCode, nDepth = parent.Depth, parentFingerprint = parent.ParentFingerprint, nChild = parent.nChild, key = new Key(new Secp256k1.ECPrivKey(kPar, this.PrivateKey._ECKey.ctx, true), true) }); #else 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, parentFingerprint = parent.ParentFingerprint, nChild = parent.nChild, key = new Key(keyParentBytes) }; return(parentExtKey); #endif }
public BitcoinExtPubKey Derive(uint index) { return(ExtPubKey.Derive(index).GetWif(Network)); }
public ExtPubKey Derive(uint nChild) { var result = new ExtPubKey(); result.nDepth = (byte)(nDepth + 1); result.vchFingerprint = pubkey.ID.ToBytes().Take(result.vchFingerprint.Length).ToArray(); result.nChild = nChild; result.pubkey = pubkey.Derivate(this.vchChainCode, nChild, out result.vchChainCode); return result; }