261
votes

I have OpenSSL x64 on Windows 7 which I downloaded from openssl-for-windows on Google Code. I'm attempting to run:

openssl pkcs12 -export -in "path.p12" -out "newfile.pem" 

but I get an error.

unable to load private key

How do I extract the certificate in PEM from PKCS#12 store using OpenSSL?

7
@jww I think given that this question is over 3 years old that it is a bit late to signal the off-topic flag.Dean MacGregor
Just a formality so folks know its off-topic. People are asking the same off-topic questions, and citing this question. If folks are not told its off-topic, then they will continue to ask on Stack Overflow.jww
@jww the highest voted answer on the meta question you link says "DevOps questions should be allowed on Stack Overflow." I will upvote, because the answer met my needs (although, for me, I wasn't programming, I could easily incorporate the answer in a program if I wished)dcorking

7 Answers

639
votes

Try:

openssl pkcs12 -in path.p12 -out newfile.crt.pem -clcerts -nokeys
openssl pkcs12 -in path.p12 -out newfile.key.pem -nocerts -nodes

After that you have:

  • certificate in newfile.crt.pem
  • private key in newfile.key.pem

To put the certificate and key in the same file without a password, use the following, as an empty password will cause the key to not be exported:

openssl pkcs12 -in path.p12 -out newfile.pem -nodes

Or, if you want to provide a password for the private key, omit -nodes and input a password:

openssl pkcs12 -in path.p12 -out newfile.pem

If you need to input the PKCS#12 password directly from the command line (e.g. a script), just add -passin pass:${PASSWORD}:

openssl pkcs12 -in path.p12 -out newfile.crt.pem -clcerts -nokeys -passin 'pass:P@s5w0rD'
22
votes

You just need to supply a password. You can do it within the same command line with the following syntax:

openssl pkcs12 -export -in "path.p12" -out "newfile.pem" -passin pass:[password]

You will then be prompted for a password to encrypt the private key in your output file. Include the "nodes" option in the line above if you want to export the private key unencrypted (plaintext):

openssl pkcs12 -export -in "path.p12" -out "newfile.pem" -passin pass:[password] -nodes

More info: http://www.openssl.org/docs/apps/pkcs12.html

19
votes

If you can use Python, it is even easier if you have the pyopenssl module. Here it is:

from OpenSSL import crypto

# May require "" for empty password depending on version

with open("push.p12", "rb") as file:
    p12 = crypto.load_pkcs12(file.read(), "my_passphrase")

# PEM formatted private key
print crypto.dump_privatekey(crypto.FILETYPE_PEM, p12.get_privatekey())

# PEM formatted certificate
print crypto.dump_certificate(crypto.FILETYPE_PEM, p12.get_certificate())
3
votes

I had a PFX file and needed to create KEY file for NGINX, so I did this:

openssl pkcs12 -in file.pfx -out file.key -nocerts -nodes

Then I had to edit the KEY file and remove all content up to -----BEGIN PRIVATE KEY-----. After that NGINX accepted the KEY file.

2
votes

There is a free and open-source GUI tool KeyStore Explorer to work with crypto key containers. Using it you can export a certificate or private key into separate files or convert the container into another format (jks, pem, p12, pkcs12, etc)

enter image description here

0
votes
#!/usr/bin/env python3
from optparse import Option
from OpenSSL import crypto
import os
import warnings
from getpass import getpass
warnings.filterwarnings("ignore", category=DeprecationWarning) 

def sanitize_path(path):
    return os.path.expandvars(os.path.expanduser(path))

def main(in_file, out_file, passphrase=None):
    if not passphrase:
        passphrase = getpass(prompt=("SSL Private Key Passphrase: "))
   
    in_file = sanitize_path(in_file)
    out_file = sanitize_path(out_file)
    
    with open(in_file, "rb") as input_file:
        p12 = crypto.load_pkcs12(input_file.read(), passphrase)
        pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, p12.get_privatekey())
    with open(out_file, "w") as output_file:
        output_file.write(pem.decode('utf-8'))

if __name__ == '__main__':
    from optparse import OptionParser
    usage = "usage: %prog  input_file output_file [passphrase]"
    p = OptionParser(usage=usage)
    opt, args = p.parse_args()
    main(*args)
-2
votes

If you need a PEM file without any password you can use this solution.

Just copy and paste the private key and the certificate to the same file and save as .pem.

The file will look like:

-----BEGIN PRIVATE KEY-----
............................
............................
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
...........................
...........................
-----END CERTIFICATE-----

That's the only way I found to upload certificates to Cisco devices for HTTPS.