【问题标题】:BadPaddingException when decrypting using a different Cipher object使用不同的 Cipher 对象解密时出现 BadPaddingException
【发布时间】:2023-04-09 23:35:01
【问题描述】:

请原谅黑客工作!在编码方面仍然是新手,并且正在利用大量系统输出进行故障排除,这是我在 StackOverflow 上的第一篇文章。感谢您的帮助!

所以我一直在努力尝试使用 javax.crypto.Cipher API 加密 String 对象,并且我发现了一些成功,但前提是它使用的是 Cipher 对象的相同实例。但是,就我的项目而言,我正在对文本文件中的文本(字符串)进行加密和解密,并且不会每次都访问同一个 Cipher 对象。

我相信问题不在于字节数组和字符串之间的转换,因为 Base64 编码器似乎已经解决了这个问题。字节数组的输出是相同的预编码和后解码,因此应该在解密阶段将其隔离为一个问题。有什么办法让我的 decryptPW 方法可以使用不同的 Cipher 实例(传递相同的参数)而不触发 BadPaddingException?

private static String encryptPW(String pw){
    byte[] pwBytes = pw.getBytes();
    byte[] keyBytes = "0123456789abcdef".getBytes();
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    try {
        Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
        ciph.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedBytes = ciph.doFinal(pwBytes);
        pw = Base64.getEncoder().encodeToString(ciph.doFinal(pwBytes));

        for (byte b : encryptedBytes){
            System.out.print(b);
        }
        System.out.println();
    } catch (Exception e){
        e.printStackTrace();
    }
    return pw;
}

private static String decryptPW(String pw){
    byte[] pwBytes = Base64.getDecoder().decode(pw.getBytes());
    for (byte b : pwBytes){
        System.out.print(b);
    }
    System.out.println();

    byte[] keyBytes = "0123456789abcdef".getBytes();
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    try {
        Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
        ciph.init(Cipher.DECRYPT_MODE, keySpec, ciph.getParameters());
        pw = new String(ciph.doFinal(pwBytes));    
    } catch (Exception e){
        e.printStackTrace();
    }
    return pw;
}

再次感谢您!

【问题讨论】:

  • 为什么要以不同的方式初始化两个 Cipher 对象?而且我不只是回到密码模式。
  • 您好 EJP,对于 decryptPW 方法,我使用不同的参数调用 Cipher.init 方法,因为如果我不输入第三个参数,它会引发此异常:java.security.InvalidKeyException: Parameters失踪
  • 那么为什么不两次都提出这个论点呢?
  • 刚刚试了一下。给出相同的异常:javax.crypto.BadPaddingException:给定最终块未正确填充
  • 永远不要加密密码,对它们进行哈希处理。您的网站/应用程序最终会出现在这些名称和耻辱网站之一上,每个人都会投反对票并给它差评。

标签: java encryption passwords password-encryption


【解决方案1】:

当您使用CBC mode 时,您需要从加密密码中保存随机初始化向量 (IV) 并将其提供给解密密码。

您可以在初始化后从加密密码中获取它:

ciph.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] iv = ciph.getIV();

并将其提供给解密密码,例如:

ciph.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));

您需要想出一种保存 IV 的方法。一种常见的方法是在加密数据前加上 IV,以便在需要初始化解密密码时使用它。不需要保密。

【讨论】:

  • 非常感谢!这是我正在寻找的确切解决方案!我将根据您的建议修改我的其余代码,以使用加密密码存储 IV。
猜你喜欢
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
相关资源
最近更新 更多