好的,我通过执行以下操作导出了浏览器中的所有证书:工具、选项...、高级、加密、查看证书、您的证书、全部备份...(这是在 Firefox 中)。
证书列表中有 4 个证书,其中两个证书具有一个名称并具有不同的序列号,另外两个证书具有不同的名称并具有另外两个不同的序列号。所以,总的来说,有四个证书,其中两对具有相同的名称但不同的序列号。
如果我将此 p12 文件导入到另一台计算机上的另一个浏览器中,我将获得所有四个证书(如预期)。
--但是--
当我使用 java.security.* 包打开 p12 文件并查看 size() 时,它仅显示 p12 文件中的两个证书。当我循环浏览别名时,我只看到两个证书。 KeyStore 对象中是否有某些内容允许我访问所有四个证书?这很困难,因为两对的别名相同,只是序列号不同。预先感谢您提供的任何帮助。
最佳答案
好吧,回答我自己的古老问题...我了解到 Java 并不擅长读取 p12 文件。它使用每个证书的别名作为 key 创建一个 HashMap ,因此如果有两个具有相同别名的证书,Java 将用具有相同别名( key )的第二个证书破坏第一个证书,从而导致每个别名只有一个证书。
将证书导入浏览器时,浏览器会获取 p12 文件中的所有条目(不关心别名)。
我解决这个问题的方法是使用 Java 运行时执行功能来调用 openssl 并将每个证书的输出通过管道传输到字符串中,并使用该字符串创建 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;
}
希望对其他人有帮助。 :)
关于java.security.KeyStore 仅显示 p12 文件中两个证书之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5554085/