示例#1
0
        /// <summary>
        /// Adds padding to the input data and returns the padded data.
        /// </summary>
        /// <param name="dataBytes">Data to be padded prior to encryption</param>
        /// <param name="params">RSA Parameters used for padding computation</param>
        /// <returns>Padded message</returns>
        public byte[] EncodeMessage(byte[] dataBytes, RSAParameters @params)
        {
            //Determine if we can add padding.
            if (dataBytes.Length > GetMaxMessageLength(@params))
            {
                throw new CryptographicException("Data length is too long.  Increase your key size or consider encrypting less data.");
            }

            int padLength = @params.N.Length - dataBytes.Length - 3;
            BigInteger biRnd = new BigInteger();
            biRnd.genRandomBits(padLength * 8, new Random(DateTime.Now.Millisecond));

            byte[] bytRandom = null;
            bytRandom = biRnd.getBytes();

            int z1 = bytRandom.Length;

            //Make sure the bytes are all > 0.
            for (int i = 0; i <= bytRandom.Length - 1; i++)
            {
                if (bytRandom[i] == 0x00)
                {
                    bytRandom[i] = 0x01;
                }
            }

            byte[] result = new byte[@params.N.Length];


            //Add the starting 0x00 byte
            result[0] = 0x00;

            //Add the version code 0x02 byte
            result[1] = 0x02;

            for (int i = 0; i <= bytRandom.Length - 1; i++)
            {
                z1 = i + 2;
                result[z1] = bytRandom[i];
            }

            //Add the trailing 0 byte after the padding.
            result[bytRandom.Length + 2] = 0x00;

            //This starting index for the unpadded data.
            int idx = bytRandom.Length + 3;

            //Copy the unpadded data to the padded byte array.
            dataBytes.CopyTo(result, idx);

            return result;
        }
示例#2
0
        /// <summary>
        /// Adds padding to the input data and returns the padded data.
        /// </summary>
        /// <param name="dataBytes">Data to be padded prior to encryption</param>
        /// <param name="params">RSA Parameters used for padding computation</param>
        /// <returns>Padded message</returns>
        public byte[] EncodeMessage(byte[] dataBytes, RSAParameters @params)
        {
            //Iterator
            int i = 0;

            //Get the size of the data to be encrypted
            m_mLen = dataBytes.Length;

            //Get the size of the public modulus (will serve as max length for cipher text)
            m_k = @params.N.Length;

            if (m_mLen > GetMaxMessageLength(@params))
            {
                throw new CryptographicException("Bad Data.");
            }

            //Generate the random octet seed (same length as hash)
            BigInteger biSeed = new BigInteger();
            biSeed.genRandomBits(m_hLen * 8, new Random());
            byte[] bytSeed = biSeed.getBytesRaw();

            //Make sure all of the bytes are greater than 0.
            for (i = 0; i <= bytSeed.Length - 1; i++)
            {
                if (bytSeed[i] == 0x00)
                {
                    //Replacing with the prime byte 17, no real reason...just picked at random.
                    bytSeed[i] = 0x17;
                }
            }

            //Mask the seed with MFG Function(SHA1 Hash)
            //This is the mask to be XOR'd with the DataBlock below.
            byte[] dbMask = Mathematics.OAEPMGF(bytSeed, m_k - m_hLen - 1, m_hLen, m_hashProvider);

            //Compute the length needed for PS (zero padding) and 
            //fill a byte array to the computed length
            int psLen = GetMaxMessageLength(@params) - m_mLen;

            //Generate the SHA1 hash of an empty L (Label).  Label is not used for this 
            //application of padding in the RSA specification.
            byte[] lHash = m_hashProvider.ComputeHash(System.Text.Encoding.UTF8.GetBytes(string.Empty.ToCharArray()));

            //Create a dataBlock which will later be masked.  The 
            //data block includes the concatenated hash(L), PS, 
            //a 0x01 byte, and the message.
            int dbLen = m_hLen + psLen + 1 + m_mLen;
            byte[] dataBlock = new byte[dbLen];

            int cPos = 0;
            //Current position

            //Add the L Hash to the data blcok
            for (i = 0; i <= lHash.Length - 1; i++)
            {
                dataBlock[cPos] = lHash[i];
                cPos += 1;
            }

            //Add the zero padding
            for (i = 0; i <= psLen - 1; i++)
            {
                dataBlock[cPos] = 0x00;
                cPos += 1;
            }

            //Add the 0x01 byte
            dataBlock[cPos] = 0x01;
            cPos += 1;

            //Add the message
            for (i = 0; i <= dataBytes.Length - 1; i++)
            {
                dataBlock[cPos] = dataBytes[i];
                cPos += 1;
            }

            //Create the masked data block.
            byte[] maskedDB = Mathematics.BitwiseXOR(dbMask, dataBlock);

            //Create the seed mask
            byte[] seedMask = Mathematics.OAEPMGF(maskedDB, m_hLen, m_hLen, m_hashProvider);

            //Create the masked seed
            byte[] maskedSeed = Mathematics.BitwiseXOR(bytSeed, seedMask);

            //Create the resulting cipher - starting with a 0 byte.
            byte[] result = new byte[@params.N.Length];
            result[0] = 0x00;

            //Add the masked seed
            maskedSeed.CopyTo(result, 1);

            //Add the masked data block
            maskedDB.CopyTo(result, maskedSeed.Length + 1);

            return result;
        }
