如何使用Android AES加密与coldfusion encrypt相同
How to use Android AES encryption same as coldfusion encrypt
我们在网络上使用 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加密与coldfusion
encrypt
相同?
加密需要比"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
- 是一个很好的做法。
当 AES
被指定为算法 [1]. In Java/Android the provider decides which mode and padding is used if only AES
is specified [2] 时,Coldfusion 的 encrypt
默认使用 AES/ECB/PKCS5
填充,但通常它也是 AES/ECB/PKCS5
填充(就像我的机器,Android 9,API 28)。因此算法的规范是可能不是原因。尽管如此,最好在 Java 代码中使用完整规范 AES/ECB/PKCS5Padding
而不是 AES
.
可能是 Coldfusion 代码中的密钥在 Java 代码中使用不正确。在 Coldfusion 中,密钥通常使用 generateSecretKey
[3] 生成,其中 returns 密钥采用 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,当然会产生不同的密文。
更新:正如评论中已经提到的,ECB 是一种不安全的操作模式,不应使用[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]。
我们在网络上使用 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加密与coldfusion
encrypt
相同?
加密需要比"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
- 是一个很好的做法。
当 AES
被指定为算法 [1]. In Java/Android the provider decides which mode and padding is used if only AES
is specified [2] 时,Coldfusion 的 encrypt
默认使用 AES/ECB/PKCS5
填充,但通常它也是 AES/ECB/PKCS5
填充(就像我的机器,Android 9,API 28)。因此算法的规范是可能不是原因。尽管如此,最好在 Java 代码中使用完整规范 AES/ECB/PKCS5Padding
而不是 AES
.
可能是 Coldfusion 代码中的密钥在 Java 代码中使用不正确。在 Coldfusion 中,密钥通常使用 generateSecretKey
[3] 生成,其中 returns 密钥采用 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,当然会产生不同的密文。
更新:正如评论中已经提到的,ECB 是一种不安全的操作模式,不应使用[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]。