cipher.doFinal(...) 失败,而 cipher.update(...) 成功

cipher.doFinal(...) fails while cipher.update(...) succeeds

我正在尝试使用以下代码解密字节数组。为了简洁起见,我省略了异常处理和其他实践:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] key = getKey(); \Assume it is implemented.
byte[] iv = getIv(); \Assume it is implemented;
SecretKeySpec sc = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, sc, new IvParameterSpec(iv));
byte[] encrypted = getBytesFromFile(); \*Assume it is implemented. Simply reads bytes from a binary file into a byte array and returns them as are.*\
byte[] clear = new byte[cipher.getOutputSize(encrypted.length)];
int processed = cipher.doFinal(encrypted, 0, encrypted.length, clear, 0);

注意:Java 本身不支持 PKCS7Padding,但我确实通过添加安全的 BouncyCastleProvider 让它工作。为了争论,PKCS5Padding 也有同样的问题。

import org.bouncycastle.jce.provider.BouncyCastleProvider;

问题:

doFinal throws 抛出一个 BadPaddingException: pad block corrupt。但是,如果我将 doFinal 替换为 update,即:

int processed = cipher.update(encrypted, 0, encrypted.length, clear, 0); 

效果很好。结果如预期。

能否请一些人帮助我理解有什么区别以及如何使 doFinal 工作?如果需要更多信息,请告诉我。

您没有显示加密,最好的办法是填充确实不正确。要在没有 PKCS7Padding 的情况下检查此解密,您将能够看到填充并确定它是否正确。

错误出现在 doFinal 中,因为这是检查填充的地方,如果正确则将其删除。

这样做并转储解密数据(十六进制,因为填充将是 0x01 - 0x10 范围内的字节。