Пример #1
0
        internal RFC6979(IDigest h, byte[] q, byte[] x,
                         byte[] hv, int hvOff, int hvLen, bool deterministic)
        {
            if (h == null)
            {
                h = new SHA256();
            }
            else
            {
                h = h.Dup();
                h.Reset();
            }
            drbg = new HMAC_DRBG(h);
            mh   = new ModInt(q);
            qlen = mh.ModBitLength;
            int qolen = (qlen + 7) >> 3;

            this.q = new byte[qolen];
            Array.Copy(q, q.Length - qolen, this.q, 0, qolen);
            int hlen = hvLen << 3;

            if (hlen > qlen)
            {
                byte[] htmp = new byte[hvLen];
                Array.Copy(hv, hvOff, htmp, 0, hv.Length);
                BigInt.RShift(htmp, hlen - qlen);
                hv    = htmp;
                hvOff = 0;
            }
            mh.DecodeReduce(hv, hvOff, hvLen);
            ModInt mx = mh.Dup();

            mx.Decode(x);

            byte[] seed = new byte[(qolen << 1) + (deterministic ? 0 : 32)];
            mx.Encode(seed, 0, qolen);
            mh.Encode(seed, qolen, qolen);
            if (!deterministic)
            {
                RNG.GetBytes(seed, qolen << 1,
                             seed.Length - (qolen << 1));
            }
            drbg.SetSeed(seed);
        }
Пример #2
0
        /*
         * Create a new instance. It is initialized to the point at
         * infinity (represented with a 0).
         */
        internal MutableECPointCurve25519()
        {
            ECCurve25519 ccc = (ECCurve25519)EC.Curve25519;

            x  = ccc.mp.Dup();
            x1 = ccc.mp.Dup();
            x2 = ccc.mp.Dup();
            z2 = ccc.mp.Dup();
            x3 = ccc.mp.Dup();
            z3 = ccc.mp.Dup();
            a  = ccc.mp.Dup();
            aa = ccc.mp.Dup();
            b  = ccc.mp.Dup();
            bb = ccc.mp.Dup();
            c  = ccc.mp.Dup();
            d  = ccc.mp.Dup();
            e  = ccc.mp.Dup();
            u  = new byte[32];
        }
Пример #3
0
 /*
  * Create a new instance. It is initialized to the point at
  * infinity.
  */
 internal MutableECPointPrime(ECCurvePrime curve)
 {
     this.curve = curve;
     mx         = curve.mp.Dup();
     my         = curve.mp.Dup();
     mz         = curve.mp.Dup();
     mt1        = curve.mp.Dup();
     mt2        = curve.mp.Dup();
     mt3        = curve.mp.Dup();
     mt4        = curve.mp.Dup();
     mt5        = curve.mp.Dup();
     ms1        = curve.mp.Dup();
     ms2        = curve.mp.Dup();
     ms3        = curve.mp.Dup();
     ms4        = curve.mp.Dup();
     ms5        = curve.mp.Dup();
     ms6        = curve.mp.Dup();
     affine     = 0xFFFFFFFF;
 }
Пример #4
0
        /*
         * CheckValid() will verify that the prime factors are indeed
         * prime, and that all other values are correct.
         */
        public void CheckValid()
        {
            /*
             * Factors ought to be prime.
             */
            if (!BigInt.IsPrime(p) || !BigInt.IsPrime(q))
            {
                throw new CryptoException("Invalid RSA private key"
                                          + " (non-prime factor)");
            }

            /*
             * FIXME: Verify that:
             *   dp = d mod p-1
             *   e*dp = 1 mod p-1
             *   dq = d mod q-1
             *   e*dq = 1 mod q-1
             * (This is not easy with existing code because p-1 and q-1
             * are even, but ModInt tolerates only odd moduli.)
             *
             * CheckExp(p, d, dp, e);
             * CheckExp(q, d, dq, e);
             */

            /*
             * Verify that:
             *   q*iq = 1 mod p
             */
            ModInt x = new ModInt(p);
            ModInt y = x.Dup();

            x.DecodeReduce(q);
            x.ToMonty();
            y.Decode(iq);
            x.MontyMul(y);
            if (!x.IsOne)
            {
                throw new CryptoException("Invalid RSA private key"
                                          + " (wrong CRT coefficient)");
            }
        }
