コード例 #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);
        }
コード例 #2
0
        public Gost3410PublicKeyParameters(
            BigInteger			y,
            DerObjectIdentifier publicKeyParamSet)
            : base(false, publicKeyParamSet)
        {
            if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0)
                throw new ArgumentException("Invalid y for GOST3410 public key", "y");

            this.y = y;
        }
コード例 #3
0
        public Gost3410PrivateKeyParameters(
            BigInteger			x,
            DerObjectIdentifier	publicKeyParamSet)
            : base(true, publicKeyParamSet)
        {
            if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0)
                throw new ArgumentException("Invalid x for GOST3410 private key", "x");

            this.x = x;
        }
コード例 #4
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;
        }
コード例 #5
0
        /**
         * Given the domain parameters this routine generates an EC key
         * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
         */
        public AsymmetricCipherKeyPair GenerateKeyPair()
        {
            BigInteger n = parameters.N;
            BigInteger d;
            int minWeight = n.BitLength >> 2;

            for (;;)
            {
                d = new BigInteger(n.BitLength, random);

                if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0)
                    continue;

                /*
                 * Require a minimum weight of the NAF representation, since low-weight primes may be
                 * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
                 *
                 * See "The number field sieve for integers of low weight", Oliver Schirokauer.
                 */
                if (WNafUtilities.GetNafWeight(d) < minWeight)
                    continue;

                break;
            }

            ECPoint q = CreateBasePointMultiplier().Multiply(parameters.G, d);

            if (publicKeyParamSet != null)
            {
                return new AsymmetricCipherKeyPair(
                    new ECPublicKeyParameters(algorithm, q, publicKeyParamSet),
                    new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet));
            }

            return new AsymmetricCipherKeyPair(
                new ECPublicKeyParameters(algorithm, q, parameters),
                new ECPrivateKeyParameters(algorithm, d, parameters));
        }
コード例 #6
0
        public BigInteger ConvertInput(
            byte[]	inBuf,
            int		inOff,
            int		inLen)
        {
            int maxLength = (bitSize + 7) / 8;

            if (inLen > maxLength)
                throw new DataLengthException("input too large for RSA cipher.");

            BigInteger input = new BigInteger(1, inBuf, inOff, inLen);

            if (input.CompareTo(key.Modulus) >= 0)
                throw new DataLengthException("input too large for RSA cipher.");

            return input;
        }
コード例 #7
0
        public AsymmetricCipherKeyPair GenerateKeyPair()
        {
            SecureRandom random = param.Random;
            Gost3410Parameters gost3410Params = param.Parameters;

            BigInteger q = gost3410Params.Q, x;

            int minWeight = 64;
            for (;;)
            {
                x = new BigInteger(256, random);

                if (x.SignValue < 1 || x.CompareTo(q) >= 0)
                    continue;

                /*
                 * Require a minimum weight of the NAF representation, since low-weight primes may be
                 * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
                 *
                 * See "The number field sieve for integers of low weight", Oliver Schirokauer.
                 */
                if (WNafUtilities.GetNafWeight(x) < minWeight)
                    continue;

                break;
            }

            BigInteger p = gost3410Params.P;
            BigInteger a = gost3410Params.A;

            // calculate the public key.
            BigInteger y = a.ModPow(x, p);

            if (param.PublicKeyParamSet != null)
            {
                return new AsymmetricCipherKeyPair(
                    new Gost3410PublicKeyParameters(y, param.PublicKeyParamSet),
                    new Gost3410PrivateKeyParameters(x, param.PublicKeyParamSet));
            }

            return new AsymmetricCipherKeyPair(
                new Gost3410PublicKeyParameters(y, gost3410Params),
                new Gost3410PrivateKeyParameters(x, gost3410Params));
        }