示例#3
0
        //***********************************************************************
        // Generates a random number with the specified number of bits such
        // that gcd(number, this) = 1
        //***********************************************************************

        internal BigInteger genCoPrime(int bits, Random rand)
        {
            bool done = false;
            BigInteger result = new BigInteger();

            while (!done)
            {
                result.genRandomBits(bits, rand);

                // gcd test
                BigInteger g = result.gcd(this);
                if (g.dataLength == 1 && g.data[0] == 1)
                    done = true;
            }

            return result;
        }
示例#4
0
        //***********************************************************************
        // Generates a positive BigInteger that is probably prime.
        // Overloaded to use the isProbablePrime method with no confidence value
        //***********************************************************************

        internal static BigInteger genPseudoPrime(int bits, Random rand)
        {
            BigInteger result = new BigInteger();
            bool done = false;

            while (!done)
            {
                result.genRandomBits(bits, rand);
                result.data[0] |= 0x01;		// make it odd

                // prime test
                done = result.isProbablePrime();
            }
            return result;
        }
示例#5
0
        //***********************************************************************
        // Probabilistic prime test based on Solovay-Strassen (Euler Criterion)
        //
        // p is probably prime if for any a < p (a is not multiple of p),
        // a^((p-1)/2) mod p = J(a, p)
        //
        // where J is the Jacobi symbol.
        //
        // Otherwise, p is composite.
        //
        // Returns
        // -------
        // True if "this" is a Euler pseudoprime to randomly chosen
        // bases.  The number of chosen bases is given by the "confidence"
        // parameter.
        //
        // False if "this" is definitely NOT prime.
        //
        //***********************************************************************

        internal bool SolovayStrassenTest(int confidence)
        {
            BigInteger thisVal;
            if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
                thisVal = -this;
            else
                thisVal = this;

            if (thisVal.dataLength == 1)
            {
                // test small numbers
                if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
                    return false;
                else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
                    return true;
            }

            if ((thisVal.data[0] & 0x1) == 0)     // even numbers
                return false;


            int bits = thisVal.bitCount();
            BigInteger a = new BigInteger();
            BigInteger p_sub1 = thisVal - 1;
            BigInteger p_sub1_shift = p_sub1 >> 1;

            Random rand = new Random();

            for (int round = 0; round < confidence; round++)
            {
                bool done = false;

                while (!done)		// generate a < n
                {
                    int testBits = 0;

                    // make sure "a" has at least 2 bits
                    while (testBits < 2)
                        testBits = (int)(rand.NextDouble() * bits);

                    a.genRandomBits(testBits, rand);

                    int byteLen = a.dataLength;

                    // make sure "a" is not 0
                    if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
                        done = true;
                }

                // check whether a factor exists (fix for version 1.03)
                BigInteger gcdTest = a.gcd(thisVal);
                if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
                    return false;

                // calculate a^((p-1)/2) mod p

                BigInteger expResult = a.modPow(p_sub1_shift, thisVal);
                if (expResult == p_sub1)
                    expResult = -1;

                // calculate Jacobi symbol
                BigInteger jacob = Jacobi(a, thisVal);

                // if they are different then it is not prime
                if (expResult != jacob)
                    return false;
            }

            return true;
        }
