【问题标题】:AES Decryption when writing to a file using base64 encoding使用 base64 编码写入文件时的 AES 解密
【发布时间】:2021-02-22 20:47:02
【问题描述】:

我正在实施以下步骤:

  1. Bob 使用 AES 加密消息
  2. Bob 将加密编码为 base64 字符串
  3. Bob 将字符串写入文件
  4. Alice 读取文件
  5. Alice 将字符串转换为字节
  6. Alice 解密消息

但是,我在最后一步失败了。

这是加密:

public void sendHelloWorld() {
    String msg = "hello world!";
    try {
        SecretKeySpec AesKeySpec = new SecretKeySpec(aesKeyBytes, "AES");
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, AesKeySpec);
        aesEncryptedHello = c.doFinal(msg.getBytes());
    } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    String s = new String(aesEncryptedHello, StandardCharsets.UTF_8);
    System.out.println("Message = " + s);
    sendMessage(Base64.getEncoder().encodeToString(aesEncryptedHello));
}

这是解密:

public void decryptAESMessage(byte[] encryptedMessage) {
    try {
        String s = new String(encryptedMessage, StandardCharsets.UTF_8);
        System.out.println("Message = " + s);
        SecretKeySpec AesKeySpec = new SecretKeySpec(bobAesKey, "AES");
        Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, AesKeySpec);
        byte[] aesMessage = c.doFinal(encryptedMessage);
        String message = new String(aesMessage, StandardCharsets.UTF_8);
        System.out.println("Message is " + message);
    } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    
}

这是写入文件的内容:

public void sendMessage(String msg) {
    try {
        
        FileWriter myWriter = new FileWriter(<myredactedfilepath>);
        myWriter.write(msg);
        myWriter.close();
    } catch (IOException e) {
        System.out.println("An error occurred.");}
}

这里是第 5 阶段,只是为了表明没有错过解码:

alice.decryptAESMessage(Base64.getDecoder().decode(alice.readEncryptedMessage()));

我在两端打印密钥和加密消息,它们匹配。

【问题讨论】:

  • 加密 AES/CBC/PKCS5Padding 并且 IV 丢失。解密AES/ECB/PKCS5Padding 使 ECB(请不要)或 CBC 都提供 IV 并附加到密文的开头。在解密期间解决它并使用它。这个网站上有很多这样的例子。
  • @kelalaka nooooo,不敢相信我花了这么长时间却没有注意到这一点。谢谢
  • 可能还有一些其他的错误,我没有看起来那么deeoer...
  • 不是这样,它现在可以正常工作了
  • 在这种情况下,您可以写下您的问题的答案。

标签: java encryption cryptography base64 aes


【解决方案1】:

在加密部分,您使用了AES/CBC/PKCS5Padding,这是 PKCS#5 的 CBC 操作模式 - 实际上,它是 PKCS#7 - 缺少一个 IV。 CBC 模式需要和 IV 并且应该至少是随机的。可以用

生成
SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

在解密部分,您使用了AES/ECB/PKCS5Padding。通常两者必须匹配。使用 IV 制作 ECB(请不要)或 CBC。

IV 通常附加在密文的开头。在解密过程中解决它并使用它。

另外,在解密中进行 base64 解码。这将使您的模式更加健壮。

最后说明:如果没有具体原因,首选AES-GCM,它不仅可以提供机密性,还可以提供完整性和身份验证。如果您需要粘贴 CBC,则需要额外使用 HMAC 来实现完整性和身份验证。

还有一个完整的代码示例;见Maartens answer

【讨论】:

    猜你喜欢
    • 2021-02-04
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    相关资源
    最近更新 更多