首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BadPaddingException: pad块损坏

BadPaddingException: pad块损坏
EN

Stack Overflow用户
提问于 2009-05-15 13:48:05
回答 4查看 27K关注 0票数 7

我正在尝试用C#解密一个使用Rijndael/CBC/PKCS7 7加密的文件。我一直有以下例外情况:

javax.crypto.BadPaddingException: pad块损坏 在org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown源代码中) 在javax.crypto.Cipher.doFinal(DashoA13 13*.) 在AESFileDecrypter.decrypt(AESFileDecrypter.java:57)

当web服务器为第一个doFinal(inpbytes)调用byte[]方法时。我猜这是密钥或IV的问题。我在我的文件系统上有加密的文件进行测试。下面的代码有什么明显的错误吗?

*keyStr编码为base64

代码语言:javascript
复制
public AESFileDecrypter(String keyStr){
    try {
            Security.addProvider(new BouncyCastleProvider());   
            convertIvParameter();
            key = new sun.misc.BASE64Decoder().decodeBuffer(keyStr);

            //use the passed in Base64 decoded key to create a key object
            decryptKey = new SecretKeySpec(key, "AES");

            //specify the encryption algorithm
            decryptCipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");

            //make a parameter object for the initialization vector(IV)             
            IvParameterSpec ivs = new IvParameterSpec(_defaultIv);

            //initialize the decrypter to the correct mode, key used and IV
            decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey, ivs);    
        } 
     catch (Exception e) {
             e.printStackTrace();
     } 
}

public void convertIvParameter() {

   int[] iv = new int[] {11, 190, 165, 33, 68, 88, 11, 200, 245, 35, 68, 23, 60, 24, 223, 67};

   _defaultIv = new byte[16];

   for(int x = 0; x < _defaultIv.length; x++) {
      _defaultIv[x] = (byte)iv[x];
   }
}

public void decryptUpdate(byte[] inpBytes) throws Exception {
   //decrypt the byte passed in from the web server
   decryptCipher.update(inpBytes);  
}

public byte[] decryptFinal() throws Exception {
   //decrypt the byte passed in from the web server
   return decryptCipher.doFinal();
}

//sends bytes to the client for diaply
private void sendBytes(FileInputStream fis, OutputStream os)throws Exception {
    //set the buffer size to send 4k segments of data
aesFileDecrypter = new AESFileDecrypter(<Insert Key string here>);

    byte[] buffer = new byte[4096];
    int bytes = 0, totalBytes = fis.available();

    //while there is still data to be sent keep looping and write the data
    //to the output stream as the buffer is filled
    try {
       while ((bytes = fis.read(buffer)) != -1) {   
          aesFileDecrypter.decryptUpdate(buffer);
          //os.write(buffer, 0, bytes);
       }

       os.write(aesFileDecrypter.decryptFinal(), 0, totalBytes);
   }
   catch(Exception e) {
      e.printStackTrace();
   }
}
EN

回答 4

Stack Overflow用户

发布于 2009-05-15 15:33:44

首先,为了明确起见,从下面的注释中可以看出,您不应该在每个块上调用doFinal(),因为doFinal()期望在末尾有任何填充,这显然不会出现在中间块中。要么(a)对中间数据调用update(),然后在末尾调用doFinal(),要么(b)安排将所有数据放在一个缓冲区或字节数组中,然后在整个作业批次上调用doFinal()一次。

从您发布的代码中还不清楚,这实际上就是您正在做的事情,但是应该提到它,以防万一。

如果失败,那么作为调试的第一步,我建议这两种方法中哪一种对您来说更容易:

  • 在没有填充的情况下,在欧洲央行模式下解密,看看你得到了什么。看看它带来的第一个数据块。如果您可以使用IV字节对此进行异或,并获得预期的解密数据,则您知道您的密钥是可以的。
  • 在基64编码之前从C#中转储出实际的键字节,在解码和检查后从Java中排除它们是相同的。

我记得,C#有无符号字节(而Java ),所以有几个地方有空间让字节签名出现微妙的错误。

票数 6
EN

Stack Overflow用户

发布于 2011-07-26 02:07:00

我以前也遇到过这个问题。

当我编写一些代码来进行加密和解密时,如下所示:

代码语言:javascript
复制
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sec, "AES"),new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] encode = cipher.doFinal(data);

    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sec, "AES"), new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] decode = cipher.doFinal(encode);

我在加密数据时忘记了第一个IvParameterSpec(new byte[cipher.getBlockSize()]),然后我得到了一个异常"pad块损坏“,所以也许您应该检查一下加密代码。

票数 3
EN

Stack Overflow用户

发布于 2009-05-15 14:53:38

据我所知,AES是基于Rijndael的,但规范并不完全相同。我建议检查在C#中用于加密的密钥和块大小,以及在Java中使用的大小。(Rijndael和AES的.Net差异)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/868776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档