Пример #5
0
        /*
         * Inner function for addition. The Jacobian coordinates for
         * the operand are provided in Montogomery representation. If
         * p2affine is true, then it is guaranteed that p2z is 1
         * (converted to Montogomery).
         */
        uint AddCTInner(ModInt p2x, ModInt p2y, ModInt p2z, bool p2affine)
        {
            /*
             * In this comment, the two operands are called P1 and
             * P2. P1 is this instance; P2 is the operand. Coordinates
             * of P1 are (X1,Y1,Z1). Coordinates of P2 are (X2,Y2,Z2).
             *
             * Formulas:
             *   U1 = X1 * Z2^2
             *   U2 = X2 * Z1^2
             *   S1 = Y1 * Z2^3
             *   S2 = Y2 * Z1^3
             *   H = U2 - U1
             *   R = S2 - S1
             *   X3 = R^2 - H^3 - 2*U1*H^2
             *   Y3 = R*(U1*H^2 - X3) - S1*H^3
             *   Z3 = H*Z1*Z2
             *
             * If both P1 and P2 are 0, then the formulas yield 0,
             * which is fine. If one of P1 and P2 is 0 (but not both),
             * then we get 0 as result, which is wrong and must be
             * fixed at the end.
             *
             * If U1 == U2 and S1 == S2 then this means that either
             * P1 or P2 is 0 (or both), or P1 == P2. In the latter
             * case, the formulas are wrong and we must report
             * an error.
             *
             * If U1 == U2 and S1 != S2 then P1 + P2 = 0. We get H = 0,
             * which implies that we obtain the point at infinity,
             * which is fine.
             */

            uint P1IsZero = mz.IsZeroCT;
            uint P2IsZero = p2z.IsZeroCT;

            ToJacobian();

            /*
             * Save this value, in case the operand turns out to
             * be the point at infinity.
             */
            ms1.Set(mx);
            ms2.Set(my);
            ms3.Set(mz);

            /*
             * Compute U1 = X1*Z2^2 in t1, and S1 = Y1*Z2^3 in t3.
             */
            if (p2affine)
            {
                mt1.Set(mx);
                mt3.Set(my);
            }
            else
            {
                mt3.Set(p2z);
                mt3.MontySquare();
                mt1.Set(mx);
                mt1.MontyMul(mt3);
                mt3.MontyMul(p2z);
                mt3.MontyMul(my);
            }
            //PrintMR(" u1 = x1*z2^2", mt1);
            //PrintMR(" s1 = y1*z2^3", mt3);

            /*
             * Compute U2 = X2*Z1^2 in t2, and S2 = Y2*Z1^3 in t4.
             */
            mt4.Set(mz);
            mt4.MontySquare();
            mt2.Set(p2x);
            mt2.MontyMul(mt4);
            mt4.MontyMul(mz);
            mt4.MontyMul(p2y);
            //PrintMR(" u2 = x2*z1^2", mt2);
            //PrintMR(" s2 = y2*z1^3", mt4);

            /*
             * Compute H = U2 - U1 in t2, and R = S2 - S1 in t4.
             */
            mt2.Sub(mt1);
            mt4.Sub(mt3);
            //PrintMR(" h = u2-u1", mt2);
            //PrintMR(" r = s2-s1", mt4);

            /*
             * If both H and R are 0, then we may have a problem
             * (either P1 == P2, or P1 == 0, or P2 == 0).
             */
            uint formProb = mt2.IsZeroCT & mt4.IsZeroCT;

            /*
             * Compute U1*H^2 in t1 and H^3 in t5.
             */
            mt5.Set(mt2);
            mt5.MontySquare();
            mt1.MontyMul(mt5);
            mt5.MontyMul(mt2);
            //PrintMR(" u1*h^2", mt1);
            //PrintMR(" h^3", mt5);

            /*
             * Compute X3 = R^2 - H^3 - 2*U1*H^2.
             */
            mx.Set(mt4);
            mx.MontySquare();
            mx.Sub(mt5);
            mx.Sub(mt1);
            mx.Sub(mt1);
            //PrintMR(" x3 = r^2-h^3-2*u1*h^2", mx);

            /*
             * Compute Y3 = R*(U1*H^2 - X3) - S1*H^3.
             */
            mt1.Sub(mx);
            mt1.MontyMul(mt4);
            mt5.MontyMul(mt3);
            mt1.Sub(mt5);
            my.Set(mt1);
            //PrintMR(" y3 = r*(u1*h^2-x3)-s1*h^3", my);

            /*
             * Compute Z3 = H*Z1*Z2.
             */
            mz.MontyMul(mt2);
            if (!p2affine)
            {
                mz.MontyMul(p2z);
            }
            //PrintMR(" z3 = h*z1*z2", mz);

            /*
             * Fixup: handle the cases where P1 = 0 or P2 = 0.
             */
            mx.CondCopy(ms1, P2IsZero);
            my.CondCopy(ms2, P2IsZero);
            mz.CondCopy(ms3, P2IsZero);
            mx.CondCopy(p2x, P1IsZero);
            my.CondCopy(p2y, P1IsZero);
            mz.CondCopy(p2z, P1IsZero);

            /*
             * Report failure when P1 == P2, except when one of
             * the points was zero (or both) because that case
             * was properly handled.
             */
            return((~formProb) | P1IsZero | P2IsZero);
        }
