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 }
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) { byte[] 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; BigInteger 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."); } ECPoint 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())); }