AES-128-CBC在Java和Linux中是不同的

时间:2017-03-15 16:11:58

标签: java android encryption openssl aes

我想在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库来达到这个目的,但它也会给出不同的结果。

我做错了什么?或者您可能有建议选择不同的跨平台算法进行加密。

1 个答案:

答案 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");