1

I am still very new when it comes to python and I need a way to convert .pem certificate to a .pfx type.

I found that there is an OpenSSL library for python and looked at the documentation but I did not see anything that showed me how to convert a certificate from type A to type B (let alone to a pfx type.)

I did see how you can access the properties of a certificate, but that is not helping me.

Does anyone have a good link or an example showing how this is done in python they can share?

2 Answers2

0

You can use [PyPI]: pyOpenSSL.

I'll base my example on the certificate from [SO]: How can I decode a SSL certificate using python?.

Img0

code.py:

#!/usr/bin/env python3

import sys
from OpenSSL import crypto


IN_FILE = "./in.crt"
OUT_FILE = "./out.pfx"


def main():
    with open(IN_FILE, "rb") as fin:
        pem_text = fin.read()
    print("Input length: {:d}".format(len(pem_text)))
    cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_text)

    print("CERTIFICATE DATA\n    Serial: 0x{:X}\n    Issuer: {:}\n    Subject: {:}\n    Not before: {:}\n    Not after: {:}".format(
            cert.get_serial_number(), cert.get_issuer(), cert.get_subject(), cert.get_notBefore(), cert.get_notAfter()))
    p12 = crypto.PKCS12()
    p12.set_certificate(cert)
    p12_text = p12.export()
    print("Output length: {:d}".format(len(p12_text)))
    with open(OUT_FILE, "wb") as fout:
        fout.write(p12_text)
    print("Done.")


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Output:

e:\Work\Dev\StackOverflow\q054562125>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe"  code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

Input length: 2544
CERTIFICATE DATA
    Serial: 0xE77768A5D07F0E57959CA2A9D5082B5
    Issuer: <X509Name object '/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV CA-1'>
    Subject: <X509Name object '/businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=California/serialNumber=C3268102/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=github.com'>
    Not before: b'20110527000000Z'
    Not after: b'20130729120000Z'
Output length: 2044
Done.

And the PFX test (in Cygwin console):

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054562125]> ls
code.py  in.crt  out.pfx
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054562125]> certutil -dumpPFX out.pfx
Version: 3
    1.2.840.113549.1.7.1 PKCS 7 Data

authSafe count: 1
----------------------------------------------------------------
authSafe[0]:
    1.2.840.113549.1.7.6 PKCS 7 Encrypted
    Version: 0
    Content Type: 1.2.840.113549.1.7.1 PKCS 7 Data
    Content Encryption Algorithm: 1.2.840.113549.1.12.1.3 szOID_PKCS_12_pbeWithSHA1And3KeyTripleDES
Algorithm Parameters:
0000: 30 0e                                     ; SEQUENCE (e Bytes)
0002:    04 08                                  ; OCTET_STRING (8 Bytes)
0004:    |  d3 21 37 37 7a 70 e7 08                           ; .!77zp..
000c:    02 02                                  ; INTEGER (2 Bytes)
000e:       08 00
Decrypted content:
    bagId: 1.2.840.113549.1.12.10.1.3 szOID_PKCS_12_CERT_BAG
    1.2.840.113549.1.9.22.1 szOID_PKCS_12_CERT_TYPE_X509
================ Begin Nesting Level 1 ================
Serial Number: 0e77768a5d07f0e57959ca2a9d5082b5
Issuer: CN=DigiCert High Assurance EV CA-1, OU=www.digicert.com, O=DigiCert Inc, C=US
 NotBefore: 2011-05-27 02:00
 NotAfter: 2013-07-29 14:00
Subject: CN=github.com, O=GitHub, Inc., L=San Francisco, S=California, C=US, SERIALNUMBER=C3268102, OID.1.3.6.1.4.1.311.60.2.1.2=California, OID.1.3.6.1.4.1.311.60.2.1.3=US, OID.2.5.4.15=Private Organization
Non-root Certificate
Cert Hash(sha1): ce6799252cac78127d94b5622c31c516a6347353
----------------  End Nesting Level 1  ----------------

----------------------------------------------------------------
Hash Algorithm: 1.3.14.3.2.26 sha1 (sha1NoSign)
Mac:
    8fe6e58f236fa353ff5c7375a35c0aab062ccee9
Salt:
    034c9198964b2ed2
Iteration count (Default): 1
Computed Mac:
    8fe6e58f236fa353ff5c7375a35c0aab062ccee9
CertUtil: -dumpPFX command completed successfully.
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • Did this answer your question? – CristiFati Feb 07 '19 at 16:32
  • I attempted to run your code to see if it works and I get back an error - "AttributeError: 'module' object has no attribute 'load_certificate'. Can you tell me what version of your OpenSSL library is? I am thinking maybe I have an outdated or corrupted installation. – Michael Landeros Feb 07 '19 at 16:39
  • Could you be more specific? What is the error? what is the certificate used? – CristiFati Feb 07 '19 at 16:40
  • I began running your code line by line and once I attempt to run this line: "cert = crypto.load_certficate(crypto.FILETYPE_PEM, pem_text)", it errors with - \cryptography\utils.py", line 124, in __getattr__ obj = getattr(self._module, attr) AttributeError: 'module' object has no attribute 'load_certficate' – Michael Landeros Feb 07 '19 at 16:49
  • I am passing in the the content of my .crt file into the pem_text variable. – Michael Landeros Feb 07 '19 at 16:50
  • What does `import cryptography;cryptography.__version__` output? I have *2.4.2*.. What *Python* version and *OS* are you using (these should have been specified in the question)? – CristiFati Feb 07 '19 at 17:05
0

This is what worked for me:

Generate a self-signed certificate in the .pem format

$ openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

Now, open the python console and run this:

with open('key.pem', 'r') as file:
    private_key = file.read()

with open('cert.pem', 'r') as file:
    certificate = file.read()


import OpenSSL
key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, private_key)
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate)
pkcs = OpenSSL.crypto.PKCS12()
pkcs.set_privatekey(key)
pkcs.set_certificate(cert)

with open('cert.pfx', 'wb') as file:
    file.write(pkcs.export(passphrase="mypassword".encode('ASCII'))) 

This script will read the private key and certificate, and generate a .pfx certificate.

Rodrigo Dias
  • 1,331
  • 2
  • 13
  • 18