简体   繁体   中英

java.security.KeyStore shows only one of two certs in a p12 file

Ok, I exported all the certs in my browser by doing this: Tools, Options..., Advanced, Encryption, View Certificates, Your Certificates, Backup All... (this is in Firefox).

There are 4 certs in the list of Certificates, two are under one Name and have distinct serial numbers, and the other two are under a different name and have two other distinct serial numbers. So, in summary, there are four certs, two pair have the same name but distinct serial numbers.

If I were to import this p12 file into another browser on another machine I get all four certs (as expected).

-- BUT --

When I open the p12 file with the java.security.* package and look at the size(), it shows only two certs in the p12 file. When I loop through the aliases I see only two certs. Is there something in the KeyStore object that allows me access to all four certs? It's tough because the aliases are the same for the two pairs, only the serial numbers are different. Thanks in advance for any help you can provide.

Ok, to answer my own ancient question... I learned that Java is not that good at reading p12 files. It creates a hashmap using the alias of each certificate as the key so if there are two certs with the same alias, Java will clobber the first cert with the second cert with the same alias (key), rsulting in only one cert per alias.

When importing the certs into a browser, the browser takes all the entries in the p12 file (not caring about the aliases).

The way I worked around this was to use Java runtime exec functionality to call openssl and pipe the output of each cert into a String and using that string to create an X509Certificate. Here's some sample code (I cannot copy and paste as my dev box is not internet connected):

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;
}

Hope that helps others. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM