Esempio n. 1
0
        public static bool VerifyRsaPKCS1(RSACryptoServiceProvider key, byte[] signature, byte[] hash, bool allowNoPadding)
        {
            var parameters = key.ExportParameters(false);

            var e            = Utils.BigIntegerFromBigEndian(parameters.Exponent, 0, parameters.Exponent.Length);
            var mod          = Utils.BigIntegerFromBigEndian(parameters.Modulus, 0, parameters.Modulus.Length);
            var m            = Utils.BigIntegerFromBigEndian(signature, 0, signature.Length);
            var decryptedArr = Utils.BigEndianFromBigInteger(BigInteger.ModPow(m, e, mod));

            /*
             * PKCS padding used in TLS 1.0/TLS 1.1:
             * 00 01 [k-3-hashlen 0xff bytes] 00 (hash)
             * OR, for only TLS 1.0, there may be no padding (or equivalently, 00 00 [k-3-hashlen 00 bytes] 00 (hash))
             * where k is the keylen
             */

            if (allowNoPadding && decryptedArr.Length <= hash.Length)
            {
                int zeros = hash.Length - decryptedArr.Length;
                for (var i = 0; i < zeros; i++)
                {
                    if (hash[i] != 0)
                    {
                        return(false);
                    }
                }
                return(Utils.ArraysEqual(decryptedArr, 0, hash, zeros, hash.Length - zeros));
            }

            if (decryptedArr.Length != parameters.Modulus.Length - 1)
            {
                return(false);
            }

            if (decryptedArr[0] != 1)
            {
                return(false);
            }

            for (var i = 1; i < decryptedArr.Length - hash.Length - 1; i++)
            {
                if (decryptedArr[i] != 0xff)
                {
                    return(false);
                }
            }
            if (decryptedArr[decryptedArr.Length - hash.Length - 1] != 0)
            {
                return(false);
            }

            return(Utils.ArraysEqual(decryptedArr, decryptedArr.Length - hash.Length, hash, 0, hash.Length));
        }
Esempio n. 2
0
        public static byte[] SignRsaPKCS1(RSACryptoServiceProvider key, byte[] hash)
        {
            // NOTE: The X509Certificate2 must be initialized with the X509KeyStorageFlags.Exportable flag
            var parameters = key.ExportParameters(true);

            var dp   = Utils.BigIntegerFromBigEndian(parameters.DP, 0, parameters.DP.Length);
            var dq   = Utils.BigIntegerFromBigEndian(parameters.DQ, 0, parameters.DQ.Length);
            var qinv = Utils.BigIntegerFromBigEndian(parameters.InverseQ, 0, parameters.InverseQ.Length);
            var p    = Utils.BigIntegerFromBigEndian(parameters.P, 0, parameters.P.Length);
            var q    = Utils.BigIntegerFromBigEndian(parameters.Q, 0, parameters.Q.Length);

            var data = new byte[parameters.D.Length - 1];

            data[0] = 1;
            for (var i = 1; i < data.Length - hash.Length - 1; i++)
            {
                data[i] = 0xff;
            }
            data[data.Length - hash.Length - 1] = 0;
            Buffer.BlockCopy(hash, 0, data, data.Length - hash.Length, hash.Length);

            var m = Utils.BigIntegerFromBigEndian(data, 0, data.Length);

            var m1 = BigInteger.ModPow(m, dp, p);
            var m2 = BigInteger.ModPow(m, dq, q);
            var h  = qinv * (m1 - m2) % p;

            if (h.Sign == -1)
            {
                h += p;
            }
            var signature = Utils.BigEndianFromBigInteger(m2 + h * q);

            Utils.ClearArray(parameters.D);
            Utils.ClearArray(parameters.DP);
            Utils.ClearArray(parameters.DQ);
            Utils.ClearArray(parameters.InverseQ);
            Utils.ClearArray(parameters.P);
            Utils.ClearArray(parameters.Q);

            return(signature);
        }