1
votes

I have problem with decryption (or maybe wrong encryption, too) of data with RSA in Java. I wanna encrypt public key with some more info in String and then decrypt this public key and encrypt with it something (I use 2048 RSA):

Encryption:

public void saveExportToFile(String fileName, BigInteger mod, BigInteger exp, String info, PublicKey puk) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(baos));
    try {
        oout.writeObject(mod);
        oout.writeObject(exp);
        oout.writeChars(info);
        oout.close();
        baos.close();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, puk);

        FileOutputStream fos = new FileOutputStream(new File(fileName));
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        byte[] data = baos.toByteArray();

        int i = 0;
        byte[] buffer = new byte[128];
        byte[] cipherData = null;
        while (i < data.length) {
            if (i+128 >= data.length) {
                buffer = new byte[data.length - i];
                System.arraycopy(data, i, buffer, 0, data.length - i);
                cipherData = cipher.doFinal(buffer);
                bos.write(cipherData);
            } else {
                System.arraycopy(data, i, buffer, 0, 128);
                cipherData = cipher.doFinal(buffer);
                bos.write(cipherData);
            }
            i += 128;
        }

        bos.close();
    } catch (Exception e) {
        throw new IOException("Unexpected error", e);
    }
}

Decryption:

public void getDataFromRSA(String sendname, PrivateKey privateKey) {
    try {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sendname)));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        int length = 0;
        int allLength = 0;
        byte[] buffer = new byte[128];
        byte[] bufferAC = null;
        byte[] outData = null;
        byte[] allData = null;
        byte[] tmpData = null;
        while ( (length = bis.read(buffer)) != -1) {
            if (length < 128) {
                bufferAC = new byte[length];
                System.arraycopy(buffer, 0, bufferAC, 0, length);
                outData = cipher.doFinal(bufferAC);
            } else {
                outData = cipher.doFinal(buffer); // HERE IS THE ERROR
            }
            allLength += outData.length;
            tmpData = allData;
            allData = new byte[allLength];
            System.arraycopy(tmpData, 0, allData, 0, tmpData.length);
            System.arraycopy(outData, 0, allData, tmpData.length, outData.length);
        }
    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException | InvalidKeySpecException e) {
        e.printStackTrace();
    }
}

EDIT OK, it seems I don't know about encryption as much as I thought. I'd like to use only RSA (if it's possible) since I don't need to transfer info more than once (size of info vary). I've edited encryption like this:

int i = 0;
byte[] buffer = new byte[245];
byte[] cipherData = null;
while (i < data.length) {
    if (i+245 >= data.length) {
        buffer = new byte[data.length - i];
        System.arraycopy(data, i, buffer, 0, data.length - i);
    } else {
        System.arraycopy(data, i, buffer, 0, 245);
    }
    cipherData = cipher.update(buffer);
    bos.write(cipherData);
    i += 245;
}
bos.write(cipher.doFinal()); // HERE IS THE ERROR
bos.close();

And now I get javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes (tried several lower values for buffer size). Is it because data length is not multiple of blocksize? Could this be fixed? Thanks for answers.

2
You should not use RSA as block cipher. In your scheme, an attacker can simply insert a previous block anywhere in your cipher without you noticing it during decryption. Hybrid encryption/decryption is not that hard, why don't you make an effort to do it right? - Maarten Bodewes
For your current problem: RSA has padding overhead, you should be putting at most 245 bytes in and decrypt per 256 bytes (11 bytes overhead). If you must, use doFinal in a loop with a 245 byte encrypt buffer and a 256 byte decrypt input buffer. Note that this does not fix your protocol, just your current implementation. - Maarten Bodewes
Thank you, I use hybrid cryptography now without problems - d3im

2 Answers

3
votes

First of all, you should be using hybrid encryption, i.e. first encrypt the data using a symmetric cipher and then encrypt the random secret with an RSA key - sending both to the receiver.

Second, you should never have to perform doFinal in a loop for a single message. Use update and a single doFinal instead.

And thirdly, 2048 bits is 256 bytes. As long as you keep trying to decrypt 128 bytes instead of 256, you will get this exception. Usually I use 2048 / Byte.SIZE instead, it makes the code more readable and will avoid mistakes.

0
votes

This exception occurs when you try to encrypt data with private key and decrypt with public key, you need to reverse this or you have to use a single key to encrypt and decrypt your data. This would solve this exception.