Beispiel #1
0
        public Key Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            byte[] l  = null;
            byte[] ll = new byte[32];
            byte[] lr = new byte[32];
            if ((nChild >> 31) == 0)
            {
                var pubKey = PubKey.ToBytes();
                l = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray());
            }
            else
            {
                l = Hashes.BIP32Hash(cc, nChild, 0, this.ToBytes());
            }
            Array.Copy(l, ll, 32);
            Array.Copy(l, 32, lr, 0, 32);
            ccChild = lr;


            BigInteger parse256LL = new BigInteger(1, ll);
            BigInteger kPar       = new BigInteger(1, vch);
            BigInteger N          = ECKey.CURVE.N;

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }
            var key = parse256LL.Add(kPar).Mod(N);

            if (key == BigInteger.Zero)
            {
                throw new InvalidOperationException("You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again.");
            }
            return(new Key(key.ToByteArrayUnsigned()));
        }
        /// <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");
            }
            byte[] 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;
            var    ll = new byte[32];
            var    lr = new byte[32];

            byte[] 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);
            byte[] ccChild = lr;

            var        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");
            }

            byte[] keyBytes = PrivateKey.ToBytes();
            var    key      = new BigInteger(1, keyBytes);

            BigInteger kPar = key.Add(parse256LL.Negate()).Mod(N);

            byte[] 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);
        }
Beispiel #3
0
        public PubKey Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            if (!IsCompressed)
            {
                throw new InvalidOperationException("The pubkey must be compressed");
            }
            if ((nChild >> 31) != 0)
            {
                throw new InvalidOperationException("A public key can't derivate an hardened child");
            }
#if HAS_SPAN
            Span <byte> vout = stackalloc byte[64];
            vout.Clear();
            Span <byte> pubkey = stackalloc byte[33];
            this.ToBytes(pubkey, out _);
            Hashes.BIP32Hash(cc, nChild, pubkey[0], pubkey.Slice(1), vout);
            ccChild = new byte[32];;
            vout.Slice(32, 32).CopyTo(ccChild);
            return(new PubKey(this.ECKey.AddTweak(vout.Slice(0, 32)), true));
#else
            byte[] lr     = null;
            byte[] l      = new byte[32];
            byte[] r      = new byte[32];
            var    pubKey = ToBytes();
            lr = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray());
            Array.Copy(lr, l, 32);
            Array.Copy(lr, 32, r, 0, 32);
            ccChild = r;

            BigInteger N          = ECKey.CURVE.N;
            BigInteger parse256LL = new BigInteger(1, l);

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }

            var q = ECKey.CURVE.G.Multiply(parse256LL).Add(ECKey.GetPublicKeyParameters().Q);
            if (q.IsInfinity)
            {
                throw new InvalidOperationException("You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again.");
            }

            q = q.Normalize();
            var p = new NBitcoin.BouncyCastle.Math.EC.FpPoint(ECKey.CURVE.Curve, q.XCoord, q.YCoord, true);
            return(new PubKey(p.GetEncoded()));
#endif
        }
Beispiel #4
0
        public Key Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            byte[] l = null;
            if (nChild >> 31 == 0)
            {
                var pubKey = PubKey.ToBytes();
                l = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.SafeSubArray(1));
            }
            else
            {
                l = Hashes.BIP32Hash(cc, nChild, 0, this.ToBytes());
            }

            var ll = l.SafeSubArray(0, 32);
            var lr = l.SafeSubArray(32, 32);

            ccChild = lr;

            var parse256LL = new BigInteger(1, ll);
            var kPar       = new BigInteger(1, _vch);
            var N          = ECKey.Curve.N;

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException(
                          "You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }

            var key = parse256LL.Add(kPar).Mod(N);

            if (key == BigInteger.Zero)
            {
                throw new InvalidOperationException(
                          "You won the big prize ! this has probability lower than 1 in 2^127. Take a screenshot, and roll the dice again.");
            }

            var keyBytes = key.ToByteArrayUnsigned();

            if (keyBytes.Length < 32)
            {
                keyBytes = new byte[32 - keyBytes.Length].Concat(keyBytes).ToArray();
            }

            return(new Key(keyBytes));
        }
