我想在JAVA和Linux中进行aes-128-cbc加密,但它一直给我不同的结果。 例如,我想解码字符串" my.txt"。在Linux中我这样做:
echo -n my.txt | openssl aes-128-cbc -K 6f838655d1bd6312b224d3d1c8de4fe1 -iv 9027ce06e06dbc8b -a
我也将它编码为base64并且它给我这个结果: 86M5fwdUpQ3tbFrz0ddHJw ==
在Java中我使用这种方法:
public static String encrypt(String key, String initVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string: "
+ Base64.encodeToString(encrypted, Base64.DEFAULT));
return Base64.encodeToString(encrypted, Base64.DEFAULT);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
使用相同的数据,它给出了完全不同的结果: vgk6yxCrQ5iLFvHxMtQO7w ==
我还尝试使用aes-256-cbc,长度为32个符号。在Linux中我使用aes-256-cbc而在Android中我使用Spongy Castle库来达到这个目的,但它也会给出不同的结果。
我做错了什么?或者您可能有建议选择不同的跨平台算法进行加密。
答案 0 :(得分:2)
-K
和-iv
参数需要十六进制编码的字符串。您的密钥长度为32个字符,因此它是16个字节或128位。你的IV是16个字符长,所以它是8个字节或64位。 AES / CBC的IV必须正好是128位长。如果不是,则必须以某种方式填充。您的IV最有可能填充0x00字节以获得128位。你必须在Java中做同样的事情。
另一个问题是您将十六进制编码的密钥和IV视为文本,这意味着您将其视为256位密钥和Java中的128位IV。这可能不是你想要的。您必须在使用前解码Hex中的字符串。
让我们使用byte[] fromHex(String hexStr)
的虚构实现:
byte[] ivBytes = new byte[16];
byte[] ivBytesShort = fromHex(initVector);
System.arraycopy(ivBytesShort, 0, ivBytes, 0, ivBytesShort.length);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
SecretKeySpec skeySpec = new SecretKeySpec(fromHex(key), "AES");