Search code examples
javaandroidencryptioncoldfusionaes

How to use Android AES encryption same as coldfusion encrypt


We are using coldfusion encrypt method on web.

Encrypt(plainText, key, "AES", "Hex")

And in Android we are using the encrypt method in following way:

public static String aesEncryption(String plainText, String key) {
        try {
            SecretKey secKey = new SecretKeySpec(key.getBytes(), "AES");
            Cipher aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
            aesCipher.update(plainText.getBytes());
            byte[] cipherText = aesCipher.doFinal();
            return bytesToHex(cipherText);
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }


    private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

But in Android the output of encryption doesn't match, How to use Android AES encryption same as coldfusion encrypt ?


Solution

  • Coldfusion's encrypt uses AES/ECB/PKCS5 padding by default when AES is specified as algorithm [1]. In Java/Android the provider decides which mode and padding is used if only AES is specified [2], but usually it's also AES/ECB/PKCS5 padding (like on my machine, Android 9, API 28). Therefore the specification of the algorithm is probably not the cause. Nevertheless, it would be better to use the full specification AES/ECB/PKCS5Padding in the Java code instead of AES.

    It's possible that the key from the Coldfusion code is used incorrectly in the Java code. In Coldfusion the keys are usually generated with generateSecretKey [3] which returns the key Base64 encoded. This means that in the Android code the key would first have to be Base64 decoded with:

    SecretKey secKey = new SecretKeySpec(Base64.decode(key, Base64.DEFAULT), "AES");
    

    Also, if the key was generated for AES-128, no exception would be thrown because a key is 16 bytes long and Base64 encoded just 24 bytes, which in the current Android code would generate an AES key of the same length because of

    SecretKey secKey = new SecretKeySpec(key.getBytes(), "AES"); 
    

    Thus, AES-192 would be used instead of AES-128, resulting in a different ciphertext of course.

    Update: As already mentioned in the comments, ECB is an insecure mode of operation and shouldn't be used [4]. A more secure alternative is CBC [5], which is supported in both Java/Android and Coldfusion [6]. Even more secure and modern is GCM, an authenticated encryption algorithm that guarantees both data authenticity and confidentiality [7], which, if supported, should be preferred. Here a description of further modes can be found [8].