Search code examples
javaencryptionrsa

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


Small RSA decryption question with Java please.

I want to meet in a secret location with a friend of mine. As we do not want anyone to eavesdrop on the secret location, I generated a RSA key pair, a private key and a public key. Note, I generated both as Strings.

        String privateKeyString = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6cXloNrocJ8s[...]LABviZm5AFCQWfke4LZo5mOS10";
        String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB[...]EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4iGwIDAQAB";

I then shared publicly my public key to my friend, who wrote this:

private static String encryptSecretLocation(String secretLocation) {
        try {
            String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB[...]EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4iGwIDAQAB"; //public key same as above
            byte[]             buffer          = Base64.getDecoder().decode(publicKeyString);
            KeyFactory         keyFactory      = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec         = new X509EncodedKeySpec(buffer);
            PublicKey          publicKey       = keyFactory.generatePublic(keySpec);
            Cipher             encryptCipher   = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] secretMessageBytes    = secretLocation.getBytes(StandardCharsets.UTF_8);
            byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
            return Base64.getEncoder().encodeToString(encryptedMessageBytes);
        } catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
            return "bad location";
        }
    }

And indeed, he managed to get some gibberish, which he sent me back

"OixtTJRXe2nDRWDBqSs9m4wN[...]17/MKpw=="

via a nice letter:

Hey, meet me at (decrypt this)

"OixtTJRXe2nDRWDBqSs9m4wN[...]17/MKpw=="

I will wait for you there tomorrow at noon! Please come alone!

I have the private key which I did not share with anyone, and was hoping to compute back the secret location with this piece of code, this is what I tried.

 public static void main(String[] args) throws Exception {
        String privateKeyString = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6cXloNrocJ8s[...]LABviZm5AFCQWfke4LZo5mOS10";
        String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB[...]EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4iGwIDAQAB";

        byte[]              buffer1       = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec1      = new PKCS8EncodedKeySpec(buffer1);
        KeyFactory          keyFactory1   = KeyFactory.getInstance("RSA");
        PrivateKey          privateKey    = (RSAPrivateKey) keyFactory1.generatePrivate(keySpec1);

        Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decryptedMessageBytes = decryptCipher.doFinal("OixtTJRXe2nDRWDBqSs9m4wN[...]17/MKpw==".getBytes(StandardCharsets.UTF_8));
        String decryptedMessage      = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
        
        System.out.println(decryptedMessage);
    }

Unfortunately, all I am getting is :

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
    at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:347)
    at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)

May I ask what is the issue, and how to compute the secret location of our meeting back please?

Thank you

P.S. Tried to make the question interesting, hope you liked it!


Solution

  • As Topaco mentioned (all credits to him) when decrypting, the ciphertext must be Base64 decoded and not UTF8 encoded:

    In my case, it was UTF8 encoded.

    Base64.getDecoder().decode("OixtTJRXe2nDRWDBqSs9m4wN[...]17/MKpw==") worked.