Esempio n. 1
0
        /*
         * Compute a modular exponentiation (x^e mod n). Conditions:
         * -- x[], e[] and n[] use big-endian encoding.
         * -- x[] must be numerically smaller than n[].
         * -- n[] must be odd.
         * Result is returned as a newly allocated array of bytes of
         * the same length as n[].
         */
        public static byte[] ModPow(byte[] x, byte[] e, byte[] n)
        {
            ModInt mx = new ModInt(n);

            mx.Decode(x);
            mx.Pow(e);
            return(mx.Encode());
        }
Esempio n. 2
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);
            }
        }
Esempio n. 3
0
 internal override uint Encode(byte[] dst, bool compressed)
 {
     if (dst.Length != 32)
     {
         throw new CryptoException("invalid output length");
     }
     x.Encode(u, 0, 32);
     for (int i = 0; i < 32; i++)
     {
         dst[i] = u[31 - i];
     }
     return(0xFFFFFFFF);
 }
Esempio n. 4
0
        /*
         * Create a new instance with the provided elements. The
         * constructor verifies that the provided private integer
         * is non-zero and is less than the subgroup order.
         */
        public ECPrivateKey(ECCurve curve, byte[] X)
        {
            this.curve = curve;
            ModInt ms   = new ModInt(curve.SubgroupOrder);
            uint   good = ms.Decode(X);

            good &= ~ms.IsZeroCT;
            if (good == 0)
            {
                throw new CryptoException("Invalid private key");
            }
            priv = ms.Encode();
            dpk  = null;
        }
Esempio n. 5
0
 internal override byte[] Encode(bool compressed)
 {
     ToAffine();
     if (IsInfinity)
     {
         return(new byte[1]);
     }
     if (compressed)
     {
         byte[] enc = new byte[curve.EncodedLengthCompressed];
         enc[0] = (byte)(0x02 + my.GetLSB());
         mx.Encode(enc, 1, enc.Length - 1);
         return(enc);
     }
     else
     {
         byte[] enc  = new byte[curve.EncodedLength];
         int    flen = (enc.Length - 1) >> 1;
         enc[0] = 0x04;
         mx.Encode(enc, 1, flen);
         my.Encode(enc, 1 + flen, flen);
         return(enc);
     }
 }
Esempio n. 6
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);
        }
Esempio n. 7
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);
        }
Esempio n. 8
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);
        }
Esempio n. 9
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);
            }
        }