Пример #1
0
        /*
         * Checks enforced by the constructor:
         * -- modulus is odd and at least 80-bit long
         * -- subgroup order is odd and at least 30-bit long
         * -- parameters a[] and b[] are lower than modulus
         * -- coordinates gx and gy are lower than modulus
         * -- coordinates gx and gy match curve equation
         */
        internal ECCurvePrime(string name, byte[] mod, byte[] a, byte[] b,
                              byte[] gx, byte[] gy, byte[] subgroupOrder, byte[] cofactor)
            : base(subgroupOrder, cofactor)
        {
            this.mod = mod = BigInt.NormalizeBE(mod);
            int modLen = BigInt.BitLength(mod);

            if (modLen < 80)
            {
                throw new CryptoException(
                          "Invalid curve: modulus is too small");
            }
            if ((mod[mod.Length - 1] & 0x01) == 0)
            {
                throw new CryptoException(
                          "Invalid curve: modulus is even");
            }
            int sgLen = BigInt.BitLength(subgroupOrder);

            if (sgLen < 30)
            {
                throw new CryptoException(
                          "Invalid curve: subgroup is too small");
            }
            if ((subgroupOrder[subgroupOrder.Length - 1] & 0x01) == 0)
            {
                throw new CryptoException(
                          "Invalid curve: subgroup order is even");
            }

            mp    = new ModInt(mod);
            flen  = (modLen + 7) >> 3;
            pMod4 = mod[mod.Length - 1] & 3;

            this.a = a = BigInt.NormalizeBE(a);
            this.b = b = BigInt.NormalizeBE(b);
            if (BigInt.CompareCT(a, mod) >= 0 ||
                BigInt.CompareCT(b, mod) >= 0)
            {
                throw new CryptoException(
                          "Invalid curve: out-of-range parameter");
            }
            ma = mp.Dup();
            ma.Decode(a);
            ma.Add(3);
            aIsM3 = ma.IsZero;
            ma.Sub(3);
            mb = mp.Dup();
            mb.Decode(b);

            this.gx = gx = BigInt.NormalizeBE(gx);
            this.gy = gy = BigInt.NormalizeBE(gy);
            if (BigInt.CompareCT(gx, mod) >= 0 ||
                BigInt.CompareCT(gy, mod) >= 0)
            {
                throw new CryptoException(
                          "Invalid curve: out-of-range coordinates");
            }
            MutableECPointPrime G = new MutableECPointPrime(this);

            G.Set(gx, gy, true);

            hashCode = (int)(BigInt.HashInt(mod)
                             ^ BigInt.HashInt(a) ^ BigInt.HashInt(b)
                             ^ BigInt.HashInt(gx) ^ BigInt.HashInt(gy));

            if (name == null)
            {
                name = string.Format("generic prime {0}/{1}",
                                     modLen, sgLen);
            }
            this.name = name;
        }
Пример #2
0
        public static bool VerifyRaw(ECPublicKey pk,
                                     byte[] hash, int hashOff, int hashLen,
                                     byte[] sig, int sigOff, int sigLen)
        {
            try {
                /*
                 * Get the curve.
                 */
                ECCurve curve = pk.Curve;

                /*
                 * Get r and s from signature. This also verifies
                 * that they do not exceed the subgroup order.
                 */
                if (sigLen == 0 || (sigLen & 1) != 0)
                {
                    return(false);
                }
                int    tlen = sigLen >> 1;
                ModInt oneQ = new ModInt(curve.SubgroupOrder);
                oneQ.Set(1);
                ModInt r = oneQ.Dup();
                ModInt s = oneQ.Dup();
                r.Decode(sig, sigOff, tlen);
                s.Decode(sig, sigOff + tlen, tlen);

                /*
                 * If either r or s was too large, it got set to
                 * zero. We also don't want real zeros.
                 */
                if (r.IsZero || s.IsZero)
                {
                    return(false);
                }

                /*
                 * Convert the hash value to an integer modulo q.
                 * As per FIPS 186-4, if the hash value is larger
                 * than q, then we keep the qlen leftmost bits of
                 * the hash value.
                 */
                int    qBitLength = oneQ.ModBitLength;
                int    hBitLength = hashLen << 3;
                byte[] hv;
                if (hBitLength <= qBitLength)
                {
                    hv = new byte[hashLen];
                    Array.Copy(hash, hashOff, hv, 0, hashLen);
                }
                else
                {
                    int qlen = (qBitLength + 7) >> 3;
                    hv = new byte[qlen];
                    Array.Copy(hash, hashOff, hv, 0, qlen);
                    int rs = (8 - (qBitLength & 7)) & 7;
                    BigInt.RShift(hv, rs);
                }
                ModInt z = oneQ.Dup();
                z.DecodeReduce(hv);

                /*
                 * Apply the verification algorithm:
                 *   w = 1/s mod q
                 *   u = z*w mod q
                 *   v = r*w mod q
                 *   T = u*G + v*Pub
                 *   test whether T.x mod q == r.
                 */
                /*
                 * w = 1/s mod q
                 */
                ModInt w = s.Dup();
                w.Invert();

                /*
                 * u = z*w mod q
                 */
                w.ToMonty();
                ModInt u = w.Dup();
                u.MontyMul(z);

                /*
                 * v = r*w mod q
                 */
                ModInt v = w.Dup();
                v.MontyMul(r);

                /*
                 * Compute u*G
                 */
                MutableECPoint T    = curve.MakeGenerator();
                uint           good = T.MulSpecCT(u.Encode());

                /*
                 * Compute v*iPub
                 */
                MutableECPoint M = pk.iPub.Dup();
                good &= M.MulSpecCT(v.Encode());

                /*
                 * Compute T = u*G+v*iPub
                 */
                uint nd = T.AddCT(M);
                M.DoubleCT();
                T.Set(M, ~nd);
                good &= ~T.IsInfinityCT;

                /*
                 * Get T.x, reduced modulo q.
                 * Signature is valid if and only if we get
                 * the same value as r (and we did not encounter
                 * an error previously).
                 */
                s.DecodeReduce(T.X);
                return((good & r.EqCT(s)) != 0);
            } catch (CryptoException) {
                /*
                 * Exceptions may occur if the key or signature
                 * have invalid values (non invertible, out of
                 * range...). Any such occurrence means that the
                 * signature is not valid.
                 */
                return(false);
            }
        }
