简体   繁体   English

使用 Java 中的 BouncyCastle 从 PKCS7 PEM 格式的证书创建 X509Certificate

[英]Create X509Certificate from PKCS7 PEM formatted certificate using BouncyCastle in Java

I have a PKCS7 certificate chain in PEM format.我有一个 PEM 格式的 PKCS7 证书链。 Basically I'd like to perform following openssl command in Java using BouncyCastle library.基本上我想使用 BouncyCastle 库在 Java 中执行 openssl 命令。

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

I was following this pdf provided from BouncyCastle ( https://www.bouncycastle.org/fips-java/BCFipsIn100.pdf ), but couldn't really find anything that works on my need.我正在关注 BouncyCastle 提供的 pdf( https://www.bouncycastle.org/fips-java/BCFipsIn100.Z437175BA4191210EE004E1D9374 ,但我确实需要)

I've found that CMSSignedData is used for pkcs7 related operations in BouncyCastle so I tried using it, but I was getting an error and I assume it's because I was using a raw String.我发现 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));
    }
}

This is the error I got on new CMSSignedData(pkcs7Pem.getBytes());这是我在new CMSSignedData(pkcs7Pem.getBytes());上遇到的错误。

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

I also have tried using PEMParser , but parser.readObject() below returns null.我也尝试过使用PEMParser ,但下面的parser.readObject()返回 null。

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

Any help would be appreciated!任何帮助,将不胜感激!

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

That command only copies its input (if it is PKCS7 PEM) to its output without any change.该命令仅将其输入(如果是 PKCS7 PEM)复制到其 output 而不进行任何更改。 That's not useful, nor do you need BouncyCastle to do the same in Java.这没有用,您也不需要 BouncyCastle 在 Java 中做同样的事情。 I suspect you actually meant我怀疑你的意思是

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

which extracts the individual certificate(s), as a sequence of separate (PEM) objects.它将单个证书提取为一系列单独的 (PEM) 对象。

I've found that CMSSignedData is used for pkcs7 related operations in BouncyCastle我发现 CMSSignedData 用于 BouncyCastle 中的 pkcs7 相关操作

Only some -- there are lots of PKCS7/CMS formats and operations that can be done, and lots of different BC classes to do them.只有一些——有很多PKCS7/CMS 格式和操作可以完成,还有很多不同的 BC 类可以完成它们。 But the PKCS7/CMS format used to carry a certificate chain, often labelled p7b or p7c, is the SignedData type and is implemented by the BouncyCastle CMSSignedData class.但是用于承载证书链的 PKCS7/CMS 格式(通常标记为 p7b 或 p7c)是 SignedData 类型,由 BouncyCastle CMSSignedData class 实现。

I also have tried using PEMParser, but parser.readObject() below returns null.我也尝试过使用 PEMParser,但下面的 parser.readObject() 返回 null。

It shouldn't, if you give it valid PEM input not the mangled version you posted.它不应该,如果你给它有效的 PEM 输入而不是你发布的损坏版本。 For me if I give it a valid PEM PKCS7 containing a p7b/c cert chain I get a ContentInfo which can then be decoded as follows (I use file I/O for convenience, but any Java Reader and Writer will work the same):对我来说,如果我给它一个包含 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();
}

Note a p7b/c by convention does not contain any signature(s) (in PKCS7/CMS terms, SignerInfo(s)) so the code you posted -- which is designed to find the certificate(s) associated with the signature(s) -- is inappropriate and does not work.请注意,按照惯例,p7b/c 不包含任何签名(在 PKCS7/CMS 术语中,SignerInfo(s)),因此您发布的代码 - 旨在查找与签名关联的证书) -- 不合适且不起作用。 You need to simply use the certificate(s) and not expect any SignerInfo(s).您需要简单地使用证书而不期望任何 SignerInfo(s)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM