Beispiel #1
0
		/**
        * Return a random BigInteger not less than 'min' and not greater than 'max'
        * 
        * @param min the least value that may be generated
        * @param max the greatest value that may be generated
        * @param random the source of randomness
        * @return a random BigInteger value in the range [min,max]
        */
		public static BigInteger CreateRandomInRange(
			BigInteger min,
			BigInteger max,
			// TODO Should have been just Random class
			SecureRandom random)
		{
			int cmp = min.CompareTo(max);
			if(cmp >= 0)
			{
				if(cmp > 0)
					throw new ArgumentException("'min' may not be greater than 'max'");

				return min;
			}

			if(min.BitLength > max.BitLength / 2)
			{
				return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
			}

			for(int i = 0; i < MaxIterations; ++i)
			{
				BigInteger x = new BigInteger(max.BitLength, random);
				if(x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
				{
					return x;
				}
			}

			// fall back to a faster (restricted) method
			return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
		}
        private static BigInteger GeneratePrivateKey(BigInteger q, SecureRandom random)
        {
            // B.1.2 Key Pair Generation by Testing Candidates
            int minWeight = q.BitLength >> 2;
            for (;;)
            {
                // TODO Prefer this method? (change test cases that used fixed random)
                // B.1.1 Key Pair Generation Using Extra Random Bits
                //BigInteger x = new BigInteger(q.BitLength + 64, random).Mod(q.Subtract(One)).Add(One);

                BigInteger x = BigIntegers.CreateRandomInRange(One, q.Subtract(One), random);
                if (WNafUtilities.GetNafWeight(x) >= minWeight)
                {
                    return x;
                }
            }
        }
Beispiel #3
0
		public DHParameters(
			BigInteger				p,
			BigInteger				g,
			BigInteger				q,
			int						m,
			int						l,
			BigInteger				j,
			DHValidationParameters	validation)
		{
			if (p == null)
				throw new ArgumentNullException("p");
			if (g == null)
				throw new ArgumentNullException("g");
			if (!p.TestBit(0))
				throw new ArgumentException("field must be an odd prime", "p");
			if (g.CompareTo(BigInteger.Two) < 0
				|| g.CompareTo(p.Subtract(BigInteger.Two)) > 0)
				throw new ArgumentException("generator must in the range [2, p - 2]", "g");
			if (q != null && q.BitLength >= p.BitLength)
				throw new ArgumentException("q too big to be a factor of (p-1)", "q");
			if (m >= p.BitLength)
				throw new ArgumentException("m value must be < bitlength of p", "m");
			if (l != 0)
			{ 
	            if (l >= p.BitLength)
                	throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l");
				if (l < m)
					throw new ArgumentException("when l value specified, it may not be less than m value", "l");
			}
			if (j != null && j.CompareTo(BigInteger.Two) < 0)
				throw new ArgumentException("subgroup factor must be >= 2", "j");

			// TODO If q, j both provided, validate p = jq + 1 ?

			this.p = p;
			this.g = g;
			this.q = q;
			this.m = m;
			this.l = l;
			this.j = j;
			this.validation = validation;
        }
Beispiel #4
0
        // Section 7.2.6 ECVP-NR, pg 35
        /**
         * return true if the value r and s represent a signature for the
         * message passed in. Generally, the order of the curve should be at
         * least as long as the hash of the message of interest, and with
         * ECNR, it *must* be at least as long.  But just in case the signer
         * applied mod(n) to the longer digest, this implementation will
         * apply mod(n) during verification.
         *
         * @param digest  the digest to be verified.
         * @param r       the r value of the signature.
         * @param s       the s value of the signature.
         * @exception DataLengthException if the digest is longer than the key allows
         */
        public bool VerifySignature(
            byte[]		message,
            BigInteger	r,
            BigInteger	s)
        {
            if (this.forSigning)
            {
                // not properly initilaized... deal with it
                throw new InvalidOperationException("not initialised for verifying");
            }

            ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
            BigInteger n = pubKey.Parameters.N;
            int nBitLength = n.BitLength;

            BigInteger e = new BigInteger(1, message);
            int eBitLength = e.BitLength;

            if (eBitLength > nBitLength)
            {
                throw new DataLengthException("input too large for ECNR key.");
            }

            // r in the range [1,n-1]
            if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
            {
                return false;
            }

            // s in the range [0,n-1]           NB: ECNR spec says 0
            if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0)
            {
                return false;
            }

            // compute P = sG + rW

            ECPoint G = pubKey.Parameters.G;
            ECPoint W = pubKey.Q;
            // calculate P using Bouncy math
            ECPoint P = ECAlgorithms.SumOfTwoMultiplies(G, s, W, r).Normalize();

            if (P.IsInfinity)
                return false;

            BigInteger x = P.AffineXCoord.ToBigInteger();
            BigInteger t = r.Subtract(x).Mod(n);

            return t.Equals(e);
        }
