Esempio n. 1
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
        }
Esempio n. 2
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)
            {
                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()));
        }
Esempio n. 3
0
        protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
            : base(q)
        {
            this.m_q = q;
            this.m_r = r;
            this.m_infinity = new FpPoint(this, null, null);

            this.m_a = a;
            this.m_b = b;
            this.m_order = order;
            this.m_cofactor = cofactor;
            this.m_coord = FP_DEFAULT_COORDS;
        }
Esempio n. 4
0
        public FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
            : base(q)
        {
            this.m_q = q;
            this.m_r = FpFieldElement.CalculateResidue(q);
            this.m_infinity = new FpPoint(this, null, null);

            this.m_a = FromBigInteger(a);
            this.m_b = FromBigInteger(b);
            this.m_order = order;
            this.m_cofactor = cofactor;
            this.m_coord = FP_DEFAULT_COORDS;
        }
Esempio n. 5
0
		public static ECKey RecoverFromSignature(int recId, ECDSASignature sig, uint256 message, bool compressed)
		{
			if(recId < 0)
				throw new ArgumentException("recId should be positive");
			if(sig.R.SignValue < 0)
				throw new ArgumentException("r should be positive");
			if(sig.S.SignValue < 0)
				throw new ArgumentException("s should be positive");
			if(message == null)
				throw new ArgumentNullException("message");


			var curve = ECKey.Secp256k1;

			// 1.0 For j from 0 to h   (h == recId here and the loop is outside this function)
			//   1.1 Let x = r + jn

			var n = curve.N;
			var i = NBitcoin.BouncyCastle.Math.BigInteger.ValueOf((long)recId / 2);
			var x = sig.R.Add(i.Multiply(n));

			//   1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
			//        specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
			//   1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
			//        conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
			//        do another iteration of Step 1.
			//
			// More concisely, what these points mean is to use X as a compressed public key.
			var prime = ((FpCurve)curve.Curve).Q;
			if(x.CompareTo(prime) >= 0)
			{
				return null;
			}

			// Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities.
			// So it's encoded in the recId.
			ECPoint R = DecompressKey(x, (recId & 1) == 1);
			//   1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility).

			if(!R.Multiply(n).IsInfinity)
				return null;

			//   1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
			var e = new NBitcoin.BouncyCastle.Math.BigInteger(1, message.ToBytes());
			//   1.6. For k from 1 to 2 do the following.   (loop is outside this function via iterating recId)
			//   1.6.1. Compute a candidate public key as:
			//               Q = mi(r) * (sR - eG)
			//
			// Where mi(x) is the modular multiplicative inverse. We transform this into the following:
			//               Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
			// Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
			// ** is point multiplication and + is point addition (the EC group operator).
			//
			// We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
			// inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.

			var eInv = NBitcoin.BouncyCastle.Math.BigInteger.Zero.Subtract(e).Mod(n);
			var rInv = sig.R.ModInverse(n);
			var srInv = rInv.Multiply(sig.S).Mod(n);
			var eInvrInv = rInv.Multiply(eInv).Mod(n);
			var q = (FpPoint)ECAlgorithms.SumOfTwoMultiplies(curve.G, eInvrInv, R, srInv);
			if(compressed)
			{
				q = new FpPoint(curve.Curve, q.X, q.Y, true);
			}
			return new ECKey(q.GetEncoded(), false);
		}