我是密码学新手,如果您认为这是一个基本问题,请原谅
我有一个 .p7b 文件,我需要读取并提取各个公共证书,即 .cer 文件并将其存储在密钥库中。我不必担心保留在密钥库中,因为已经有一项服务将 .cer 文件作为byte[]接收并保存。
我想知道的是,我如何读取 .p7b 并提取单个 .cer 文件?我知道这可以通过 openSSL 命令来完成,但我需要在 java 中做同样的事情。我还需要阅读Issued By名称,因为它将用作保存证书的唯一密钥。
提前致谢
我是密码学新手,如果您认为这是一个基本问题,请原谅
我有一个 .p7b 文件,我需要读取并提取各个公共证书,即 .cer 文件并将其存储在密钥库中。我不必担心保留在密钥库中,因为已经有一项服务将 .cer 文件作为byte[]接收并保存。
我想知道的是,我如何读取 .p7b 并提取单个 .cer 文件?我知道这可以通过 openSSL 命令来完成,但我需要在 java 中做同样的事情。我还需要阅读Issued By名称,因为它将用作保存证书的唯一密钥。
提前致谢
您可以使用 BouncyCastle 从 PKCS#7 对象获取证书。这是一个快速的代码示例:
public Collection<X59Certificate> getCertificates(String path) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
CMSSignedData sd = new CMSSignedData(new FileInputStream(path));
X509Store store = sd.getCertificates("Collection", "BC");
Collection<X509Certificate> certificates = store.getMatches(X509CertStoreSelector.getInstance(new X509CertSelector()));
return certificates;
}
请注意,PKCS#7 可能包含多个证书。大多数情况下,它包括在最终用户证书和根 CA 之间构建证书链所需的中间证书颁发机构证书。
我成功地从 p7b 文件中读取了单个 .X509 证书。以下是步骤
第一步包括从 java.io.File 中获取一个 byte[]。这些步骤包括从文件中删除 -----BEGIN PKCS7----- 和 -----END PKCS7-----,并解码剩余的 base64 编码字符串。
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder cerfile = new StringBuilder();
String line = null;
while(( line = reader.readLine())!=null){
if(!line.contains("PKCS7")){
cerfile.append(line);
}
}
byte[] fileBytes = Base64.decode(cerfile.toString().getBytes());
下一步是使用 BouncyCastle api 来解析文件
CMSSignedData dataParser = new CMSSignedData(trustBundleByte);
ContentInfo contentInfo = dataParser.getContentInfo();
SignedData signedData = SignedData.getInstance(contentInfo.getContent());
CMSSignedData encapInfoBundle = new CMSSignedData(new CMSProcessableByteArray(signedData.getEncapContentInfo().getContent().getDERObject().getEncoded()),contentInfo);
SignedData encapMetaData = SignedData.getInstance(encapInfoBundle.getContentInfo().getContent());
CMSProcessableByteArray cin = new CMSProcessableByteArray(((ASN1OctetString)encapMetaData.getEncapContentInfo().getContent()).getOctets());
CertificateFactory ucf = CertificateFactory.getInstance("X.509");
CMSSignedData unsignedParser = new CMSSignedData(cin.getInputStream());
ContentInfo unsginedEncapInfo = unsignedParser.getContentInfo();
SignedData metaData = SignedData.getInstance(unsginedEncapInfo.getContent());
Enumeration certificates = metaData.getCertificates().getObjects();
// Build certificate path
while (certificates.hasMoreElements()) {
DERObject certObj = (DERObject) certificates.nextElement();
InputStream bin = new ByteArrayInputStream(certObj.getDEREncoded());
X509Certificate cert = (X509Certificate) ucf.generateCertificate(bin);
X500Name x500name = new JcaX509CertificateHolder(cert).getSubject();
RDN cn = x500name.getRDNs(BCStyle.CN)[0];
}
上述步骤工作正常,但我相信还有其他解决方案可以用更少的代码行来实现这一点。我正在使用 bcjdk16 罐子。