【问题标题】:Decrypting returns, javax.crypto.BadPaddingException: Given final block not properly padded解密返回,javax.crypto.BadPaddingException:给定最终块未正确填充
【发布时间】:2018-08-17 13:56:57
【问题描述】:

我正在尝试解密加密的 xml 文件。我将它作为输入流获取如下。我有正确的加密密钥。但每次我的程序返回空字符串。每次我输入正确的密钥。但每次都返回 Badpadding Exception。

   try{
                InputStream is = new ByteArrayInputStream(decryption.getFileData().getBytes());
                String xmlEncryptedStr = getStringFromInputStream(is);
               String xmlStr = CipherUtils.decrypt(xmlEncryptedStr, new  Long(key));
               .......

这是我的 CipherUtils.java 类

.........

     public static String decrypt(String strToDecrypt,Long key)
        {
            String keyString=String.format("%016d", key);
            //System.out.println("decrypt keyString :"+keyString);
            return decrypt(strToDecrypt, keyString.getBytes());
        }


        public static String decrypt(String strToDecrypt,byte[] key)
        {
            if(strToDecrypt==null)
                return strToDecrypt;
            try
            {
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
                cipher.init(Cipher.DECRYPT_MODE, secretKey);

                final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
                System.out.println("CipherUtils.decryptedString :"+decryptedString);
                return decryptedString;
            }
            catch (Exception e)
            {
                log.error("Ops!", e);
            }
            return null;
        }

.......

更多信息,这里是我的加密代码

   public static String encrypt(String strToEncrypt,Long key)
        {
            String keyString=String.format("%016d", key);
            //System.out.println("encrypt keyString :"+keyString);
            return encrypt(strToEncrypt,keyString.getBytes());
        }



        public static String encrypt(String strToEncrypt,byte[] key)
        {
            if(strToEncrypt==null)
                return strToEncrypt;
            try
            {
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
                final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
              //  System.out.println("CipherUtils.encrypt :"+encryptedString);
                return encryptedString;
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;

        }

【问题讨论】:

  • 如果不显示我们只是猜测的加密代码。我不会这样做,但也许其他人会这样做。
  • 不要在新作品中使用 ECB 模式并尽快更新旧作品,它不安全,请参阅ECB mode,向下滚动到企鹅。而是使用带有随机IV的CBC模式,只需在加密数据前加上IV用于解密即可,它不需要保密。
  • 一般的填充错误,特别是考虑到加密和解密都明确指定了相同的填充,所以解密失败。为了测试没有填充的解密并检查解密的数据。确保密钥大小正确且编码匹配。没有嵌套函数调用更容易调试,使 Base64 编码/解码成为一个单独的步骤。
  • 这里是交易:如果解密失败,意味着它没有解密到正确的结果,填充也没有正确解密并且存在“填充错误”但它不是错误填充,这是一个整体解密错误。打印出密钥和数据并验证它们,这意味着将 Base64 编码/解码放在单独的语句中。添加到问题中。加密后的数据应该以十六进制显示,不是可显示的字符串。
  • 换一种说法可能更清楚:像 AES 这样的现代对称密码是双射的,所以如果你在使用时使用密文或密钥或 IV 解密(不适用于 ECB)甚至有一点错误,你不要从密码中得到错误只是垃圾数据,如果使用填充几乎总是会导致填充错误。因此,收到填充错误几乎总是意味着您使用错误的密文或密钥或 IV 解密。 @zaph:不要为 ECB 的语义不安全而烦恼,10^16 的密钥空间可以在几天内被商品硬件完全破坏。

标签: java encryption apache-commons-codec


【解决方案1】:

对不起,我无法发表评论,所以我在答案部分写。 当我使用不同的密钥时,我遇到了这个问题,虽然我传递了相同的密钥,但我使用了 CBC 方法。

请注意,您是否检查过加密也是由 AES/ECB/PKCS5Padding 完成的,而不是像 AES/CBC/PKCS5Padding 这样的其他格式

还要检查用于加密的密钥格式是否也与您的 keyValue 的 %016d 格式相同。密钥长度为 16 个字符。

我创建了一个简单的 AES 和 DESede 加密实用程序,它运行良好。

private static final byte[] keyValue = new String(
        "CjxI&S@V&#DSA_S0dA-SDSA$").getBytes();

public static void main(String[] args) throws Exception {
    Client cli = new Client();
    System.out.println(cli.encrypt("your password for encryption"));

    Client cli1 = new Client();
    System.out.println(cli1.decrypt("fTsgVQtXvv49GynHazT4OGZ4Va1H57d+6AM+44Ex040="));
}
public String encrypt(String Data) throws Exception {
    Key key = new SecretKeySpec(keyValue, "AES");
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, key);
    byte[] encVal = c.doFinal(Data.getBytes());
    String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
    // String encryptedValue = new BASE64Encoder().encode(encVal);
    return encryptedValue;
}

public String decrypt(String encryptedData) throws Exception {
    Key key = new SecretKeySpec(keyValue, "AES");
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
    c.init(Cipher.DECRYPT_MODE, key);
    byte[] decordedValue = DatatypeConverter
            .parseBase64Binary(encryptedData);
    byte[] decValue = c.doFinal(decordedValue);
    String decryptedValue = new String(decValue);
    return decryptedValue;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 2017-03-20
    相关资源
    最近更新 更多