Beispiel #5
0
		//[Fact]
		//http://bitcoin.stackexchange.com/questions/25814/ecdsa-signature-and-the-z-value
		//http://www.nilsschneider.net/2013/01/28/recovering-bitcoin-private-keys.html
		public void PlayingWithSignatures()
		{
			var script1 = new Script("30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e01 04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff");

			var script2 = new Script("30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab01 04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff");

			var sig1 = (PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(script1).TransactionSignature.Signature);
			var sig2 = (PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(script2).TransactionSignature.Signature);

			var n = ECKey.CURVE.N;
			var z1 = new BigInteger(1, Encoders.Hex.DecodeData("c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e"));
			var z2 = new BigInteger(1, Encoders.Hex.DecodeData("17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc"));

			var z = z1.Subtract(z2);
			var s = sig1.S.Subtract(sig2.S);
			var n2 = BigInteger.Two.Pow(256).Subtract(new BigInteger("432420386565659656852420866394968145599"));

			var expected = new Key(Encoders.Hex.DecodeData("c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96"), fCompressedIn: false);

			var expectedBigInt = new NBitcoin.BouncyCastle.Math.BigInteger(1, Encoders.Hex.DecodeData("c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96"));
			var priv = (z1.Multiply(sig2.S).Subtract(z2.Multiply(sig1.S)).Mod(n)).Divide(sig1.R.Multiply(sig1.S.Subtract(sig2.S)).Mod(n));
			Assert.Equal(expectedBigInt.ToString(), priv.ToString());

		}
        /// <summary>Choose a random prime value for use with RSA</summary>
        /// <param name="bitlength">the bit-length of the returned prime</param>
        /// <param name="e">the RSA public exponent</param>
        /// <returns>a prime p, with (p-1) relatively prime to e</returns>
        protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e)
        {
            for (;;)
            {
                BigInteger p = new BigInteger(bitlength, 1, param.Random);

                if (p.Mod(e).Equals(BigInteger.One))
                    continue;

                if (!p.IsProbablePrime(param.Certainty))
                    continue;

                if (!e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One))
                    continue;

                return p;
            }
        }
		/**
		 * Procedure C
		 * procedure generates the a value from the given p,q,
		 * returning the a value.
		 */
		private BigInteger procedure_C(BigInteger p, BigInteger q)
		{
			BigInteger pSub1 = p.Subtract(BigInteger.One);
			BigInteger pSub1Divq = pSub1.Divide(q);

			for(;;)
			{
				BigInteger d = new BigInteger(p.BitLength, init_random);

				// 1 < d < p-1
				if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0)
				{
					BigInteger a = d.ModPow(pSub1Divq, p);

					if (a.CompareTo(BigInteger.One) != 0)
					{
						return a;
					}
				}
			}
		}
        /*
         * Select a high order element of the multiplicative group Zp*
         * 
         * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
         */
        internal static BigInteger SelectGenerator(BigInteger p, BigInteger q, SecureRandom random)
        {
            BigInteger pMinusTwo = p.Subtract(BigInteger.Two);
            BigInteger g;

            /*
             * (see: Handbook of Applied Cryptography 4.80)
             */
//			do
//			{
//				g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
//			}
//			while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
//				|| g.ModPow(q, p).Equals(BigInteger.One));

            /*
             * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
             */
            do
            {
                BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);

                g = h.ModPow(BigInteger.Two, p);
            }
            while (g.Equals(BigInteger.One));

            return g;
        }
Beispiel #9
0
        public BigInteger Add(
            BigInteger value)
        {
            if (this.sign == 0)
                return value;

            if (this.sign != value.sign)
            {
                if (value.sign == 0)
                    return this;

                if (value.sign < 0)
                    return Subtract(value.Negate());

                return value.Subtract(Negate());
            }

            return AddToMagnitude(value.magnitude);
        }
Beispiel #10
0
        private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu)
        {
            int xLen = x.BitLength, mLen = m.BitLength;
            if (xLen < mLen)
                return x;

            if (xLen - mLen > 1)
            {
                int k = m.magnitude.Length;

                BigInteger q1 = x.DivideWords(k - 1);
                BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here
                BigInteger q3 = q2.DivideWords(k + 1);

                BigInteger r1 = x.RemainderWords(k + 1);
                BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here
                BigInteger r3 = r2.RemainderWords(k + 1);

                x = r1.Subtract(r3);
                if (x.sign < 0)
                {
                    x = x.Add(mr);
                }
            }

            while (x.CompareTo(m) >= 0)
            {
                x = x.Subtract(m);
            }

            return x;
        }
        protected virtual BigInteger CalculateGenerator_FIPS186_3_Verifiable(IDigest d, BigInteger p, BigInteger q,
            byte[] seed, int index)
        {
            // A.2.3 Verifiable Canonical Generation of the Generator g
            BigInteger e = p.Subtract(BigInteger.One).Divide(q);
            byte[] ggen = Hex.Decode("6767656E");

            // 7. U = domain_parameter_seed || "ggen" || index || count.
            byte[] U = new byte[seed.Length + ggen.Length + 1 + 2];
            Array.Copy(seed, 0, U, 0, seed.Length);
            Array.Copy(ggen, 0, U, seed.Length, ggen.Length);
            U[U.Length - 3] = (byte)index; 

            byte[] w = new byte[d.GetDigestSize()];
            for (int count = 1; count < (1 << 16); ++count)
            {
                Inc(U);
                Hash(d, U, w);
                BigInteger W = new BigInteger(1, w);
                BigInteger g = W.ModPow(e, p);

                if (g.CompareTo(BigInteger.Two) >= 0)
                    return g;
            }

            return null;
        }
        protected virtual BigInteger CalculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r)
        {
            BigInteger e = p.Subtract(BigInteger.One).Divide(q);
            BigInteger pSub2 = p.Subtract(BigInteger.Two);

            for (;;)
            {
                BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pSub2, r);
                BigInteger g = h.ModPow(e, p);

                if (g.BitLength > 1)
                    return g;
            }
        }
        protected virtual DsaParameters GenerateParameters_FIPS186_2()
        {
            byte[] seed = new byte[20];
            byte[] part1 = new byte[20];
            byte[] part2 = new byte[20];
            byte[] u = new byte[20];
            int n = (L - 1) / 160;
            byte[] w = new byte[L / 8];

            if (!(digest is Sha1Digest))
                throw new InvalidOperationException("can only use SHA-1 for generating FIPS 186-2 parameters");

            for (;;)
            {
                random.NextBytes(seed);

                Hash(digest, seed, part1);
                Array.Copy(seed, 0, part2, 0, seed.Length);
                Inc(part2);
                Hash(digest, part2, part2);

                for (int i = 0; i != u.Length; i++)
                {
                    u[i] = (byte)(part1[i] ^ part2[i]);
                }

                u[0] |= (byte)0x80;
                u[19] |= (byte)0x01;

                BigInteger q = new BigInteger(1, u);

                if (!q.IsProbablePrime(certainty))
                    continue;

                byte[] offset = Arrays.Clone(seed);
                Inc(offset);

                for (int counter = 0; counter < 4096; ++counter)
                {
                    for (int k = 0; k < n; k++)
                    {
                        Inc(offset);
                        Hash(digest, offset, part1);
                        Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
                    }

                    Inc(offset);
                    Hash(digest, offset, part1);
                    Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);

                    w[0] |= (byte)0x80;

                    BigInteger x = new BigInteger(1, w);

                    BigInteger c = x.Mod(q.ShiftLeft(1));

                    BigInteger p = x.Subtract(c.Subtract(BigInteger.One));

                    if (p.BitLength != L)
                        continue;

                    if (p.IsProbablePrime(certainty))
                    {
                        BigInteger g = CalculateGenerator_FIPS186_2(p, q, random);

                        return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter));
                    }
                }
            }
        }