Пример #3
0
 /*
  * Generate a new EC key pair in the specified curve.
  */
 public static ECPrivateKey Generate(ECCurve curve)
 {
     return(new ECPrivateKey(curve,
                             BigInt.RandIntNZ(curve.SubgroupOrder)));
 }
Пример #4
0
        /*
         * Create a new instance with the provided elements. Values are
         * in unsigned big-endian representation.
         *
         *   n    modulus
         *   e    public exponent
         *   d    private exponent
         *   p    first modulus factor
         *   q    second modulus factor
         *   dp   d mod (p-1)
         *   dq   d mod (q-1)
         *   iq   (1/q) mod p
         *
         * Rules verified by this constructor:
         *   n must be odd and at least 512 bits
         *   e must be odd
         *   p must be odd
         *   q must be odd
         *   p and q are greater than 1
         *   n is equal to p*q
         *   dp must be non-zero and lower than p-1
         *   dq must be non-zero and lower than q-1
         *   iq must be non-zero and lower than p
         *
         * This constructor does NOT verify that:
         *   p and q are prime
         *   d is equal to dp modulo p-1
         *   d is equal to dq modulo q-1
         *   dp is the inverse of e modulo p-1
         *   dq is the inverse of e modulo q-1
         *   iq is the inverse of q modulo p
         */
        public RSAPrivateKey(byte[] n, byte[] e, byte[] d,
                             byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] iq)
        {
            n  = BigInt.NormalizeBE(n);
            e  = BigInt.NormalizeBE(e);
            d  = BigInt.NormalizeBE(d);
            p  = BigInt.NormalizeBE(p);
            q  = BigInt.NormalizeBE(q);
            dp = BigInt.NormalizeBE(dp);
            dq = BigInt.NormalizeBE(dq);
            iq = BigInt.NormalizeBE(iq);

            if (n.Length < 64 || (n.Length == 64 && n[0] < 0x80))
            {
                throw new CryptoException(
                          "Invalid RSA private key (less than 512 bits)");
            }
            if (!BigInt.IsOdd(n))
            {
                throw new CryptoException(
                          "Invalid RSA private key (even modulus)");
            }
            if (!BigInt.IsOdd(e))
            {
                throw new CryptoException(
                          "Invalid RSA private key (even exponent)");
            }
            if (!BigInt.IsOdd(p) || !BigInt.IsOdd(q))
            {
                throw new CryptoException(
                          "Invalid RSA private key (even factor)");
            }
            if (BigInt.IsOne(p) || BigInt.IsOne(q))
            {
                throw new CryptoException(
                          "Invalid RSA private key (trivial factor)");
            }
            if (BigInt.Compare(n, BigInt.Mul(p, q)) != 0)
            {
                throw new CryptoException(
                          "Invalid RSA private key (bad factors)");
            }
            if (dp.Length == 0 || dq.Length == 0)
            {
                throw new CryptoException(
                          "Invalid RSA private key"
                          + " (null reduced private exponent)");
            }

            /*
             * We can temporarily modify p[] and q[] (to compute
             * p-1 and q-1) since these are freshly produced copies.
             */
            p[p.Length - 1]--;
            q[q.Length - 1]--;
            if (BigInt.Compare(dp, p) >= 0 || BigInt.Compare(dq, q) >= 0)
            {
                throw new CryptoException(
                          "Invalid RSA private key"
                          + " (oversized reduced private exponent)");
            }
            p[p.Length - 1]++;
            q[q.Length - 1]++;
            if (iq.Length == 0 || BigInt.Compare(iq, p) >= 0)
            {
                throw new CryptoException(
                          "Invalid RSA private key"
                          + " (out of range CRT coefficient)");
            }
            this.n  = n;
            this.e  = e;
            this.d  = d;
            this.p  = p;
            this.q  = q;
            this.dp = dp;
            this.dq = dq;
            this.iq = iq;
        }