BadPaddingException:pad块已损坏 [英] BadPaddingException: pad block corrupted

查看:545
本文介绍了BadPaddingException:pad块已损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解密一个使用Rijndael / CBC / PKCS7在C#中加密的Java文件。我继续收到以下异常:


javax.crypto.BadPaddingException:pad块已损坏

在org.bouncycastle。 jce.provider.JCEBlockCipher.engineDoFinal(未知来源)

在javax.crypto.Cipher.doFinal(DashoA13 * ..)

在AESFileDecrypter.decrypt(AESFileDecrypter.java:57)


doFinal(inpbytes)方法被Web服务器调用第一个字节[]。我猜这是钥匙或IV的问题。我的文件系统上加密文件进行测试。有没有什么可以看到我的代码下面的明显错误?



*** keyStr是base64编码

  public AESFileDecrypter(String keyStr){
try {
Security.addProvider(new BouncyCastleProvider());
convertIvParameter();
key = new sun.misc.BASE64Decoder()。decodeBuffer(keyStr);

//使用传递的Base64解码密钥创建一个关键对象
decryptKey = new SecretKeySpec(key,AES);

//指定加密算法
decryptCipher = Cipher.getInstance(AES / CBC / PKCS7Padding,BC);

//为初始化向量(IV)创建参数对象
IvParameterSpec ivs = new IvParameterSpec(_defaultIv);

//将解密器初始化为正确的模式,使用密钥和IV
decryptCipher.init(Cipher.DECRYPT_MODE,decryptKey,ivs);
}
catch(异常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]; (int x = 0; x< _defaultIv.length; x ++)

{
_defaultIv [x] =(byte)iv [x]
}
}

public void decryptUpdate(byte [] inpBytes)throws异常{
//解密从Web服务器传入的字节
decryptCipher .update(inpBytes);
}

public byte [] decryptFinal()throws异常{
//解密从Web服务器传入的字节
return decryptCipher.doFinal();
}

//向客户端发送字节为
private void sendBytes(FileInputStream fis,OutputStream os)throws异常{
//将缓冲区大小设置为发送4k数据段
aesFileDecrypter = new AESFileDecrypter(< Insert Key string here>);

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

//尽管仍然有数据被发送保持循环并将数据
//写入缓冲区中的输出流
try {
while ((bytes = fis.read(buffer))!= -1){
aesFileDecrypter.decryptUpdate(buffer);
//os.write(buffer,0,bytes);
}

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


解决方案

,只要清楚,从下面的评论中,你不应该在每个块上调用doFinal(),因为doFinal()期望在末尾有任何填充,这显然不会在中间块中。 (a)对中间数据调用update(),然后在末尾调用doFinal(),或者(b)只是将所有数据放在一个缓冲区或字节数组中,并在整个作业批次中调用doFinal()一次。



您发布的代码不清楚,这实际上是您正在做的,但应该提及,以防万一。



没有这个,那么作为调试的第一步,我建议你们中的哪一个更容易:




  • 在ECB模式下解密,没有填充,看到你得到什么。看看这带来的第一个数据块。如果你可以用你的IV字节异或得到预期的解密数据,你知道你的密钥是可以的。

  • 解码之前的基本64编码和Java之前的C#中的实际的关键字节并且检查它们是一样的。



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


I am trying to decrypt a file in Java which was encrypted in C# using Rijndael/CBC/PKCS7. I keep getting the following exception:

javax.crypto.BadPaddingException: pad block corrupted
at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at AESFileDecrypter.decrypt(AESFileDecrypter.java:57)

when the doFinal(inpbytes) method is called by the web server for the first byte[]. I am guessing this is a problem with the key or IV. I have the encrypted files on my file system for testing. Is there anything that anyone can see glaringly wrong with my code below?

***keyStr is base64 encoded

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();
   }
}

解决方案

Firstly, just to be clear, from comments below, you shouldn't call doFinal() on every block, because doFinal() expects any padding at the end, which obviouslly won't be there in intermediate blocks. Either (a) call update() on intermediate data, then doFinal() at the end, or (b) just arrange to have all your data in one buffer or byte array, and call doFinal() once on the whole job lot.

It's not clear from the code you posted that that's actually what you're doing, but it should be mentioned just in case.

Failing that, then as a first step to debugging, I'd suggest whichever of these two is easier for you:

  • Decrypting in ECB mode with no padding and seeing what you get. Look at the first block of data this brings back. If you can XOR this with your IV bytes and get the expected decrypted data, you know your key is OK.
  • Dumping out the actual key bytes from C# before base 64 encoding and Java after decoding and checking they are the same.

As I recall, C# has unsigned bytes (whereas Java signed) so there are a few places where there's room for things subtly going wrong with byte signedness.

这篇关于BadPaddingException:pad块已损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