示例#6
0
        //***********************************************************************
        // Probabilistic prime test based on Rabin-Miller's
        //
        // for any p > 0 with p - 1 = 2^s * t
        //
        // p is probably prime (strong pseudoprime) if for any a < p,
        // 1) a^t mod p = 1 or
        // 2) a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
        //
        // Otherwise, p is composite.
        //
        // Returns
        // -------
        // True if "this" is a strong pseudoprime to randomly chosen
        // bases.  The number of chosen bases is given by the "confidence"
        // parameter.
        //
        // False if "this" is definitely NOT prime.
        //
        //***********************************************************************

        internal bool RabinMillerTest(int confidence)
        {
            BigInteger thisVal;
            if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
                thisVal = -this;
            else
                thisVal = this;

            if (thisVal.dataLength == 1)
            {
                // test small numbers
                if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
                    return false;
                else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
                    return true;
            }

            if ((thisVal.data[0] & 0x1) == 0)     // even numbers
                return false;


            // calculate values of s and t
            BigInteger p_sub1 = thisVal - (new BigInteger(1));
            int s = 0;

            for (int index = 0; index < p_sub1.dataLength; index++)
            {
                uint mask = 0x01;

                for (int i = 0; i < 32; i++)
                {
                    if ((p_sub1.data[index] & mask) != 0)
                    {
                        index = p_sub1.dataLength;      // to break the outer loop
                        break;
                    }
                    mask <<= 1;
                    s++;
                }
            }

            BigInteger t = p_sub1 >> s;

            int bits = thisVal.bitCount();
            BigInteger a = new BigInteger();
            Random rand = new Random();

            for (int round = 0; round < confidence; round++)
            {
                bool done = false;

                while (!done)		// generate a < n
                {
                    int testBits = 0;

                    // make sure "a" has at least 2 bits
                    while (testBits < 2)
                        testBits = (int)(rand.NextDouble() * bits);

                    a.genRandomBits(testBits, rand);

                    int byteLen = a.dataLength;

                    // make sure "a" is not 0
                    if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
                        done = true;
                }

                // check whether a factor exists (fix for version 1.03)
                BigInteger gcdTest = a.gcd(thisVal);
                if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
                    return false;

                BigInteger b = a.modPow(t, thisVal);

                bool result = false;

                if (b.dataLength == 1 && b.data[0] == 1)         // a^t mod p = 1
                    result = true;

                for (int j = 0; result == false && j < s; j++)
                {
                    if (b == p_sub1)         // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
                    {
                        result = true;
                        break;
                    }

                    b = (b * b) % thisVal;
                }

                if (result == false)
                    return false;
            }
            return true;
        }
示例#7
0
        //***********************************************************************
        // Probabilistic prime test based on Fermat's little theorem
        //
        // for any a < p (p does not divide a) if
        //      a^(p-1) mod p != 1 then p is not prime.
        //
        // Otherwise, p is probably prime (pseudoprime to the chosen base).
        //
        // Returns
        // -------
        // True if "this" is a pseudoprime to randomly chosen
        // bases.  The number of chosen bases is given by the "confidence"
        // parameter.
        //
        // False if "this" is definitely NOT prime.
        //
        // Note - this method is fast but fails for Carmichael numbers except
        // when the randomly chosen base is a factor of the number.
        //
        //***********************************************************************

        internal bool FermatLittleTest(int confidence)
        {
            BigInteger thisVal;
            if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
                thisVal = -this;
            else
                thisVal = this;

            if (thisVal.dataLength == 1)
            {
                // test small numbers
                if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
                    return false;
                else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
                    return true;
            }

            if ((thisVal.data[0] & 0x1) == 0)     // even numbers
                return false;

            int bits = thisVal.bitCount();
            BigInteger a = new BigInteger();
            BigInteger p_sub1 = thisVal - (new BigInteger(1));
            Random rand = new Random();

            for (int round = 0; round < confidence; round++)
            {
                bool done = false;

                while (!done)		// generate a < n
                {
                    int testBits = 0;

                    // make sure "a" has at least 2 bits
                    while (testBits < 2)
                        testBits = (int)(rand.NextDouble() * bits);

                    a.genRandomBits(testBits, rand);

                    int byteLen = a.dataLength;

                    // make sure "a" is not 0
                    if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
                        done = true;
                }

                // check whether a factor exists (fix for version 1.03)
                BigInteger gcdTest = a.gcd(thisVal);
                if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
                    return false;

                // calculate a^(p-1) mod p
                BigInteger expResult = a.modPow(p_sub1, thisVal);

                int resultLen = expResult.dataLength;

                // is NOT prime is a^(p-1) mod p != 1

                if (resultLen > 1 || (resultLen == 1 && expResult.data[0] != 1))
                {
                    return false;
                }
            }

            return true;
        }