【问题标题】:Exception unwrapping key: bad padding: Decryption error异常解包密钥:错误填充:解密错误
【发布时间】:2021-09-20 01:59:22
【问题描述】:

我正在尝试解密文件“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));

【问题讨论】:

    标签: java encryption jks


    【解决方案1】:

    从这里我看不到出了什么问题,但错误发生在 RSA 私钥解密对称密钥期间。

    CMS 是一种容器格式。它包含处理或封装数据的方法。如果您有一个封装容器,则其中的数据不会直接使用 RSA 公钥加密。相反,它使用随机对称密钥(通常称为数据密钥甚至会话密钥)进行加密。然后使用公钥加密此对称密钥。

    RSA 加密首先填充数据,然后使用公共指数执行模幂运算。解密由具有私有指数和未填充的模幂运算组成。现在,无论数据或指数的值如何,模幂运算都将始终成功。因此,如果数据或密钥无效,则填充异常是唯一的指示。

    由于容器中的数据可能是有效的 - 如果不是,您会期望解码错误 - 私钥与公钥不匹配的可能性更大。不排除 CMS 库的实现错误,但如果 CMS 库经过良好测试,我认为相对不太可能。

    所以我会怀疑您的键值而不是您的代码 - 当然,读取或写入您的键的代码也可能有错误。

    总而言之,我肯定会首先在您的代码中修复流处理。仅仅创建一个encryptedAndSignedByte 缓冲区并调用一次read 是非常幼稚的,它可能不会返回所有数据。

    【讨论】:

      【解决方案2】:

      我已经修改了代码,但出现了同样的问题。我相信加密部分应该没有问题。

      解密代码:

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

      在主类中

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

      【讨论】:

      • 你知道,我完全错过了这个,因为它是作为答案发布的。不要创建答案作为对问题的跟进。要么创建一个新答案,要么修改你当前的答案。
      • 未来的读者要小心!:我认为这甚至不是一个答案。 CSSC 在上午 7 点 28 分发布了这个答案,但后来在上午 8 点 18 分对@MaartenBodewes 的回答发表了评论,说:“我现在可以解密文件了。:) 是关键问题。”他的根本原因(也是我的?)是他使用了错误的解密密钥。即使使用此代码,我仍然看到exception unwrapping key: bad padding: Decryption error。因此,即使此答案的存在表明 OP 已使用此代码解决了问题,但我认为情况并非如此。
      猜你喜欢
      • 2017-12-10
      • 2012-09-14
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 1970-01-01
      • 2021-01-22
      • 1970-01-01
      • 2017-10-11
      相关资源
      最近更新 更多