【问题标题】:Java Cipher AES not encrypting whole StringJava Cipher AES 不加密整个字符串
【发布时间】:2020-09-08 19:33:41
【问题描述】:

我正在尝试使用带有 AES 算法的 java Cipher 加密和解密字符串。但不知何故,它不想加密整个字符串。我的目标不是安全地加密特定的东西,我希望有人不能很容易地读取字符串(后来存储在文件中)。

为了加密,我使用以下代码:

Cipher cipher = Cipher.getInstance("AES");
byte[] input = plain.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(input);

return new String(encrypted);

为了解密,我使用以下代码:

Cipher cipher = Cipher.getInstance("AES");
byte[] input = encrypted.getBytes();
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = cipher.doFinal(input);

return new String(decrypted);

为了测试上面提到的代码,我使用了以下参数:

SecretKeySpec key = new SecretKeySpec(new byte[]{103,38,125,-67,-71,-23,-119,102,78,-3,-33,-23,-5,32,-112,-124}, "AES");
String plain = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur auctor ornare bibendum."

该测试产生加密然后再次解密的字符串:

�T���Ѩ�%���Kr sit amet, consectetur adipiscing elit. Curabitur auctor ornare bibendum.

【问题讨论】:

    标签: java encryption cryptography aes


    【解决方案1】:

    有几个问题:

    byte[] encrypted = cipher.doFinal(input);
    return new String(encrypted);
    

    问题是你不能仅仅“字符串化”一个字节数组,你需要用不同的格式来表示字节数组,比如 Base64 或 Hex。 String 仅用于可打印字符。

    Problems converting byte array to string and back to byte array

    byte[] encrypted = cipher.doFinal(input);
    return Base64.getEncoder().encodeToString(encrypted);
    

    同样的方式 - 你需要在解密之前将编码的字符串解码成一个字节数组。

    编辑:

    另一个问题 - 你应该指定完整的mode of operation

    默认情况下,如果提供了 IV(初始化向量),则“AES”参数应使用 CBC 模式,如果未定义 IV,则应使用 ECB 模式(据我所知,至少这是 Oracle JDK 的工作方式)。

    不保证适用于所有运行时。您使用的是哪个平台/jre? .由于您的第一个字节块被加扰,我假设实现使用的是随机 IV(您可以使用密码。getIV()),并且您必须在解密时传递 IV。

    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    
    IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
    SecretKey symmetricKey = new 
    SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);
    
    cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);
    

    对于 CBC,IV 必须是长度为 AES 块大小(128 位 =16 字节)的随机字节数组,并且通常的做法是在密文前面加上 IV。

    请务必了解有关正确使用加密的知识,否则您可能会得到不安全的解决方案。

    我有一个小reference project,你可以试试看。

    【讨论】:

    • "默认情况下,如果提供了 IV(初始化向量),则“AES”参数应使用 CBC 模式,如果未定义 IV,则应使用 ECB 模式(据我所知,这至少是 Oracle JDK 的工作方式)。”它没有。它只是在初始化时选择 ECB 模式,然后如果您提供 IV,则在 init 上失败。唯一懒惰的做法是根据密钥 afaik 选择提供程序。
    • @MaartenBodewes 我保持正确。但是在问题中,我看到没有提供 IV,并且第一个块被加扰,这意味着 CBC 模式正在使用错误的 IV(零向量?)。我会对 JRE 版本/平台感到好奇,因为对编码的无效使用应该比仅第一个块扰乱更大的密文部分。
    • 也可能是因为编码拙劣,密文的第一个块被破坏了,这是我唯一能想到的。可能如果密文“字符”被替换为...那么是的......很多时候你只会在完全了解询问者的实际情况时发现,有时它只是奇怪的错误复制或诸如此类。
    猜你喜欢
    • 2011-12-08
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多