异常解包密钥:填充错误:解密错误
Exception unwrapping key: bad padding: Decryption error
我正在尝试解密文件 "test.txt.p7b",该文件使用 JKS 中的证书加密。
我在调试代码时收到此错误。感谢有人可以解释为什么会出现此错误。是我的钥匙有问题还是我的代码有问题(大多数情况下,我相信是这样)。非常感谢
错误信息如下,
Exception in thread "main" org.bouncycastle.cms.CMSException: exception unwrapping key: bad padding: Decryption error
at org.bouncycastle.cms.jcajce.JceKeyTransRecipient.extractSecretKey(Unknown Source)
at org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.KeyTransRecipientInformation.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContentStream(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContent(Unknown Source)
at TestingB.decryptData(TestingB.java:299)
at TestingB.main(TestingB.java:161)
Caused by: org.bouncycastle.operator.OperatorException: bad padding: Decryption error
at org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper.generateUnwrappedKey(Unknown Source)
... 7 more
Caused by: javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
... 8 more
这是我的解密代码。
FileInputStream fIn = new FileInputStream(_keyStorePath);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, _password);
PrivateKey key = (PrivateKey) keystore.getKey("def","123456".toCharArray());
fIn.close();
File file = new File("C:\1_Eclipse\1_CS\Encrypted\test.txt.p7b");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] encryptedAndSignedByte = new byte[(int)file.length()];
fileInputStream.read(encryptedAndSignedByte);
fileInputStream.close();
X509Certificate cert9 = (X509Certificate) keystore.getCertificate("abc");
KeyTransRecipientId recId = new JceKeyTransRecipientId(cert9.getIssuerX500Principal(), cert9.getSerialNumber());
CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedAndSignedByte);
RecipientInformationStore recipients = enveloped.getRecipientInfos();
RecipientInformation recipient = recipients.get(recId);
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient(key);
ter.setContentProvider(BouncyCastleProvider.PROVIDER_NAME);
System.out.println("content : " + recipient.getContent(ter));
从这里我看不出哪里出了问题,但是错误发生在用RSA私钥解密对称密钥的过程中。
CMS 是一种容器格式。它包含处理或封装数据的方法。如果您有一个封装容器,则其中的数据不会直接使用 RSA public 密钥加密。相反,它是用随机对称密钥(通常称为数据密钥甚至会话密钥)加密的。然后使用 public 密钥加密此对称密钥。
RSA加密首先填充数据,然后用public指数进行模幂运算。解密包括使用私有指数和去填充的模幂运算。现在,无论数据或指数的值如何,模幂总是会成功。因此,如果数据或密钥无效,则填充异常是唯一的指示。
由于容器中的数据可能是有效的 - 如果不是,您会期望出现解码错误 - 私钥很可能与 public 密钥不匹配。它不排除 CMS 库的实现错误,但如果 CMS 库经过良好测试,我认为这种可能性相对较小。
所以我会怀疑你的密钥值而不是你的代码 - 当然也可能在读取或写入你的密钥的代码中有错误。
总而言之,我肯定会首先修复您代码中的流处理。仅仅创建一个 encryptedAndSignedByte
缓冲区并调用 read
一次是非常幼稚的,它可能不会 return 所有数据。
我修改了代码,还是出现同样的问题。我相信加密部分应该没有问题。
解密代码:
public static void decrypt(final InputStream is, OutputStream os, Key key, String providerName) throws Exception {
final InputStream bis = new BufferedInputStream(is, bufferSize);
final OutputStream bos = new BufferedOutputStream(os, bufferSize);
final Iterator it = new CMSEnvelopedDataParser(bis).getRecipientInfos().getRecipients().iterator();
if (it.hasNext()) {
final RecipientInformation recipient = (RecipientInformation)it.next();
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient((PrivateKey) key);
final CMSTypedStream recData = recipient.getContentStream(ter);
final InputStream ris = recData.getContentStream();
fromInToOut(ris, bos);
}
os.close();
}
主要class
new File("C:\1_Eclipse\1_CS\Encrypted\test_result.txt");
FileOutputStream E_fileOuputStream = new FileOutputStream("C:\1_Eclipse\1_CS\Encrypted\test_result.txt");
FileInputStream E_fileInputStream = new FileInputStream("C:\1_Eclipse\1_CS\Encrypted\test.txt.p7b");
decrypt(E_fileInputStream,E_fileOuputStream,key,"BC");
我认为错误是由我的这部分解密引起的。
final RecipientInformation recipient = (RecipientInformation)it.next();
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient((PrivateKey) key);
final CMSTypedStream recData = recipient.getContentStream(ter);
我正在尝试解密文件 "test.txt.p7b",该文件使用 JKS 中的证书加密。
我在调试代码时收到此错误。感谢有人可以解释为什么会出现此错误。是我的钥匙有问题还是我的代码有问题(大多数情况下,我相信是这样)。非常感谢
错误信息如下,
Exception in thread "main" org.bouncycastle.cms.CMSException: exception unwrapping key: bad padding: Decryption error
at org.bouncycastle.cms.jcajce.JceKeyTransRecipient.extractSecretKey(Unknown Source)
at org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.KeyTransRecipientInformation.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContentStream(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContent(Unknown Source)
at TestingB.decryptData(TestingB.java:299)
at TestingB.main(TestingB.java:161)
Caused by: org.bouncycastle.operator.OperatorException: bad padding: Decryption error
at org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper.generateUnwrappedKey(Unknown Source)
... 7 more
Caused by: javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
... 8 more
这是我的解密代码。
FileInputStream fIn = new FileInputStream(_keyStorePath);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, _password);
PrivateKey key = (PrivateKey) keystore.getKey("def","123456".toCharArray());
fIn.close();
File file = new File("C:\1_Eclipse\1_CS\Encrypted\test.txt.p7b");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] encryptedAndSignedByte = new byte[(int)file.length()];
fileInputStream.read(encryptedAndSignedByte);
fileInputStream.close();
X509Certificate cert9 = (X509Certificate) keystore.getCertificate("abc");
KeyTransRecipientId recId = new JceKeyTransRecipientId(cert9.getIssuerX500Principal(), cert9.getSerialNumber());
CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedAndSignedByte);
RecipientInformationStore recipients = enveloped.getRecipientInfos();
RecipientInformation recipient = recipients.get(recId);
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient(key);
ter.setContentProvider(BouncyCastleProvider.PROVIDER_NAME);
System.out.println("content : " + recipient.getContent(ter));
从这里我看不出哪里出了问题,但是错误发生在用RSA私钥解密对称密钥的过程中。
CMS 是一种容器格式。它包含处理或封装数据的方法。如果您有一个封装容器,则其中的数据不会直接使用 RSA public 密钥加密。相反,它是用随机对称密钥(通常称为数据密钥甚至会话密钥)加密的。然后使用 public 密钥加密此对称密钥。
RSA加密首先填充数据,然后用public指数进行模幂运算。解密包括使用私有指数和去填充的模幂运算。现在,无论数据或指数的值如何,模幂总是会成功。因此,如果数据或密钥无效,则填充异常是唯一的指示。
由于容器中的数据可能是有效的 - 如果不是,您会期望出现解码错误 - 私钥很可能与 public 密钥不匹配。它不排除 CMS 库的实现错误,但如果 CMS 库经过良好测试,我认为这种可能性相对较小。
所以我会怀疑你的密钥值而不是你的代码 - 当然也可能在读取或写入你的密钥的代码中有错误。
总而言之,我肯定会首先修复您代码中的流处理。仅仅创建一个 encryptedAndSignedByte
缓冲区并调用 read
一次是非常幼稚的,它可能不会 return 所有数据。
我修改了代码,还是出现同样的问题。我相信加密部分应该没有问题。
解密代码:
public static void decrypt(final InputStream is, OutputStream os, Key key, String providerName) throws Exception {
final InputStream bis = new BufferedInputStream(is, bufferSize);
final OutputStream bos = new BufferedOutputStream(os, bufferSize);
final Iterator it = new CMSEnvelopedDataParser(bis).getRecipientInfos().getRecipients().iterator();
if (it.hasNext()) {
final RecipientInformation recipient = (RecipientInformation)it.next();
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient((PrivateKey) key);
final CMSTypedStream recData = recipient.getContentStream(ter);
final InputStream ris = recData.getContentStream();
fromInToOut(ris, bos);
}
os.close();
}
主要class
new File("C:\1_Eclipse\1_CS\Encrypted\test_result.txt");
FileOutputStream E_fileOuputStream = new FileOutputStream("C:\1_Eclipse\1_CS\Encrypted\test_result.txt");
FileInputStream E_fileInputStream = new FileInputStream("C:\1_Eclipse\1_CS\Encrypted\test.txt.p7b");
decrypt(E_fileInputStream,E_fileOuputStream,key,"BC");
我认为错误是由我的这部分解密引起的。
final RecipientInformation recipient = (RecipientInformation)it.next();
JceKeyTransEnvelopedRecipient ter = new JceKeyTransEnvelopedRecipient((PrivateKey) key);
final CMSTypedStream recData = recipient.getContentStream(ter);