【问题标题】:java.security.KeyStore shows only one of two certs in a p12 filejava.security.KeyStore 仅显示 p12 文件中的两个证书之一
【发布时间】:2011-07-30 01:44:01
【问题描述】:

好的,我通过执行以下操作导出了浏览器中的所有证书:工具、选项...、高级、加密、查看证书、您的证书、全部备份...(这是在 Firefox 中)。

证书列表中有 4 个证书,其中两个在同一个名称下并具有不同的序列号,另外两个在不同的名称下并具有另外两个不同的序列号。所以,总而言之,有四个证书,两对具有相同的名称但不同的序列号。

如果我将此 p12 文件导入另一台机器上的另一个浏览器中,我将获得所有四个证书(如预期的那样)。

-- 但是--

当我使用 java.security.* 包打开 p12 文件并查看 size() 时,它仅显示 p12 文件中的两个证书。当我遍历别名时,我只看到两个证书。 KeyStore 对象中有什么东西可以让我访问所有四个证书吗?这很难,因为这两对的别名相同,只是序列号不同。提前感谢您提供的任何帮助。

【问题讨论】:

    标签: java security export certificate keystore


    【解决方案1】:

    好的,回答我自己的古老问题...我了解到 Java 不擅长读取 p12 文件。它使用每个证书的别名作为密钥创建一个哈希图,因此如果有两个具有相同别名的证书,Java 将使用具有相同别名(密钥)的第二个证书破坏第一个证书,从而导致每个别名只有一个证书。

    将证书导入浏览器时,浏览器会获取 p12 文件中的所有条目(不关心别名)。

    我解决此问题的方法是使用 Java 运行时 exec 功能调用 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;
    }
    

    希望对其他人有所帮助。 :)

    【讨论】:

      猜你喜欢
      • 2019-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2018-05-27
      相关资源
      最近更新 更多