How to encrypt a large amount of data using RSA?
By ganton ~ September 19th, 2008. Filed under: .Net, C#.
Sometimes we need to encrypt a large amount data using some asymmetric key. As we all know it is impossible to encrypt more bytes than the key size (in bytes) of the key.
Padding Operating System Supported Maximum Length of rgb Parameter OAEP padding (PKCS#1 v2) Microsoft Windows XP or later. Modulus size -2 -2*hLen, where hLen is the size of the hash. Direct Encryption (PKCS#1 v1.5) Microsoft Windows 2000 or later with the high encryption pack installed. Modulus size - 11. (11 bytes is the minimum padding possible.) Direct Encryption and OAEP padding not supported Microsoft Windows 98, Microsoft Windows Millennium, or Windows 2000 or later without the high encryption pack installed. The maximum size allowed for a symmetric key.
This quote is from Microsoft description of RSACryptoServiceProvider.Encrypt and what I still cannot understand is what does this magic number “2″ mean? I’ve searched the internet and didn’t found anything.
Below I’ll provide two methods Decrypt and Encrypt which one can copy and use them.
/// <summary>
/// Encrypts data.
/// </summary>
/// <param name="data">A byte array with data to be encrypted.</param>
/// <returns>Returns encrypted data into a array of bytes.</returns>
protected byte[] Encrypt(byte[] data)
{
List<byte> array = new List<byte>();
CspParameters parameters = new CspParameters() { KeyContainerName = "my_container_name" };
using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider(parameters))
{
int maxLength = (provider.KeySize /
- (SHA1.Create().ComputeHash(data).Length * 2 + 2);
int blocksCount = data.Length / maxLength;
for (int i = 0; i <= blocksCount; i++)
{
int bytesCount = data.Length - maxLength * i;
if (bytesCount > maxLength)
{
bytesCount = maxLength;
}
byte[] block = new byte[bytesCount];
Buffer.BlockCopy(data, maxLength * i, block, 0, block.Length);
byte[] encryptedData = provider.Encrypt(block, true);
Array.Reverse(encryptedData);
array.AddRange(encryptedData);
}
}
return array.ToArray();
}
/// <summary>
/// Decrypts data.
/// </summary>
/// <param name="encryptedData">A byte array with encryoted information to be decrypted.</param>
/// <returns>Decrypted data into array of bytes.</returns>
protected byte[] Decrypt(byte[] encryptedData)
{
CspParameters parameters = new CspParameters() { KeyContainerName = "my_container_name" };
List<byte> array = new List<byte>();
using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider(parameters))
{
int keySize = provider.KeySize / 8;
int blocksCount = encryptedData.Length / keySize;
for (int i = 0; i < blocksCount; i++)
{
int bytesCount = encryptedData.Length - keySize * i;
if (bytesCount > keySize)
{
bytesCount = keySize;
}
byte[] block = new byte[bytesCount];
Buffer.BlockCopy(encryptedData, keySize * i, block, 0, block.Length);
Array.Reverse(block);
byte[] decryptedData = provider.Decrypt(block, true);
array.AddRange(decryptedData);
}
}
return array.ToArray();
}
Note that I use padding of type OAEP padding (PKCS#1 v2) but if you change it you should also change the way maxLength is calculated.