1

I've written 2 small java applications. The first one encrypts a string with a random key and sends the key via post-request to my server. The encrypted string will be send to another server also via post-request. Now I want to access the second server manually copy the encrypted string and decrypt it using my second application. But it seems that the textArea in the second application can't handle a lot of the special symbols.

Lets go by an example: The String "TESTDATA" is AES-encrypted with MD5-digest of random generated key "28r94sabf614atuhp1rhtprq8q". The result which reaches my server would be "ïë>1Ùd›íÔâªOMT". When I paste this into the textArea of the second application and try to decrypt it it throws this exception:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at GUI.decrypt(GUI.java:108)

Here the important code of my first application:

public static void main(String[] args) {
    String data = getData();
    String key = generateKey();
    byte[] encrypted = encryptData(data, key);
    String str_encrypted = new String(encrypted);
    String url = pushToServer(str_encrypted);
}

private static byte[] encryptData(String data, String key) {

    try {
        MessageDigest md = MessageDigest.getInstance("MD5");

        md.update(key.getBytes("UTF-8"));
        byte[] digest = md.digest();

        Cipher c = Cipher.getInstance("AES");
        SecretKeySpec k = new SecretKeySpec(digest, "AES");
        c.init(Cipher.ENCRYPT_MODE, k);

        byte[] tobeencrypted = data.getBytes("UTF-8");

        return c.doFinal(tobeencrypted);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;

}

And here the important code of my second application:

btnDecrypt.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        String data = textArea.getText();
        String key = txtDecryptionkey.getText();

        textArea.setText(decrypt(data, key));

    }
});

-

private static String decrypt(String data, String key){
    try {


    MessageDigest md = MessageDigest.getInstance("MD5");

    md.update(key.getBytes("UTF-8"));
    byte[] digest = md.digest();

    Cipher c = Cipher.getInstance("AES");
    SecretKeySpec k = new SecretKeySpec(digest, "AES");
    c.init(Cipher.DECRYPT_MODE, k);

    byte[] decrypt = c.doFinal(data.getBytes("UTF-8"));

    String decrypted = new String(decrypt);

    return decrypted;
    } catch (Exception e){
        e.printStackTrace();
        return "Something went wrong";
    }
}
  • What happens if you test your crypto-code offline (without the server)? Is the encrypted text possible to decrypt? If so, you should check how to server processes the encoding. – Martin Pfeffer Jun 05 '16 at 20:25
  • 2
    You can't assume a random series of bytes will represent a valid string in UTF-8 (or pretty much any character encoding), nor that you'll get exactly the same bytes back if you go via that route. Instead of `new String(encrypted)` you should consider e.g. converting it to hex digits, or base64-encoding it, and then doing the reverse on the other side – CupawnTae Jun 05 '16 at 20:27
  • 1
    General advice: **Always use a fully qualified Cipher string.** `Cipher.getInstance("AES");` may result in different ciphers depending on the default security provider. It most likely results in `"AES/ECB/PKCS5Padding"`, but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs. – Artjom B. Jun 05 '16 at 20:30
  • 1
    @CupawnTae Thank you very much. Solved it using base64 encoding/decoding. – StackHogger Jun 05 '16 at 20:46

0 Answers0