好的,我通过以下方式导出浏览器中的所有证书:工具,选项...,高级,加密,查看证书,证书,全部备份......(这是在Firefox中)。
证书列表中有4个证书,其中两个在一个名称下有不同的序列号,另外两个在不同的名称下有两个不同的序列号。因此,总而言之,有四个证书,两个具有相同的名称但不同的序列号。
如果我要将这个p12文件导入另一台机器上的另一个浏览器,我会获得所有四个证书(如预期的那样)。
- 但是 -
当我使用java.security。*包打开p12文件并查看size()时,它只显示p12文件中的两个证书。当我遍历别名时,我只看到两个证书。 KeyStore对象中是否有允许我访问所有四个证书的东西?这很难,因为两对的别名是相同的,只有序列号不同。提前感谢您提供的任何帮助。
答案 0 :(得分:4)
好的,回答我自己的古老问题......我了解到Java在阅读p12文件方面并不擅长。它使用每个证书的别名作为密钥创建一个hashmap,因此如果有两个具有相同别名的证书,Java将使用相同的别名(密钥)破坏第一个证书和第二个证书,每个别名只有一个证书。
将证书导入浏览器时,浏览器会获取p12文件中的所有条目(不关心别名)。
我解决这个问题的方法是使用Java运行时exec功能调用openssl并将每个证书的输出通过管道传输到String中,并使用该字符串创建X509Certificate。这里有一些示例代码(我无法复制和粘贴,因为我的开发框没有连接互联网):
private ArrayList<X509Certificate> parseCerts( String fileName, String pwd ) {
ArrayList certsFromP12File = new ArrayList();
String cmdLine = "/usr/bin/openssl pkcs12 -info -in " + fileName + " -clcerts -nokeys -passin pass:" + pwd;
String line;
Process p = Runtime.getRuntime().exec( cmdLine );
BufferedReader input = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
boolean readingCert = false;
boolean gotCertToProcess = false;
String certString;
while ((line=input.readLine()) != null ) {
if ( line.contains("-----BEGIN CERTIFICATE-----") ) {
readingCert = true;
}
if ( readingCert ) {
certString += line + System.getProperty("line.separator");
}
if ( line.contains("-----END CERTIFICATE-----") ) {
readingCert = false;
getCertToProcess = true;
}
if ( gotCertToProcess ) {
X509Certificate cert = null;
byte[] cert_bytes = certString.getBytes();
ByteArrayInputStream certInputStream = new ByteArrayInputStream(cert_bytes);
cert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate( certInputStream );
certsFromP12File.add( cert );
gotCertToProcess = false;
certString = "";
}
}
input.close();
return certsfromP12File;
}
希望能帮助他人。 :)