Exemplo n.º 1
0
        public static byte[] SignRaw(ECPrivateKey sk, IDigest rfc6979Hash,
                                     byte[] hash, int hashOff, int hashLen)
        {
            ECCurve curve = sk.Curve;

            byte[]  q  = curve.SubgroupOrder;
            RFC6979 rf = new RFC6979(rfc6979Hash, q, sk.X,
                                     hash, hashOff, hashLen, rfc6979Hash != null);
            ModInt mh = rf.GetHashMod();
            ModInt mx = mh.Dup();

            mx.Decode(sk.X);

            /*
             * Compute DSA signature. We use a loop to enumerate
             * candidates for k until a proper one is found (it
             * is VERY improbable that we may have to loop).
             */
            ModInt mr = mh.Dup();
            ModInt ms = mh.Dup();
            ModInt mk = mh.Dup();

            byte[] k = new byte[q.Length];
            for (;;)
            {
                rf.NextK(k);
                MutableECPoint G = curve.MakeGenerator();
                if (G.MulSpecCT(k) == 0)
                {
                    /*
                     * We may get an error here only if the
                     * curve is invalid (generator does not
                     * produce the expected subgroup).
                     */
                    throw new CryptoException(
                              "Invalid EC private key / curve");
                }
                mr.DecodeReduce(G.X);
                if (mr.IsZero)
                {
                    continue;
                }
                ms.Set(mx);
                ms.ToMonty();
                ms.MontyMul(mr);
                ms.Add(mh);
                mk.Decode(k);
                mk.Invert();
                ms.ToMonty();
                ms.MontyMul(mk);

                byte[] sig = new byte[q.Length << 1];
                mr.Encode(sig, 0, q.Length);
                ms.Encode(sig, q.Length, q.Length);
                return(sig);
            }
        }
Exemplo n.º 2
0
 /*
  * Given a value X in sx, this method computes X^3+aX+b into sd.
  * 'sx' is unmodified. 'st' is modified (it receives a*X).
  * The sx, sd and st instances MUST be distinct.
  */
 internal void RebuildY2(ModInt sx, ModInt sd, ModInt st)
 {
     sd.Set(sx);
     sd.ToMonty();
     st.Set(sd);
     sd.MontySquare();
     sd.MontyMul(sx);
     st.MontyMul(ma);
     sd.Add(st);
     sd.Add(mb);
 }
Exemplo n.º 3
0
        /*
         * Convert to affine coordinates (if not already done).
         */
        void ToAffine()
        {
            if (affine != 0)
            {
                return;
            }

            /*
             * Divisions are expensive, so we want to make only one,
             * not two. This involves some games with Montgomery
             * representation.
             *
             * A number a in Montgomery representation means that
             * the value we have is equal to aR. Montgomery
             * multiplication of a by b yields ab/R (so, if we
             * apply it to aR and bR, we get abR).
             */

            /* Save Z*R in mt1. */
            mt1.Set(mz);

            /* Compute Z^3 in mz. */
            mz.MontySquare();
            mz.MontyMul(mt1);
            mz.FromMonty();

            /* Compute t2 = 1/Z^3. */
            mt2.Set(mz);
            mt2.Invert();
            uint cc = ~mt2.IsZeroCT;

            /* Compute y. */
            my.MontyMul(mt2);

            /* Compute t2 = 1/Z^2. */
            mt2.MontyMul(mt1);

            /* Compute x. */
            mx.MontyMul(mt2);

            /*
             * If the point is infinity (division by Z^2 failed),
             * then set all coordinates to 0. Otherwise, set mz
             * to exactly 1.
             */
            mx.CondCopy(curve.mp, ~cc);
            my.CondCopy(curve.mp, ~cc);
            mz.Set((int)cc & 1);

            affine = 0xFFFFFFFF;
        }
Exemplo n.º 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)");
            }
        }
Exemplo n.º 5
0
        internal override void DoubleCT()
        {
            ToJacobian();

            /*
             * Formulas are:
             *   S = 4*X*Y^2
             *   M = 3*X^2 + a*Z^4
             *   X' = M^2 - 2*S
             *   Y' = M*(S - X') - 8*Y^4
             *   Z' = 2*Y*Z
             *
             * These formulas also happen to work properly (with our
             * chosen representation) when the source point has
             * order 2 (Y = 0 implies Z' = 0) and when the source
             * point is already the point at infinity (Z = 0 implies
             * Z' = 0).
             *
             * When a = -3, the value of M can be computed with the
             * more efficient formula:
             *   M = 3*(X+Z^2)*(X-Z^2)
             */

            /*
             * Compute M in t1.
             */
            if (curve.aIsM3)
            {
                /*
                 * Set t1 = Z^2.
                 */
                mt1.Set(mz);
                mt1.MontySquare();

                /*
                 * Set t2 = X-Z^2 and then t1 = X+Z^2.
                 */
                mt2.Set(mx);
                mt2.Sub(mt1);
                mt1.Add(mx);

                /*
                 * Set t1 = 3*(X+Z^2)*(X-Z^2).
                 */
                mt1.MontyMul(mt2);
                mt2.Set(mt1);
                mt1.Add(mt2);
                mt1.Add(mt2);
            }
            else
            {
                /*
                 * Set t1 = 3*X^2.
                 */
                mt1.Set(mx);
                mt1.MontySquare();
                mt2.Set(mt1);
                mt1.Add(mt2);
                mt1.Add(mt2);

                /*
                 * Set t2 = a*Z^4.
                 */
                mt2.Set(mz);
                mt2.MontySquare();
                mt2.MontySquare();
                mt2.MontyMul(curve.ma);

                /*
                 * Set t1 = 3*X^2 + a*Z^4.
                 */
                mt1.Add(mt2);
            }

            /*
             * Compute S = 4*X*Y^2 in t2. We also save 2*Y^2 in mt3.
             */
            mt2.Set(my);
            mt2.MontySquare();
            mt2.Add(mt2);
            mt3.Set(mt2);
            mt2.Add(mt2);
            mt2.MontyMul(mx);

            /*
             * Compute X' = M^2 - 2*S.
             */
            mx.Set(mt1);
            mx.MontySquare();
            mx.Sub(mt2);
            mx.Sub(mt2);

            /*
             * Compute Z' = 2*Y*Z.
             */
            mz.MontyMul(my);
            mz.Add(mz);

            /*
             * Compute Y' = M*(S - X') - 8*Y^4. We already have
             * 4*Y^2 in t3.
             */
            mt2.Sub(mx);
            mt2.MontyMul(mt1);
            mt3.MontySquare();
            mt3.Add(mt3);
            my.Set(mt2);
            my.Sub(mt3);
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
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);
            }
        }