【问题标题】:How to use Android AES encryption same as coldfusion encrypt如何使用与coldfusion加密相同的Android AES加密
【发布时间】:2019-12-27 05:55:26
【问题描述】:

我们在网络上使用coldfusion encrypt 方法。

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

Android 中,我们使用加密方法如下:

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);
    }

但是在Android 中加密的输出不匹配,如何使用Android AES 加密与coldfusionencrypt 相同?

【问题讨论】:

  • 你能发布一个 java 和 cf 输出的例子吗?使用 generateSecretKey() 生成一次性密钥。
  • 为什么使用ECB模式?它不安全。在今天的标准中,我们使用 AES-GCM 等经过身份验证的加密模式。

标签: java android encryption coldfusion aes


【解决方案1】:

AES 被指定为算法[1] 时,Coldfusion 的encrypt 默认使用AES/ECB/PKCS5 填充。在 Java/Android 中,如果仅指定 AES [2],则提供者决定使用哪种模式和填充,但通常它也是 AES/ECB/PKCS5 填充(就像在我的机器上,Android 9,API 28)。因此,算法的规范可能不是原因。不过,最好在 Java 代码中使用完整的规范 AES/ECB/PKCS5Padding 而不是 AES

Coldfusion 代码中的密钥可能在 Java 代码中使用不正确。在 Coldfusion 中,密钥通常使用 generateSecretKey [3] 生成,它返回 Base64 编码的密钥。这意味着在 Android 代码中,密钥首先必须经过 Base64 解码:

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

此外,如果密钥是为 AES-128 生成的,则不会引发异常,因为密钥长度为 16 字节,而 Base64 编码仅 24 字节,这在当前 Android 代码中会生成相同长度的 AES 密钥,因为的

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

因此,将使用 AES-192 代替 AES-128,当然会产生不同的密文。

更新:正如 cmets 中已经提到的,ECB 是一种不安全的操作模式,不应使用[4]。更安全的替代方法是 CBC [5],它在 Java/Android 和 Coldfusion [6] 中都受支持。更安全、更现代的是 GCM,这是一种经过身份验证的加密算法,可以保证数据的真实性和机密性[7],如果支持,应该是首选。这里可以找到更多模式的描述[8]

【讨论】:

  • It's possible that the key is used incorrectly 这很可能是造成差异的原因。尝试将密钥解码为 base64,它可能会起作用。一旦它工作,另请参阅using CBC instead of the default ECB 的其他建议。
  • .. 当然使用上面的建议,在两侧指定“AES/ECB/PKCS5Padding”或“AES/CBC/PKCS5Padding”以确保两端使用相同的设置。 (CF encrypt() 确实支持这个)
  • 没有建议不要使用欧洲央行?
【解决方案2】:

加密需要比“AES”更多的细节,根据符号它必须类似于:AES/CBC/PKCS7Padding,即它应该是:

Cipher.getInstance(transformation);

其中transformation 应包含[Algorithm]/[Mode]/[Padding],可能值的范围取决于基础密码。对于 Java,它是这样的:

AES/CBC/NoPadding
AES/CBC/PKCS5Padding
AES/ECB/NoPadding
AES/ECB/PKCS5Padding
DES/CBC/NoPadding
etc...

如果您在这种情况下不指定模式和填充,密码将使用默认值。

我不知道 ColdFusion 方面的默认设置是什么,无论如何我建议在 ColdFusion 和 Android 方面都使用完整规范,例如:AES/CBC/PKCS5Padding - 是一个很好的做法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2017-04-16
    • 2016-02-19
    • 2021-01-05
    相关资源
    最近更新 更多