从java中的.p7b文件中提取单个.cer证书

我是Cryptography的新手,所以如果您认为这是一个基本问题,请原谅

我有一个.p7b文件,我需要读取并提取单个公共证书,即.cer文件并将其存储在密钥库中。 我不必担心持久存在密钥存储区,因为已经有一个服务将.cer文件作为byte []接收并保存。

我想知道的是,我如何阅读.p7b并提取单个.cer文件? 我知道可以通过openSSL命令完成,但我需要在java中做同样的事情。 我还需要读取Issued By名称,因为它将用作持久保存证书的唯一键。

提前致谢

您可以使用BouncyCastle从PKCS#7对象获取证书。 这是一个快速代码示例:

public Collection getCertificates(String path) throws Exception { Security.addProvider(new BouncyCastleProvider()); CMSSignedData sd = new CMSSignedData(new FileInputStream(path)); X509Store store = sd.getCertificates("Collection", "BC"); Collection certificates = store.getMatches(X509CertStoreSelector.getInstance(new X509CertSelector())); return certificates; } 

请注意,PKCS#7可能包含多个证书。 大多数情况下,它包括在最终用户证书和根CA之间构建证书链所需的中间证书颁发机构证书。

我成功地从p7b文件中读取了各个.X509证书。 这是步骤

  • 第一步包括从java.io.File获取byte []。 步骤包括从文件中删除—– BEGIN PKCS7 —–和—– END PKCS7 —–,并解码剩余的base64编码的String。

     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]; } 
  • 上面的步骤工作正常,但我相信还有其他解决方案,用更少的代码行来实现这一目标。 我正在使用bcjdk16jar子。