简体   繁体   中英

Decrypt a larger text using RSA private key

I have to encrypt and decrypt a large string using RSA public key and private key. I have managed to encrypt a larger text using the following sample code

public static string Encrypt(string publicKey, string data, RsaKeyLengths length)
        {
            // full array of bytes to encrypt
            byte[] bytesToEncrypt;

            // worker byte array
            byte[] block;

            // encrypted bytes
            byte[] encryptedBytes;

            // length of bytesToEncrypt
            var dataLength = 0;

            // number of bytes in key                
            var keySize = 0;

            // maximum block length to encrypt          
            var maxLength = 0;

            // how many blocks must we encrypt to encrypt entire message?
            var iterations = 0;

            // the encrypted data
            var encryptedData = new StringBuilder();

            // instantiate the crypto provider with the correct key length
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider((int)length);

            // initialize the RSA object from the given public key
            rsaCryptoServiceProvider.FromXmlString(publicKey);

            // convert data to byte array
            bytesToEncrypt = Encoding.Unicode.GetBytes(data);

            // get length of byte array
            dataLength = bytesToEncrypt.Length;

            // convert length of key from bits to bytes
            keySize = (int)length / 8;

            // .NET RSACryptoServiceProvider uses SHA1 Hash function
            // use this to work out the maximum length to encrypt per block
            maxLength = ((keySize - 2) - (2 * SHA1.Create().ComputeHash(bytesToEncrypt).Length));

            // how many blocks do we need to encrypt?
            iterations = dataLength / maxLength;

            // encrypt block by block
            for (int index = 0; index <= iterations; index++)
            {
                // is there more than one full block of data left to encrypt?
                if ((dataLength - maxLength * index) > maxLength)
                {
                    block = new byte[maxLength];
                }
                else
                {
                    block = new byte[dataLength - maxLength * index];
                }

                // copy the required number of bytes from the array of bytes to encrypt to our worker array
                Buffer.BlockCopy(bytesToEncrypt, maxLength * index, block, 0, block.Length);

                // encrypt the current worker array block of bytes
                encryptedBytes = rsaCryptoServiceProvider.Encrypt(block, true);

                // RSACryptoServiceProvider reverses the order of encrypted bytesToEncrypt after encryption and before decryption.
                // Undo this reversal for compatibility with other implementations
                Array.Reverse(encryptedBytes);

                // convert to base 64 string
                encryptedData.Append(Convert.ToBase64String(encryptedBytes));

            }
            return encryptedData.ToString();

        }

Then I tried to decrypt the larger text using the following code

/// <summary>
        /// Encrypt an arbitrary string of data under the supplied public key
        /// </summary>
        /// <param name="publicKey">The public key to encrypt under</param>
        /// <param name="data">The data to encrypt</param>
        /// <param name="length">The bit length or strength of the public key: 1024, 2048 or 4096 bits. This must match the 
        /// value actually used to create the publicKey</param>
        /// <returns></returns>
        public static string Decrypt(string privateKey, string data, RsaKeyLengths length)
        {
            // full array of bytes to encrypt
            byte[] bytesToDecrypt;

            // worker byte array
            byte[] block;

            // encrypted bytes
            byte[] decryptedBytes;

            // length of bytesToEncrypt
            var dataLength = 0;

            // number of bytes in key                
            var keySize = 0;

            // maximum block length to encrypt          
            var maxLength = 0;

            // how many blocks must we encrypt to encrypt entire message?
            var iterations = 0;

            // the encrypted data
            var decryptedData = new StringBuilder();

            // instantiate the crypto provider with the correct key length
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider((int)length);

            // initialize the RSA object from the given public key
            rsaCryptoServiceProvider.FromXmlString(privateKey);

            // convert data to byte array
            bytesToDecrypt = Encoding.Unicode.GetBytes(data);

            // get length of byte array
            dataLength = bytesToDecrypt.Length;

            // convert length of key from bits to bytes
            keySize = (int)length / 8;

            // .NET RSACryptoServiceProvider uses SHA1 Hash function
            // use this to work out the maximum length to encrypt per block
            //maxLength = ((keySize - 2) - (2 * SHA1.Create().ComputeHash(bytesToDecrypt).Length));
            maxLength = ((keySize / 8) % 3 != 0) ?
              (((keySize / 8) / 3) * 4) + 4 : ((keySize / 8) / 3) * 4; ;

            // how many blocks do we need to encrypt?
            iterations = dataLength / maxLength;

            // encrypt block by block
            for (int index = 0; index <= iterations; index++)
            {
                // is there more than one full block of data left to encrypt?
                if ((dataLength - maxLength * index) > maxLength)
                {
                    block = new byte[maxLength];
                }
                else
                {
                    block = new byte[dataLength - maxLength * index];
                }

                // copy the required number of bytes from the array of bytes to encrypt to our worker array
                Buffer.BlockCopy(bytesToDecrypt, maxLength * index, block, 0, block.Length);

                // encrypt the current worker array block of bytes
                decryptedBytes = rsaCryptoServiceProvider.Decrypt(block, true);

                // RSACryptoServiceProvider reverses the order of encrypted bytesToEncrypt after encryption and before decryption.
                // Undo this reversal for compatibility with other implementations
                Array.Reverse(decryptedBytes);

                // convert to base 64 string
                decryptedData.Append(Convert.ToBase64String(decryptedBytes));

            }
            return decryptedData.ToString();
        }

Actually the encryption is going on smoothly. No problem with it. But when I am trying to decrypt it. I am getting the following exception

Unhandled Exception: System.Security.Cryptography.CryptographicException: Error occurred while decoding OAEP padding.

Can anybody help me out?

Use stream cipher instead and only encrypt that key for this cipher with RSA. This may help if you need RSA because of its public-private key logic and want to use the different keys for encryption and decryption. With stream cipher you would be able encrypt and decrypt gigabytes of data no problem.

RSA is normally not used for really big amounts of data.

Maybe a bit late, but I found http://tekaris.com/blog/2013/02/08/encrypting-large-data-with-asymetric-rsacryptoserviceprovider/ helpful. The trick here obviously is to split the data, encrypt and re-join the data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM