10
votes

I am trying to encode a simple String "test" back and forth.

public static String encode(Key publicKey, String data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    byte[] byteData = data.getBytes(); // convert string to byte array

    Cipher cipher = Cipher.getInstance(ALGORITHM); // create conversion processing object
    cipher.init(Cipher.ENCRYPT_MODE, publicKey); // initialize object's mode and key

    byte[] encryptedByteData = cipher.doFinal(byteData); // use object for encryption

    return new String(encryptedByteData); // convert encrypted byte array to string and return it

}

public static String decode(Key privateKey, String data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    byte[] byteData = data.getBytes(); // convert string to byte array

    Cipher cipher = Cipher.getInstance(ALGORITHM); // create conversion processing object
    cipher.init(Cipher.DECRYPT_MODE, privateKey); // initialize object's mode and key

    System.out.println(byteData.length);

    byte[] decryptedByteData = cipher.doFinal(byteData); // use object for decryption

    return new String(decryptedByteData); // convert decrypted byte array to string and return it

}

However, although the encryption works just fine (ALGORITHM is "RSA"), when trying to decrypt the string I have just gotten from encrypting "test", I get following exception:

javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes

Should I split the encrypted bytes in chunks of 256 in order to be able to decrypt it?

3

3 Answers

9
votes

You can't reliably convert random bytes to a String. The results will depend on what your default character encoding is on the machine where you run this. With many encodings, the cipher text will be corrupted, and information will be lost.

Modify your code to use a byte[] instead (the result of the 'doFinal()` method.

If you need to convert the byte[] to a character string, use an encoding like Base-64.

4
votes

From here:

The RSA algorithm can only encrypt data that has a maximum byte length of the RSA key length in bits divided with eight minus eleven padding bytes, i.e. number of maximum bytes = key length in bits / 8 - 11. If you want to encrypt larger data, then use a larger key, for example, a key with 4096 bits will allow you to encrypt 501 bytes of data.

4
votes

If you have a long data, you should either split it to data chunks that fits and encrypt / decrypt each of them (not such a good idea) or encrypt / decrypt them using a symmetric algorithm (AES / DES / RC4 / etc.), encrypt the symmetric key with the RSA public key and send both to the other side. (much better idea).

The second approach is a very common approach, since asymmetric encryption algorithms are much more expensive than symmetric algorithms (for both encryption and decryption).