Пример #6
0
        internal override uint MulSpecCT(byte[] n)
        {
            /*
             * Copy scalar into a temporary array (u[]) for
             * normalisation to 32 bytes and clamping.
             */
            if (n.Length > 32)
            {
                return(0);
            }
            Array.Copy(n, 0, u, 32 - n.Length, n.Length);
            for (int i = 0; i < 32 - n.Length; i++)
            {
                u[i] = 0;
            }
            u[31] &= 0xF8;
            u[0]  &= 0x7F;
            u[0]  |= 0x40;

            x1.Set(x);
            x1.ToMonty();
            x2.SetMonty(0xFFFFFFFF);
            z2.Set(0);
            x3.Set(x1);
            z3.Set(x2);
            uint   swap = 0;
            ModInt ma24 = ((ECCurve25519)EC.Curve25519).ma24;

            for (int t = 254; t >= 0; t--)
            {
                uint kt = (uint)-((u[31 - (t >> 3)] >> (t & 7)) & 1);
                swap ^= kt;
                x2.CondSwap(x3, swap);
                z2.CondSwap(z3, swap);
                swap = kt;

                a.Set(x2);
                a.Add(z2);
                aa.Set(a);
                aa.MontySquare();
                b.Set(x2);
                b.Sub(z2);
                bb.Set(b);
                bb.MontySquare();
                e.Set(aa);
                e.Sub(bb);
                c.Set(x3);
                c.Add(z3);
                d.Set(x3);
                d.Sub(z3);
                d.MontyMul(a);
                c.MontyMul(b);
                x3.Set(d);
                x3.Add(c);
                x3.MontySquare();
                z3.Set(d);
                z3.Sub(c);
                z3.MontySquare();
                z3.MontyMul(x1);
                x2.Set(aa);
                x2.MontyMul(bb);
                z2.Set(e);
                z2.MontyMul(ma24);
                z2.Add(aa);
                z2.MontyMul(e);
            }
            x2.CondSwap(x3, swap);
            z2.CondSwap(z3, swap);

            /*
             * We need to restore z2 to normal representation before
             * inversion. Then the final Montgomery multiplication
             * will cancel out with x2, which is still in Montgomery
             * representation.
             */
            z2.FromMonty();
            z2.Invert();
            x2.MontyMul(z2);

            /*
             * x2 now contains the result.
             */
            x.Set(x2);
            return(0xFFFFFFFF);
        }
Пример #7
0
 internal void Set(ModInt X, ModInt Y, bool check)
 {
     throw new CryptoException("Not implemented for Curve25519");
 }
Пример #8
0
        public static void DoPrivate(RSAPrivateKey sk,
                                     byte[] x, int off, int len)
        {
            /*
             * Check that the source array has the proper length
             * (identical to the length of the modulus).
             */
            if (len != sk.N.Length)
            {
                throw new CryptoException(
                          "Invalid source length for RSA private");
            }

            /*
             * Reduce the source value to the proper range.
             */
            ModInt mx = new ModInt(sk.N);

            mx.DecodeReduce(x, off, len);

            /*
             * Compute m1 = x^dp mod p.
             */
            ModInt m1 = new ModInt(sk.P);

            m1.Set(mx);
            m1.Pow(sk.DP);

            /*
             * Compute m2 = x^dq mod q.
             */
            ModInt m2 = new ModInt(sk.Q);

            m2.Set(mx);
            m2.Pow(sk.DQ);

            /*
             * Compute h = (m1 - m2) / q mod p.
             * (Result goes in m1.)
             */
            ModInt m3 = m1.Dup();

            m3.Set(m2);
            m1.Sub(m3);
            m3.Decode(sk.IQ);
            m1.ToMonty();
            m1.MontyMul(m3);

            /*
             * Compute m_2 + q*h. This works on plain integers, but
             * we have efficient and constant-time code for modular
             * integers, so we will do it modulo n.
             */
            m3 = mx;
            m3.Set(m1);
            m1 = m3.Dup();
            m1.Decode(sk.Q);
            m1.ToMonty();
            m3.MontyMul(m1);
            m1.Set(m2);
            m3.Add(m1);

            /*
             * Write result back in x[].
             */
            m3.Encode(x, off, len);
        }
Пример #9
0
 /*
  * Compare for equality this value with another. Comparison still
  * works if the two values use distinct moduli.
  */
 public bool Eq(ModInt b)
 {
     return(EqCT(b) != 0);
 }
Пример #10
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;
        }
Пример #11
0
        /*
         * Test an integer for primality. This function runs up to 50
         * Miller-Rabin rounds, which is a lot of overkill but ensures
         * that non-primes will be reliably detected (with overwhelming
         * probability) even with maliciously crafted inputs. "Normal"
         * non-primes will be detected most of the time at the first
         * iteration.
         *
         * This function is not constant-time.
         */
        public static bool IsPrime(byte[] x)
        {
            x = NormalizeBE(x);

            /*
             * Handle easy cases:
             *   0 is not prime
             *   small primes (one byte) are known in a constant bit-field
             *   even numbers (larger than one byte) are non-primes
             */
            if (x.Length == 0)
            {
                return(false);
            }
            if (x.Length == 1)
            {
                return(IsSmallPrime(x[0]));
            }
            if ((x[x.Length - 1] & 0x01) == 0)
            {
                return(false);
            }

            /*
             * Perform some trial divisions by small primes.
             */
            for (int sp = 3; sp < 256; sp += 2)
            {
                if (!IsSmallPrime(sp))
                {
                    continue;
                }
                int z = 0;
                foreach (byte b in x)
                {
                    z = ((z << 8) + b) % sp;
                }
                if (z == 0)
                {
                    return(false);
                }
            }

            /*
             * Run some Miller-Rabin rounds. We use as basis random
             * integers that are one byte smaller than the modulus.
             */
            ModInt xm1 = new ModInt(x);
            ModInt y   = xm1.Dup();

            y.Set(1);
            xm1.Sub(y);
            byte[] e = xm1.Encode();
            ModInt a = new ModInt(x);

            byte[] buf = new byte[x.Length - 1];
            for (int i = 0; i < 50; i++)
            {
                RNG.GetBytes(buf);
                a.Decode(buf);
                a.Pow(e);
                if (!a.IsOne)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #12
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);
            }
        }