68

When calling the following function :

byte[] bytes = rsa.Encrypt(System.Text.UTF8Encoding.UTF8.GetBytes(stringToEncrypt), true);

I am now getting the error: bad length.

With a smaller string it works, any ideas what the problem could be the string I am passing is under 200 characters.

blowdart
  • 55,577
  • 12
  • 114
  • 149
JL.
  • 78,954
  • 126
  • 311
  • 459

4 Answers4

101

RSA encryption is only mean for small amounts of data, the amount of data you can encrypt is dependent on the size of the key you are using, for example for 1024 bit RSA keys, and PKCS # 1 V1.5 padding, you can encrypt 117 bytes at most, with a 2048 RSA key, you can encrypt 245 bytes.

There's a good reason for this, asymmetric encryption is computationally expensive. If you want to encrypt large amounts of data you should be using symmetric encryption. But what if you want non-repudiation? Well what you then do is use both. You create a symmetric key and exchange it using asymmetric encryption, then that safely exchanged symmetric key to encrypt your large amounts of data. This is what SSL and WS-Secure use underneath the covers.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
blowdart
  • 55,577
  • 12
  • 114
  • 149
  • Do you know off hand what .net object I should be using to encrypt strings of up to 500 characters? – JL. Sep 30 '09 at 08:43
  • Any of the symmetric algorithms. It depends what purpose you want to encrypt it for. Probably best to phrase that as another question. – blowdart Sep 30 '09 at 08:44
  • 7
    It's not just that it's computationally extensive. The RSA algorithm encrypts a specific number, producing another number. Because of the way the algorithm works, there is a maximum size to that number. The wider the key, the larger the maximum number it can encrypt. A 1024 bit key is a number 128 bytes wide, and a 2048 bit key is 256 bytes. Each can encrypt a number with a maximum width a little bit less than its own width. If the input number is too large, then the output will be the same as encrypting another number that is in range, and there's no way to tell which was the actual input. – Jonathan Gilbert Jul 19 '13 at 18:56
  • I'm getting this exception when I try to encrypt the **same** data second time. any idea what might cause this ?? – mrid Jan 22 '18 at 06:55
  • @mrid probably because the cyphertext (the encrypted output) is larger than the original plain text, so while the plain text is small enough for your algorithm, the cyphertext is not. – thinkOfaNumber Nov 05 '18 at 23:28
60

For future searches regarding RSA bad length exceptions...

You can calculate the max number of bytes which can be encrypted with a particular key size with the following:

((KeySize - 384) / 8) + 37

However, if the optimal asymmetric encryption padding (OAEP) parameter is true, as it is in the original post, the following can be used to calculate the max bytes:

((KeySize - 384) / 8) + 7

The legal key sizes are 384 thru 16384 with a skip size of 8.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
ObjectType
  • 1,159
  • 10
  • 15
  • 2
    ((KeySize - 384) / 8) + 7 doesn't work for me. See https://crypto.stackexchange.com/questions/42097/what-is-the-maximum-size-of-the-plaintext-message-for-rsa-oaep the correct formular would be: ((KeySize - 384) / 8) + 6 – Bin4ry Oct 18 '19 at 19:49
20

As explained above, the solution to the 'bad length' type exceptions is to hybridize the use of symmetric and asymmetric encryption, so that the size of the text you are encrypting is not constrained by the key size. You basically use RSA encryption to asymmetrically encrypt the random key .

For encryption:

  1. Generate a random key of the length required for symmetrical encryption technique such as AES or Rijndael.

  2. Symmetrically encrypt your text/data using AES/Rijndael using the random key generated in step 1.

  3. Using RSA, asymmetrically encrypt the random key generated in step 1.

For decryption:

  1. First decrypt the AES/Rijndael-generated random key using your private RSA key.

  2. Then decrypt the original text/data using the RSA-decrypted random key

For a demonstration, you may wish to have a look this following example in C#:

http://www.technical-recipes.com/2013/using-rsa-to-encrypt-large-data-files-in-c/

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
AndyUK
  • 3,933
  • 7
  • 42
  • 44
8

I faced the same challenge while doing 2048 RSA encryption of plain text having less than 200 characters.

In my opinion, we can achieve the target without getting into complexity of Symmetric or Asymmetric encryption, with following simple steps;

By doing so I managed to encrypt and decrypt 40x larger text

Encryption:

  1. Compress the plain text by using *Zip() method and convert into array of bytes
  2. Encrypt with RSA

Decryption:

  1. Decrypt cypher text with RSA
  2. un-compress decrypted data by using **Unzip() method

*byte[] bytes = Zip(stringToEncrypt); // Zip() method copied below

**decryptedData = Unzip(decryptedBytes); // Unzip() method copied below


public static byte[] Zip(string str)
{
    var bytes = System.Text.Encoding.UTF8.GetBytes(str);    
    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream())
    {
        using (var gs = new GZipStream(mso, CompressionMode.Compress))
        {                        
            CopyTo(msi, gs);
        }    
        return mso.ToArray();
    }
}
public static string Unzip(byte[] bytes)
{
    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream())
    {
        using (var gs = new GZipStream(msi, CompressionMode.Decompress))
        {                     
            CopyTo(gs, mso);
        }    
        return System.Text.Encoding.UTF8.GetString(mso.ToArray());
    }
}

public static void CopyTo(Stream src, Stream dest)
    {
        byte[] bytes = new byte[4096];

        int cnt;

        while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
        {
            dest.Write(bytes, 0, cnt);
        }
    }
S.ATTA.M
  • 409
  • 5
  • 10