333

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?

3
  • 1
    @jww I think given that this question is over 3 years old that it is a bit late to signal the off-topic flag. Commented Nov 27, 2016 at 23:11
  • 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
    Commented Nov 27, 2016 at 23:26
  • 5
    @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
    Commented Feb 28, 2017 at 14:41

7 Answers 7

823

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'
12
  • 2
    Is it possible that private key and certificate would be stored in the same *.pem file?
    – Ramis
    Commented Sep 25, 2015 at 10:08
  • 32
    yes, it is: openssl pkcs12 -in path.p12 -out newfile.pem
    – Gee-Bee
    Commented Oct 3, 2015 at 18:58
  • 2
    asking for Import Password . what is that ? Commented Jan 11, 2016 at 8:44
  • 5
    @SaurabhChandraPatel you have to know the password for your certificate. This isn't a means to recover a forgotten password Commented Feb 22, 2016 at 15:14
  • 3
    omitting -nodes, the private key does not get extracted.
    – Meixner
    Commented Oct 17, 2016 at 12:53
26

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

20

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())
8
  • Is there any reason to open the file using file and not open? I just want to understand it as I am going to use it in future (to simplify my solution calling openssh as command) Commented May 8, 2014 at 21:40
  • Nope, no difference. You can just do open("push.p12", 'rb').read().
    – KVISH
    Commented May 9, 2014 at 0:03
  • 3
    If using python 3 you'll probably want to write the contents to files: with open("push.pem", "wb") as fobj: fobj.write(crypto.dump_certificate(crypto.FILETYPE_PEM, p12.get_certificate())) to write the cert and with open("push.key", "wb") as fobj: fobj.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, p12.get_privatekey())) for the key. Commented Jun 18, 2018 at 18:55
  • I'm using python 3.7, when running the above example, I get the following: "TypeError: initializer for ctype 'char' must be a bytes of length 1, not str" Is there something wrong with my password
    – getaglow
    Commented Nov 29, 2018 at 15:29
  • 1
    Why is it "even easier" to create a file, enter the code, save it, and run it -- rather than just executing a single command? Commented Jul 2, 2019 at 11:57
19

On Macbook M1 with openssl installed through homebrew i had to add -legacy option:

openssl pkcs12 -in certificate.p12 -out certificate.pem -noenc -legacy

2
  • Without the -legacy flag, you'll get: Error outputting keys and certificates 4062F80002000000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:355:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()
    – T'Pol
    Commented Jul 5 at 15:51
  • It worked like a charm. Thanks. Commented Jul 25 at 21:11
13

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

4

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.

3
#!/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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.