public ExtKey(CCKey key, byte[] chainCode, byte depth, byte[] fingerprint, uint child)
 {
     if (key == null)
     {
         throw new ArgumentNullException(nameof(key));
     }
     if (chainCode == null)
     {
         throw new ArgumentNullException(nameof(chainCode));
     }
     if (fingerprint == null)
     {
         throw new ArgumentNullException(nameof(fingerprint));
     }
     if (fingerprint.Length != 4)
     {
         throw new ArgumentException(string.Format("The fingerprint must be {0} bytes.", 4), "fingerprint");
     }
     if (chainCode.Length != ChainCodeLength)
     {
         throw new ArgumentException(string.Format("The chain code must be {0} bytes.", ChainCodeLength), "chainCode");
     }
     this.key          = key;
     this.nDepth       = depth;
     this.nChild       = child;
     parentFingerprint = new HDFingerprint(fingerprint);
     Buffer.BlockCopy(chainCode, 0, vchChainCode, 0, ChainCodeLength);
 }
 public RootedKeyPath(HDFingerprint masterFingerprint, KeyPath keyPath)
 {
     if (keyPath == null)
     {
         throw new ArgumentNullException(nameof(keyPath));
     }
     _KeyPath           = keyPath;
     _MasterFingerprint = masterFingerprint;
 }
 public RootedKeyPath(IHDKey masterKey, KeyPath keyPath)
 {
     if (masterKey == null)
     {
         throw new ArgumentNullException(nameof(masterKey));
     }
     if (keyPath == null)
     {
         throw new ArgumentNullException(nameof(keyPath));
     }
     _KeyPath           = keyPath;
     _MasterFingerprint = new HDFingerprint(masterKey.GetPublicKey());
 }
Beispiel #4
0
 public static bool TryParse(string str, out HDFingerprint result)
 {
     if (str == null)
     {
         throw new ArgumentNullException(nameof(str));
     }
     result = default;
     if (!HexEncoder.IsWellFormed(str) || str.Length != 4 * 2)
     {
         return(false);
     }
     result = new HDFingerprint(Encoders.Hex.DecodeData(str));
     return(true);
 }
 /// <summary>
 /// Constructor. Creates an extended key from the public key and corresponding private key.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The ExtPubKey has the relevant values for child number, depth, chain code, and fingerprint.
 /// </para>
 /// </remarks>
 public ExtKey(ExtPubKey extPubKey, CCKey privateKey)
 {
     if (extPubKey == null)
     {
         throw new ArgumentNullException(nameof(extPubKey));
     }
     if (privateKey == null)
     {
         throw new ArgumentNullException(nameof(privateKey));
     }
     this.nChild            = extPubKey.nChild;
     this.nDepth            = extPubKey.nDepth;
     this.vchChainCode      = extPubKey.vchChainCode;
     this.parentFingerprint = extPubKey.parentFingerprint;
     this.key = privateKey;
 }
 public ExtPubKey(PubKey pubkey, byte[] chainCode, byte depth, HDFingerprint fingerprint, uint child)
 {
     if (pubkey == null)
     {
         throw new ArgumentNullException(nameof(pubkey));
     }
     if (chainCode == null)
     {
         throw new ArgumentNullException(nameof(chainCode));
     }
     if (chainCode.Length != ChainCodeLength)
     {
         throw new ArgumentException(string.Format("The chain code must be {0} bytes.", ChainCodeLength), "chainCode");
     }
     this.pubkey       = pubkey;
     this.nDepth       = depth;
     this.nChild       = child;
     parentFingerprint = fingerprint;
     Buffer.BlockCopy(chainCode, 0, vchChainCode, 0, ChainCodeLength);
 }
        public static bool TryParse(string str, out RootedKeyPath result)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            result = null;
            var separator = str.IndexOf('/');

            if (separator == -1)
            {
                return(false);
            }
            if (!HDFingerprint.TryParse(str.Substring(0, separator), out var fp))
            {
                return(false);
            }
            if (!KeyPath.TryParse(str.Substring(separator + 1), out var keyPath))
            {
                return(false);
            }
            result = new RootedKeyPath(fp, keyPath);
            return(true);
        }
        /// <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 = new HDFingerprint(parent.PubKey);

            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 CCKey(keyParentBytes)
            };
            return(parentExtKey);
#endif
        }
Beispiel #9
0
 public RootedKeyPath ToRootedKeyPath(HDFingerprint masterFingerprint)
 {
     return(new RootedKeyPath(masterFingerprint, this));
 }