Example #1
0
		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;
		}
Example #2
0
		/// <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;
		}
Example #3
0
		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;
		}
Example #4
0
		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;
		}
Example #5
0
 public BitcoinExtPubKey(ExtPubKey key, Network network)
     : base(key, network)
 {
 }
Example #6
0
		public bool IsChildOf(ExtPubKey parentKey)
		{
			if(Depth != parentKey.Depth + 1)
				return false;
			return parentKey.CalculateChildFingerprint().SequenceEqual(Fingerprint);
		}
Example #7
0
		public bool IsParentOf(ExtPubKey childKey)
		{
			return childKey.IsChildOf(this);
		}
Example #8
0
        /// <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);
        }
Example #9
0
 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;
 }
Example #10
0
        public ExtPubKey Derive(KeyPath derivation)
        {
            ExtPubKey result = this;

            return(derivation.Indexes.Aggregate(result, (current, index) => current.Derive(index)));
        }
Example #11
0
 public BitcoinExtPubKey CreateBitcoinExtPubKey(ExtPubKey pubkey)
 {
     return(new BitcoinExtPubKey(pubkey, this));
 }
Example #12
0
 public bool IsParentOf(ExtPubKey childKey)
 {
     return(childKey.IsChildOf(this));
 }
Example #13
0
 public BitcoinExtPubKey(ExtPubKey key, Network network)
     : base(key, network)
 {
 }
Example #14
0
        /// <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
        }
Example #15
0
 public BitcoinExtPubKey Derive(uint index)
 {
     return(ExtPubKey.Derive(index).GetWif(Network));
 }
Example #16
0
 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;
 }