0

I am currently installing an SSL certificate on an IBM Httpd server's port using a code written by me. The code installs the certificate as follows:

  1. Creates a password protected .p12 file containing the private key object and an end entity certificate (passed as an X509Certificate array of 1 element).

    public static KeyStore createKeyStoreFromKeyAndCertChain(String encoding,
        String friendlyName, X509Certificate[] certChain, 
        PrivateKey key, String password)
        throws KeyStoreException, CertificateException,
        NoSuchAlgorithmException, IOException {
    KeyStore store = KeyStore.getInstance(encoding);
    store.load(null, null);
    store.setKeyEntry(friendlyName, key, password.toCharArray(), certChain);
    return store; 
    

This correctly generates a .p12 file which is parsable using openssl and keytool.

  1. Uses the following commands to create a .kdb file, add issuer certs to the .kdb file and then add the .p12 file (containing the private key and end entity cert) created in Step 1.

"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -keydb -create -db "C:\Work\Certs\IBM certs\test.kdb" -pw password -type cms -expire 60 -stash

"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -add -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label icacert -file "C:\renewcert\ica.cer" -trust enable

"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -add -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label rootcert -file "C:\renewcert\rootCert.cer" -trust enable

"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -import -db "C:\renewcert\certWithPvtKey.p12" -pw password -target "C:\Work\Certs\IBM certs\httpdkey.kdb" -target_pw password -target_type cms

This creates a .kdb file.

  1. Updates the virtual host directive inside httpd.conf file to store information corresponding to the newly created .kdb file:
    Listen 10.212.143.105:6042
    <VirtualHost 10.212.143.105:6042>
         SSLEnable
         SSLProtocolDisable SSLv2

         SSLServerCert ibmhttpdsslcert
         KeyFile "C:\Work\Certs\IBM certs\key1.kdb"
         SSLStashFile "C:\Work\Certs\IBM certs\key1.sth"

    </VirtualHost>

The label used for tag SSLServerCert is same as the friendly name used to create .p12 in step 1.

The certificate is discoverable through our application (which uses Java based SSL certificate discovery) and through openssl also.

Problem

We need to now export the original .p12 out of the .kdb file. For the same, following command is used:

"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -export -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label ibmhttpdsslcert -type cms -target "C:\Work\Certs\IBM certs\certChain.p12" -target_pw password -target_type pkcs12

What essentially happens is that the .p12 file that gets generated appears to be corrupted and is not parsable using the following code:

public static void main(String[] args) throws Exception {
        
    
    String password = "password";
    
    // Read the .p12 and convert it to Java objects
    FileInputStream fm = new FileInputStream(new File("C:\\Work\\Certs\\IBM certs\\certChain.p12"));
    KeyStore ks = KeyStore.getInstance("PKCS12");
    try {
        ks.load(fm, password.toCharArray());
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    System.out.println("Size- " +ks.size());
    
    Enumeration aliases = ks.aliases();

    while(aliases.hasMoreElements()){
        String param = (String) aliases.nextElement();
        System.out.println("Param- " +param);
    }
    
    
    KeyStore.ProtectionParameter protParam =
            new KeyStore.PasswordProtection(password.toCharArray());

    // Retrieve the key using the alias "IBMHttpdSSLCert"
    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
        ks.getEntry("IBMHttpdSSLcert", protParam);
    PrivateKey myPrivateKey = pkEntry.getPrivateKey();
    
    Object pemObject = myPrivateKey;
    
    // Write the key to file
    JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(new File("C:\\Work\\pvtKey.pem")));
    pemWriter.writeObject(pemObject);
    pemWriter.close();
    
    System.out.println("Pvt key- " +myPrivateKey);
    
    fm.close();
}

What happens is that the size of the keystore is reported as zero (0) and the keystore file is not parsable using keytool also. The same is however parsable using openssl but we cannot bundle openssl in out code binary.

Any idea if it is a known bug with IBM's implementation for keystore export ?

Community
  • 1
  • 1
  • If there is no JKS involved at all, I generally find $IHSROOT/bin/gskcapicmd to do a better job to/from CMS/P12. It's also much faster. You also may be able to get away with a one-liner for -keydb -convert. – covener Nov 07 '16 at 18:02
  • Thanks covener. gskcapicmd worked seamlessly for me. I was able to export the keystore (.p12) correctly out of the .kdb file and proceed. Thanks for the help ! – Ankit Sharma Nov 08 '16 at 17:53

0 Answers0