【问题标题】:Create X509Certificate from PKCS7 PEM formatted certificate using BouncyCastle in Java在 Java 中使用 BouncyCastle 从 PKCS7 PEM 格式的证书创建 X509Certificate
【发布时间】:2021-11-20 17:07:34
【问题描述】:

我有一个 PEM 格式的 PKCS7 证书链。基本上我想使用 BouncyCastle 库在 Java 中执行以下 openssl 命令。

openssl pkcs7 -in client-certificate_pkcs7.pem -out client-certificate_chain.pem

我一直在关注 BouncyCastle (https://www.bouncycastle.org/fips-java/BCFipsIn100.pdf) 提供的这个 pdf,但找不到任何符合我需要的东西。

我发现 CMSSignedData 用于 BouncyCastle 中的 pkcs7 相关操作,所以我尝试使用它,但我收到错误,我认为这是因为我使用的是原始字符串。

String pkcs7Pem = "-----BEGIN PKCS7-----\nMIIR...WTEA\n-----END PKCS7-----\n";
CMSSignedData data = new CMSSignedData(pkcs7Pem.getBytes());
Store certStore = data.getCertificates();
SignerInformationStore signerInfos = data.getSignerInfos();
Collection<SignerInformation> signers = signerInfos.getSigners();
List<X509Certificate> x509Certificates = new ArrayList<>();
for (SignerInformation signer : signers) {
    Collection<X509CertificateHolder> matches = certStore.getMatches(signer.getSID());
    for (X509CertificateHolder holder : matches) {
        x509Certificates.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder));
    }
}

这是我在new CMSSignedData(pkcs7Pem.getBytes());上遇到的错误

org.bouncycastle.cms.CMSException: IOException reading content.

我也尝试过使用PEMParser,但下面的parser.readObject() 返回null。

String pkcs7Pem = "-----BEGIN PKCS7-----\nMIIR...WTEA\n-----END PKCS7-----\n";
PEMParser parser = new PEMParser(new StringReader(pkcs7Pem));
parser.readObject();

任何帮助将不胜感激!

【问题讨论】:

    标签: java bouncycastle client-certificates pem pkcs#7


    【解决方案1】:

    openssl pkcs7 -in client-certificate_pkcs7.pem -out client-certificate_chain.pem

    该命令仅将其输入(如果它是 PKCS7 PEM)复制到其输出,而没有任何更改。这没有用,您也不需要 BouncyCastle 在 Java 中做同样的事情。我怀疑你的意思是

    openssl pkcs7 -print_certs -in (pkcs7) -out (chain)

    将单个证书提取为一系列单独的 (PEM) 对象。

    我发现 CMSSignedData 用于 BouncyCastle 中的 pkcs7 相关操作

    只有一些 -- 有 很多 PKCS7/CMS 格式和操作可以完成,还有很多不同的 BC 类可以完成它们。但用于承载证书链的 PKCS7/CMS 格式(通常标记为 p7b 或 p7c)是 SignedData 类型,由 BouncyCastle CMSSignedData 类实现。

    我也尝试过使用 PEMParser,但是下面的 parser.readObject() 返回 null。

    它不应该,如果你给它有效 PEM 输入而不是你发布的损坏版本。对我来说,如果我给它一个包含 p7b/c 证书链的有效 PEM PKCS7,我会得到一个 ContentInfo,然后可以按如下方式解码(为方便起见,我使用文件 I/O,但任何 Java ReaderWriter将工作相同):

    static void SO70048115PKCS7Certs (String[] args) throws Exception {
        PEMParser p = new PEMParser(new FileReader(args[0])); 
        CMSSignedData sd = new CMSSignedData( (ContentInfo)p.readObject() );
        p.close();
        JcaPEMWriter w = new JcaPEMWriter(new FileWriter(args[1])); 
        for( X509CertificateHolder ch : sd.getCertificates().getMatches(null) ){
            // optionally put subject,issuer as 'comments' like OpenSSL does
            w.writeObject( new PemObject("CERTIFICATE",ch.getEncoded()) );
        }
        w.close();
    }
    

    注意 p7b/c 按照惯例不包含任何签名(在 PKCS7/CMS 术语中,SignerInfo(s)),因此您发布的代码 - 旨在查找证书 与签名相关联 -- 不合适且不起作用。您需要简单地使用证书,而不需要任何 SignerInfo(s)。

    【讨论】:

    • 感谢您的评论,您是对的,我的意思是 openssl pkcs7 -print_certs -in (pkcs7) -out (chain) 正如您所指出的。可能是我抄错了。你也对parser.readObject() 不返回null 是正确的。我刚刚发现我使用了Evaluate Expression 选项卡,我可以在调试模式下调用方法,并发现一旦我调用pemParser.readObject(),它下次返回null。就像您提到的那样,它正确地返回ContentInfo。非常感谢您的帮助和澄清。
    猜你喜欢
    • 2018-12-28
    • 2022-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多