Extracting objects from a keystore into PEM files

Extracting objects from an existing keystore into a PEM file can be useful when a keystore needs to be changed, but original PEM files are no longer available. The basic command "openssl pkcs12" parses a PKCS #12 input file and produces PEM output. It can therefore be used to extract keystore content into a PEM file for re-use with a new "openssl pkcs12 -export ..." command. As the PKCS #12 keystores are password protected, the correct password for the keystore must be supplied to access and parse the content of a keystore file.

Following are some examples for extracting objects from a keystore. The examples use the database server's keystore as it was created in the previous example. This keystore contains a private key and the corresponding user certificate as well as the (root) CA certificate, and the password for this keystore is "s1passwd".
  • Extract only the user certificate from the keystore:
    $ openssl pkcs12 -in server1.p12 -passin pass:s1passwd \
    > -clcerts -nokeys -out s1.ext1.pem

    The command parses the PKCS #12 input file "server1.p12" using password "s1passwd" and writes the output in PEM format to file "s1.ext1.pem". The option "-clcerts" tells the command to output only the user certificate, but not the CA certificate. The option "-nokeys" causes the command to exclude the private key from the output.

    The output file "s1.ext1.pem" contains the database server's user certificate in PEM format between the header and footer lines, like:
    -----BEGIN CERTIFICATE-----
    MIIDrzCCApcCAQUwDQYJKoZIhvcNAQELBQAwgaIxCzAJBgNVBAYTAlVTMRAwDgYD
    ...
    Ylz7hya2c7No4sFBRsHSQXJPXFRo0hG8ThiJZesjehmUnfE=
    -----END CERTIFICATE-----

    Besides the actual PEM object as shown above, the output file contains some information on the PEM object, like the attributes friendly name and localKeyID of the SafeBag containers in the PKCS #12 keystore. In case of a certificate, also the certificate's issuer name and subject name are included as human readable information. This makes it fairly easy to verify, that the desired object was extracted from the keystore. The additional information can be removed with a text editor, if this is deemed necessary. However, the header and footer lines marking the begin and end of the PEM content should remain intact. Usually, other "openssl" commands that accept a PEM file as input conveniently ignore the additional, human readable information.

    The PEM output file can be further parsed by the appropriate "openssl" command. For certificates in a PEM file, this is the command "openssl x509", e.g.:
    $ openssl x509 -in s1.ext1.pem -text -noout
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number: 5 (0x5)
            Signature Algorithm: sha256WithRSAEncryption
            Issuer: C = US, ST = Florida, L = Anytown, O = Acme Software Inc.,
                    OU = Database CA, CN = Database CA Root1,
                    emailAddress = dba_ca1@acme.info
            Validity
               Not Before: Jun 2 16:10:19 2021 GMT
               Not After : Jun 2 16:10:19 2022 GMT
    ...

    Omitting the option "-nokeys" from the extract command includes the private key separate PEM section in the output. Because by default private keys get protected with PBE (password based encryption), the command without "-nokeys" then prompts twice for the password to use for the private key. The interactive prompting for this password can be avoided by either providing the password on the command line as "-passout pass:..." or by not protecting the private key in the PEM file with the option "-nodes". PEM output files that contain unprotected private keys should not be left 'unattended'.

    The PEM section with a PBE protected private key in an output file would look like:
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIDRjU76XwLYUCAggA
    ...
    1Dw3Imvms7AnpD+4iOGNAg==
    -----END ENCRYPTED PRIVATE KEY-----
  • Extract only the CA certificate(s) from the keystore:
    $ openssl pkcs12 -in server1.p12 -passin pass:s1passwd \
    > -cacerts -nokeys -out s1.ext2.pem
    

    Here, the option "-cacerts" tells the command to only output CA certificates but no user certificate. Without the option "-nokeys", the private key would be included in the output as explained already above. Also as explained above, the certificate in the output PEM file "s1.ext2.pem" can be further parsed using the command "openssl x509 -in s1.ext2.pem -text -noout".

  • Extract only the private key from the keystore:
    $ openssl pkcs12 -in server1.p12 -passin pass:s1passwd -nocerts \
    > -passout pass:pkextpw -out s1.ext3.pem
    Here, the option "-nocerts" excludes all certificates from the output. With that, only the private key is included in the output. By default, the private key is PBE protected in the output and therefore, the password for the output is provided as "pkextpw" with the option "-passout pass:pkextpw". The PEM section in the output file "s1.ext3.pem" looks like the following:
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQINL3IaWjpZeACAggA
    ...
    JmO+VpfOb/o6BNN9UfcHcA==
    -----END ENCRYPTED PRIVATE KEY-----
    Knowing that the database server's private key is a RSA key, the private key in the PEM output file can be parsed with the following command. As the private key in the PEM file is password protected, the password is needed:
    $ openssl rsa -in s1.ext3.pem -passin pass:pkextpw -text -noout
    RSA Private-Key: (2048 bit, 2 primes)
    modulus:
        00:e1:7b:21:f4:dc:b1:be:d3:2a:5c:33:69:75:35:
        ...
        6b:ab
    publicExponent: 65537 (0x10001)
    privateExponent:
        07:2f:ee:98:28:84:bd:e9:6b:3b:3f:24:48:69:28:
        ...
        89
    prime1:
        00:fb:5c:69:e2:c4:8e:b6:91:81:35:e6:bd:a2:71:
        ...
        52:73:58:17:9f:46:fd:d1:b7
    prime2:
        00:e5:a4:72:1a:81:66:b8:b1:e0:6f:9a:4f:dc:ad:
        ...
        8d:ca:f8:d0:ab:34:cb:e5:ad
    exponent1:
        70:e7:20:94:80:0f:4e:47:eb:0e:c7:f6:b3:c9:7a:
        ...
        d5:ea:62:a9:e3:5c:4c:df
    exponent2:
        51:71:98:12:34:70:84:f2:79:01:bb:bd:b5:2b:68:
        ...
        b9:5f:b3:49:f5:08:97:65
    coefficient:
        25:68:e6:7d:50:f3:40:02:69:03:44:bf:10:39:e3:
        ...
        71:2c:27:ed:c3:40:87:5e
    It is possible to extract the private key without PBE protection by using the option "-nodes". In this case, no output password with option "-passout pass:..." is needed. The PEM section of an unprotected private key in the output file would look like:
    -----BEGIN PRIVATE KEY-----
    MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDheyH03LG+0ypc
    ...
    usCJOrhtwwVxLCftw0CHXg==
    -----END PRIVATE KEY-----
    Warning: PEM files containing unprotected private keys should not be left 'unattended'.
  • Extracting all objects from a keystore into a single PEM file:
    $ openssl pkcs12 -in server1.p12 -passin pass:s1passwd \
    > -out s1.ext4.pem -passout pass:s1extpw

    Using the input password "s1passwd", the command parses the PKCS #12 input file "server1.p12" and writes all objects found in the keystore to the PEM output file "s1.ext4.pem". The private key in the PEM output file is PBE protected with the output password "s1extpw". As expected, the output file contains the encrypted private key, the user certificate that corresponds to the private key, and the root CA certificate.

    As with the previous example, using option "-nodes" instead of option "-passout pass:s1extpw" would write the private key without PBE protection to the output file.