コード例 #8
0
        /**
         * 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;
                    }
                }
            }
        }
コード例 #9
0
        internal static PublicKey Derivate(this PublicKey publicKey, byte[] cc, uint nChild, Network network, out byte[] ccChild)
        {
            byte[] lr = null;
            byte[] l = new byte[32];
            byte[] r = new byte[32];
            if ((nChild >> 31) == 0)
            {
                var pubKey = publicKey.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 = ECHelper.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 eq = ECHelper.Secp256k1.Curve.DecodePoint(publicKey.ToBytes());
            var publicKeyParameters = new ECPublicKeyParameters("EC", eq, ECHelper.DomainParameter);

            var q = ECHelper.CURVE.G.Multiply(parse256LL).Add(publicKeyParameters.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 BitcoinKit.BouncyCastle.Math.EC.FpPoint(ECHelper.CURVE.Curve, q.X, q.Y, true);
            return new PublicKey(p.GetEncoded(), network);
        }
コード例 #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;
        }
コード例 #11
0
        // 5.4 pg 29
        /**
         * return true if the value r and s represent a DSA signature for
         * the passed in message (for standard DSA the message should be
         * a SHA-1 hash of the real message to be verified).
         */
        public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
        {
            BigInteger n = key.Parameters.N;

            // r and s should both in the range [1,n-1]
            if (r.SignValue < 1 || s.SignValue < 1
                || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0)
            {
                return false;
            }

            BigInteger e = CalculateE(n, message);
            BigInteger c = s.ModInverse(n);

            BigInteger u1 = e.Multiply(c).Mod(n);
            BigInteger u2 = r.Multiply(c).Mod(n);

            ECPoint G = key.Parameters.G;
            ECPoint Q = ((ECPublicKeyParameters) key).Q;

            ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2).Normalize();

            if (point.IsInfinity)
                return false;

            BigInteger v = point.AffineXCoord.ToBigInteger().Mod(n);

            return v.Equals(r);
        }
コード例 #12
0
        /**
         * Set the private key.
         *
         * @param p   key parameter: field modulus
         * @param q   key parameter: subgroup order
         * @param g   key parameter: generator
         * @param x   private key
         */
        public void setPrivateKey(BigInteger p, BigInteger q,
            BigInteger g, BigInteger x)
        {
            /*
             * Perform some basic sanity checks.  We do not
             * check primality of p or q because that would
             * be too expensive.
             *
             * We reject keys where q is longer than 999 bits,
             * because it would complicate signature encoding.
             * Normal DSA keys do not have a q longer than 256
             * bits anyway.
             */
            if(p == null || q == null || g == null || x == null
                    || p.SignValue <= 0 || q.SignValue <= 0
                    || g.SignValue <= 0 || x.SignValue <= 0
                    || x.CompareTo(q) >= 0 || q.CompareTo(p) >= 0
                    || q.BitLength > 999
                    || g.CompareTo(p) >= 0 || g.BitLength == 1
                    || g.ModPow(q, p).BitLength != 1)
            {
                throw new InvalidOperationException(
                        "invalid DSA private key");
            }
            this.p = p;
            this.q = q;
            this.g = g;
            this.x = x;
            qlen = q.BitLength;
            if(q.SignValue <= 0 || qlen < 8)
            {
                throw new InvalidOperationException(
                        "bad group order: " + q);

            }
            rolen = (qlen + 7) >> 3;
            rlen = rolen * 8;

            /*
             * Convert the private exponent (x) into a sequence
             * of octets.
             */
            bx = int2octets(x);
        }
コード例 #13
0
        /**
         * return true if the value r and s represent a GOST3410 signature for
         * the passed in message (for standard GOST3410 the message should be
         * a GOST3411 hash of the real message to be verified).
         */
        public bool VerifySignature(
            byte[]		message,
            BigInteger	r,
            BigInteger	s)
        {
            byte[] mRev = new byte[message.Length]; // conversion is little-endian
            for (int i = 0; i != mRev.Length; i++)
            {
                mRev[i] = message[mRev.Length - 1 - i];
            }

            BigInteger e = new BigInteger(1, mRev);
            BigInteger n = key.Parameters.N;

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

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

            BigInteger v = e.ModInverse(n);

            BigInteger z1 = s.Multiply(v).Mod(n);
            BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n);

            ECPoint G = key.Parameters.G; // P
            ECPoint Q = ((ECPublicKeyParameters)key).Q;

            ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize();

            if (point.IsInfinity)
                return false;

            BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n);

            return R.Equals(r);
        }
コード例 #14
0
        internal static PrivateKey Derivate(this PrivateKey privateKey, byte[] cc, uint nChild, Network network, out byte[] ccChild)
        {
            byte[] l = null;
            if((nChild >> 31) == 0)
            {
                var pubKey = privateKey.GetPublicKey().ToBytes();
                l = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray());
            }
            else
            {
                l = Hashes.BIP32Hash(cc, nChild, 0, privateKey.ToBytes());
            }
            var ll = l.Take(32).ToArray();
            var lr = l.Skip(32).Take(32).ToArray();

            ccChild = lr;

            var parse256LL = new BigInteger(1, ll);
            var kPar = new BigInteger(1, privateKey.ToBytes());
            var N = ECHelper.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.");

            var keyBytes = key.ToByteArrayUnsigned();
            if(keyBytes.Length < 32)
                keyBytes = new byte[32 - keyBytes.Length].Concat(keyBytes).ToArray();

            return new PrivateKey(keyBytes, network);
        }
コード例 #15
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);
        }
コード例 #16
0
        /**
        * Process a single block using the basic ElGamal algorithm.
        *
        * @param in the input array.
        * @param inOff the offset into the input buffer where the data starts.
        * @param length the length of the data to be processed.
        * @return the result of the ElGamal process.
        * @exception DataLengthException the input block is too large.
        */
        public byte[] ProcessBlock(
            byte[]	input,
            int		inOff,
            int		length)
        {
            if (key == null)
                throw new InvalidOperationException("ElGamal engine not initialised");

            int maxLength = forEncryption
                ?	(bitSize - 1 + 7) / 8
                :	GetInputBlockSize();

            if (length > maxLength)
                throw new DataLengthException("input too large for ElGamal cipher.\n");

            BigInteger p = key.Parameters.P;

            byte[] output;
            if (key is ElGamalPrivateKeyParameters) // decryption
            {
                int halfLength = length / 2;
                BigInteger gamma = new BigInteger(1, input, inOff, halfLength);
                BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength);

                ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key;

                // a shortcut, which generally relies on p being prime amongst other things.
                // if a problem with this shows up, check the p and g values!
                BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p);

                output = m.ToByteArrayUnsigned();
            }
            else // encryption
            {
                BigInteger tmp = new BigInteger(1, input, inOff, length);

                if (tmp.BitLength >= p.BitLength)
                    throw new DataLengthException("input too large for ElGamal cipher.\n");

                ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key;

                BigInteger pSub2 = p.Subtract(BigInteger.Two);

                // TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated
                BigInteger k;
                do
                {
                    k = new BigInteger(p.BitLength, random);
                }
                while (k.SignValue == 0 || k.CompareTo(pSub2) > 0);

                BigInteger g = key.Parameters.G;
                BigInteger gamma = g.ModPow(k, p);
                BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p);

                output = new byte[this.GetOutputBlockSize()];

                // TODO Add methods to allow writing BigInteger to existing byte array?
                byte[] out1 = gamma.ToByteArrayUnsigned();
                byte[] out2 = phi.ToByteArrayUnsigned();
                out1.CopyTo(output, output.Length / 2 - out1.Length);
                out2.CopyTo(output, output.Length - out2.Length);
            }

            return output;
        }
コード例 #17
0
        public bool RabinMillerTest(int certainty, Random random)
        {
            Debug.Assert(certainty > 0);
            Debug.Assert(BitLength > 2);
            Debug.Assert(TestBit(0));

            // let n = 1 + d . 2^s
            BigInteger n = this;
            int s = n.GetLowestSetBitMaskFirst(-1 << 1);
            Debug.Assert(s >= 1);
            BigInteger r = n.ShiftRight(s);

            // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead

            BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n);
            BigInteger minusMontRadix = n.Subtract(montRadix);

            do
            {
                BigInteger a;
                do
                {
                    a = new BigInteger(n.BitLength, random);
                }
                while (a.sign == 0 || a.CompareTo(n) >= 0
                    || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix));

                BigInteger y = ModPowMonty(a, r, n, false);

                if (!y.Equals(montRadix))
                {
                    int j = 0;
                    while (!y.Equals(minusMontRadix))
                    {
                        if (++j == s)
                            return false;

                        y = ModPowMonty(y, Two, n, false);

                        if (y.Equals(montRadix))
                            return false;
                    }
                }

                certainty -= 2; // composites pass for only 1/4 possible 'a'
            }
            while (certainty > 0);

            return true;
        }