Python: reading a pkcs12 certificate with pyOpenSSL.crypto Python: reading a pkcs12 certificate with pyOpenSSL.crypto python python

Python: reading a pkcs12 certificate with pyOpenSSL.crypto


It's fairly straight-forward to use. This isn't tested, but should work:

# load OpenSSL.cryptofrom OpenSSL import crypto# open it, using password. Supply/read your own from stdin.p12 = crypto.load_pkcs12(open("/path/to/cert.p12", 'rb').read(), passwd)# get various properties of said file.# note these are PyOpenSSL objects, not strings although you# can convert them to PEM-encoded strings.p12.get_certificate()     # (signed) certificate objectp12.get_privatekey()      # private key.p12.get_ca_certificates() # ca chain.

For more examples, have a look through the unit test code of pyopenssl. Pretty much every way you might want to use the library is there

See also here or without adverts here.


Maybe is wrong answering to an old Q, but I thought that it may help someone that find this Q after me. This solution work for python 3, and I think is a little bit better. I found it in the repo of zeep and is a class to encapsule the usage.

Class

import osfrom OpenSSL import cryptoclass PKCS12Manager():    def __init__(self, p12file, passphrase):        self.p12file = p12file        self.unlock = passphrase        self.webservices_dir = ''        self.keyfile = ''        self.certfile = ''        # Get filename without extension        ext = os.path.splitext(p12file)        self.filebasename = os.path.basename(ext[0])        self.createPrivateCertStore()        self.p12topem()    def getKey(self):        return self.keyfile    def getCert(self):        return self.certfile    def createPrivateCertStore(self):        home = os.path.expanduser('~')        webservices_dir = os.path.join(home, '.webservices')        if not os.path.exists(webservices_dir):            os.mkdir(webservices_dir)        os.chmod(webservices_dir, 0o700)        self.webservices_dir = webservices_dir    def p12topem(self):        p12 = crypto.load_pkcs12(open(self.p12file, 'rb').read(), bytes(self.unlock, 'utf-8'))        # PEM formatted private key        key = crypto.dump_privatekey(crypto.FILETYPE_PEM, p12.get_privatekey())        self.keyfile = os.path.join(self.webservices_dir, self.filebasename + ".key.pem")        open(self.keyfile, 'a').close()        os.chmod(self.keyfile, 0o600)        with open(self.keyfile, 'wb') as f:            f.write(key)        # PEM formatted certificate        cert = crypto.dump_certificate(crypto.FILETYPE_PEM, p12.get_certificate())        self.certfile = os.path.join(self.webservices_dir, self.filebasename + ".crt.pem")        open(self.certfile, 'a').close()        os.chmod(self.certfile, 0o644)        with open(self.certfile, 'wb') as f:            f.write(cert)

Usage

from requests import Sessionfrom zeep import Clientfrom zeep.transports import Transport# https://github.com/mvantellingen/python-zeep/issues/824pkcs12 = PKCS12Manager('cert.p12', 'password_for_cert')session = Session()session.cert = (pkcs12.getCert(), pkcs12.getKey())transport = Transport(session=session)client = Client('url_service', transport=transport)


As pyOpenSSL.crypto.load_pkcs12 is now deprecated, here is the equivalent solution using cryptography, with loading inside a requests Session as a bonus.

from cryptography.hazmat.primitives import serializationfrom requests import Sessionwith open("./cert.p12", "rb") as f:    (        private_key,        certificate,        additional_certificates,    ) = serialization.pkcs12.load_key_and_certificates(        f.read(), CLIENT_CERT_KEY.encode()    )# key will be available in user readable temporary file for the time of the# program run (until key and cert get gc'ed)key = tempfile.NamedTemporaryFile()cert = tempfile.NamedTemporaryFile()key.write(    private_key.private_bytes(        encoding=serialization.Encoding.PEM,        format=serialization.PrivateFormat.PKCS8,        encryption_algorithm=serialization.NoEncryption(),    ))key.flush()cert.write(    certificate.public_bytes(serialization.Encoding.PEM),)cert.flush()session = Session()session.cert = (cert.name, key.name)