Beispiel #5
0
        public PubKey Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            byte[] lr = null;
            var    l  = new byte[32];
            var    r  = new byte[32];

            if (nChild >> 31 == 0)
            {
                var pubKey = ToBytes();
                lr = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray());
            }
            else
            {
                throw new InvalidOperationException("A public key can't derivate an hardened child");
            }

            Array.Copy(lr, l, 32);
            Array.Copy(lr, 32, r, 0, 32);
            ccChild = r;


            var N          = ECKey.CURVE.N;
            var parse256LL = new BigInteger(1, l);

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException(
                          "You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }

            var q = ECKey.CURVE.G.Multiply(parse256LL).Add(this.ECKey.GetPublicKeyParameters().Q);

            if (q.IsInfinity)
            {
                throw new InvalidOperationException(
                          "You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again.");
            }

            q = q.Normalize();
            var p = new FpPoint(ECKey.CURVE.Curve, q.XCoord, q.YCoord, true);

            return(new PubKey(p.GetEncoded()));
        }
Beispiel #6
0
        public PubKey Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            byte[] lr = null;
            byte[] l  = new byte[32];
            byte[] r  = new byte[32];
            if ((nChild >> 31) == 0)
            {
                var pubKey = ToBytes();
                lr = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray());
            }
            else
            {
                throw new InvalidOperationException("Impossible to derivate a child key from a hardened one");
            }
            Array.Copy(lr, l, 32);
            Array.Copy(lr, 32, r, 0, 32);
            ccChild = r;


            BigInteger N          = ECKey.CURVE.N;
            BigInteger kPar       = new BigInteger(1, this.vch);
            BigInteger parse256LL = new BigInteger(1, l);

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }

            var q = ECKey.CURVE.G.Multiply(parse256LL).Add(_Key.GetPublicKeyParameters().Q);

            if (q.IsInfinity)
            {
                throw new InvalidOperationException("You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again.");
            }

            var p = new NBitcoin.BouncyCastle.Math.EC.FpPoint(ECKey.CURVE.Curve, q.X, q.Y, true);

            return(new PubKey(p.GetEncoded()));
        }
Beispiel #7
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
        }
Beispiel #8
0
        public Key Derivate(byte[] cc, uint nChild, out byte[] ccChild)
        {
            AssertNotDisposed();
#if HAS_SPAN
            if (!IsCompressed)
            {
                throw new InvalidOperationException("The key must be compressed");
            }
            Span <byte> vout = stackalloc byte[64];
            vout.Clear();
            if ((nChild >> 31) == 0)
            {
                Span <byte> pubkey = stackalloc byte[33];
                this.PubKey.ToBytes(pubkey, out _);
                Hashes.BIP32Hash(cc, nChild, pubkey[0], pubkey.Slice(1), vout);
            }
            else
            {
                Span <byte> privkey = stackalloc byte[32];
                this._ECKey.WriteToSpan(privkey);
                Hashes.BIP32Hash(cc, nChild, 0, privkey, vout);
                privkey.Fill(0);
            }
            ccChild = new byte[32];
            vout.Slice(32, 32).CopyTo(ccChild);
            Secp256k1.ECPrivKey keyChild = _ECKey.TweakAdd(vout.Slice(0, 32));
            vout.Clear();
            return(new Key(keyChild, true));
#else
            byte[]? l = null;
            if ((nChild >> 31) == 0)
            {
                var pubKey = PubKey.ToBytes();
                l = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.SafeSubarray(1));
            }
            else
            {
                l = Hashes.BIP32Hash(cc, nChild, 0, this.ToBytes());
            }
            var ll = l.SafeSubarray(0, 32);
            var lr = l.SafeSubarray(32, 32);

            ccChild = lr;

            var parse256LL = new BigInteger(1, ll);
            var kPar       = new BigInteger(1, vch);
            var N          = ECKey.CURVE.N;

            if (parse256LL.CompareTo(N) >= 0)
            {
                throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again.");
            }
            var key = parse256LL.Add(kPar).Mod(N);
            if (key == BigInteger.Zero)
            {
                throw new InvalidOperationException("You won the big prize ! this has probability lower than 1 in 2^127. Take a screenshot, and roll the dice again.");
            }

            var keyBytes = key.ToByteArrayUnsigned();
            if (keyBytes.Length < 32)
            {
                keyBytes = new byte[32 - keyBytes.Length].Concat(keyBytes).ToArray();
            }
            return(new Key(keyBytes));
#endif
        }