【问题标题】:BadPaddingException: Given final block not properly paddedBadPaddingException:给定最终块未正确填充
【发布时间】:2014-05-29 01:08:02
【问题描述】:

我有一个用 DES/ECB/PKCS5Padding 加密的私钥文件(由秘密短语生成的 56 位 DES 密钥),我想解密它。 我不知道为什么,但每次我尝试解密时,我的密码类的方法 doFinal 都会抛出这个错误:

javax.crypto.BadPaddingException:给定的最终块不正确 在 com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 处填充 com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 在 com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA13*..) 在 javax.crypto.Cipher.doFinal(DashoA13*..) at...

这是我的代码:

public static PrivateKey readPrivateKeyFromFile(File file, String chaveSecreta) {
    try {
        SecureRandom r = new SecureRandom(chaveSecreta.getBytes());
        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
        keyGen.init(56, r);
        Key key = keyGen.generateKey();

        byte[] privateKeyBytes = decryptPKFile(file, key);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = null;
        try {
            privateKey = keyFactory.generatePrivate(privateKeySpec);
        } catch (InvalidKeySpecException e) {
            JOptionPane.showMessageDialog(null, "Erro 01, tente mais tarde");
        }
        return privateKey;
    } catch (NoSuchAlgorithmException e) {
        JOptionPane.showMessageDialog(null, "Erro 02, tente mais tarde");
    }
    return null;
}

public static byte[] decryptPKFile(File file, Key key){
    try{
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        byte[] cipherText = readBytes(file);
        cipher.init(Cipher.DECRYPT_MODE, key);
        System.out.println(cipher);
        System.out.println(cipherText);
        byte[] text = cipher.doFinal(cipherText);
        return text;
    }catch(Exception e){
        e.printStackTrace();
        return null;
    }
}

public static byte[] readBytes(File file) {
    try {
        FileInputStream fs = new FileInputStream(file);
        byte content[] = new byte[(int) file.length()];
        fs.read(content);
        return content;
    } catch (FileNotFoundException e) {
        System.out.println("Arquivo não encontrado!");
        e.printStackTrace();
    } catch (IOException ioe) {
        System.out.println("Erro ao ler arquivo!");
        ioe.printStackTrace();
    }
    return null;
}

有什么建议吗?

【问题讨论】:

  • 我猜您从文件中读取的输入不是有效的加密文本。使用 DES 是块算法,你应该检查文件长度是否是 64 的乘积。如果不是,则意味着该文件已损坏。
  • 你的意思是8的倍数?是的,文件没有损坏,我已经检查过了。
  • @markubik 这是一个随机密钥:P

标签: java encryption


【解决方案1】:

您正在尝试使用使用特定种子创建的随机数生成器来解密密文。但是,您没有指定算法,并且算法也可能在内部发生变化。 Android 甚至会为某些版本生成完全随机的值。

您需要使用SecretKeyFactory 而不是KeyGenerator。您当然需要 8 字节的密钥数据。在您的情况下,唯一的检索方法是在之前找到 SecureRandom 算法/实现并重新计算密钥。

现在任何密文都可以用任何密钥解密。 DES ECB 仅提供(某种)机密性,而不是完整性。问题是它会解密成垃圾。现在,如果您尝试从垃圾中删除填充,您可能会收到填充错误。

如果你“幸运”——大约 256 次一次——你会得到一个结果。当解密块以010202 结尾时会发生这种情况,这是有效的填充。结果当然也会是垃圾,但它不会以BadPaddingException 结尾。在您的情况下,SecureRandom 实例可能会一遍又一遍地返回相同的错误值,因此这可能永远不会发生。

以后,请使用 PBKDF2 并输入编码密码。清楚地注意使用的字符编码,Java SE 使用 char 数组的最低 8 位。永远不要使用String.getBytes(),因为系统之间的默认编码可能不同。

【讨论】:

猜你喜欢
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
  • 1970-01-01
  • 2011-12-24
  • 2011-05-16
  • 1970-01-01
  • 2015-06-18
相关资源
最近更新 更多