I use create_certs.py at build time in the Debian packaging to avoid dealing with expired certs. Since Debian is in the process of trying to remove Python 2, I've updated the script to work with Python 3.
It would also be useful if 1.4 were released, so I could switch to the CMake build. Cheers, -- James GPG Key: 4096R/91BF BF4D 6956 BD5D F7B7 2D23 DFE6 91AE 331B A3DB
Index: test/certs/create_certs.py =================================================================== --- test/certs/create_certs.py (revision 1870782) +++ test/certs/create_certs.py (working copy) @@ -47,11 +47,11 @@ key = crypto.PKey() key.generate_key(KEY_ALGO, KEY_SIZE) if passphrase: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + open(keyfile, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key, KEY_CIPHER, passphrase)) else: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + open(keyfile, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) return key @@ -62,7 +62,7 @@ pkcs12.set_certificate(clientcert) pkcs12.set_privatekey(clientkey) pkcs12.set_ca_certificates([issuer]) - open(pkcs12file, "wt").write(pkcs12.export(passphrase=passphrase, + open(pkcs12file, "wb").write(pkcs12.export(passphrase=passphrase, iter=2048, maciter=2048)) def create_crl(revokedcert, cakey, cacert, crlfile, next_crl_days=VALID_DAYS): @@ -69,12 +69,12 @@ crl = crypto.CRL() revoked = crypto.Revoked() - serial_number = "%x" % revokedcert.get_serial_number() + serial_number = b"%x" % revokedcert.get_serial_number() now = datetime.utcnow() - now_str = now.strftime('%Y%m%d%H%M%SZ') + now_str = now.strftime('%Y%m%d%H%M%SZ').encode('utf-8') revoked.set_serial(serial_number) - revoked.set_reason('unspecified') + revoked.set_reason(b'unspecified') revoked.set_rev_date(now_str) # revoked as of now crl.add_revoked(revoked) @@ -84,7 +84,7 @@ # Some very old versions of pyopenssl (such as the one on macOS) # do not support the 'digest' keyword argument. exported = crl.export(cacert, cakey, days=next_crl_days) - open(crlfile, "wt").write(exported) + open(crlfile, "wb").write(exported) # subjectAltName def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='', @@ -96,7 +96,7 @@ subjectAltName Array of fully qualified subject alternative names (use OpenSSL syntax): - For a DNS entry, use: ['DNS:localhost']. Other options are 'email', 'URI', 'IP'. + For a DNS entry, use: [b'DNS:localhost']. Other options are b'email', b'URI', b'IP'. ''' cert = crypto.X509() @@ -122,34 +122,34 @@ if ca: cert.add_extensions([ - crypto.X509Extension("basicConstraints", False, - "CA:TRUE"), - crypto.X509Extension("subjectKeyIdentifier", False, "hash", + crypto.X509Extension(b"basicConstraints", False, + b"CA:TRUE"), + crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash", subject=cert) ]) cert.add_extensions([ - crypto.X509Extension("authorityKeyIdentifier", False, - "keyid:always", issuer=issuer) + crypto.X509Extension(b"authorityKeyIdentifier", False, + b"keyid:always", issuer=issuer) ]) - if subjectAltName: + if subjectAltName is not None: critical = True if not cn else False cert.add_extensions([ - crypto.X509Extension('subjectAltName', critical, ", ".join(subjectAltName))]) + crypto.X509Extension(b'subjectAltName', critical, ", ".join(subjectAltName).encode('utf-8'))]) - if ocsp_responder_url: + if ocsp_responder_url is not None: cert.add_extensions([ - crypto.X509Extension('authorityInfoAccess', False, - 'OCSP;URI:' + ocsp_responder_url)]) + crypto.X509Extension(b'authorityInfoAccess', False, + 'OCSP;URI:{}'.format(ocsp_responder_url).encode('utf-8'))]) if ocsp_signer: cert.add_extensions([ - crypto.X509Extension('extendedKeyUsage', True, 'OCSPSigning') + crypto.X509Extension(b'extendedKeyUsage', True, b'OCSPSigning') ]) cert.sign(issuerkey, SIGN_ALGO) - open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, + open(certfile, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) return cert @@ -156,7 +156,7 @@ if __name__ == '__main__': # root CA key pair and certificate. # This key will be used to sign the intermediate CA certificate - rootcakey = create_key('private/serfrootcakey.pem', 'serftest') + rootcakey = create_key('private/serfrootcakey.pem', b'serftest') rootcacert = create_cert(subjectkey=rootcakey, certfile='serfrootcacert.pem', @@ -167,7 +167,7 @@ # intermediate CA key pair and certificate # This key will be used to sign all server certificates - cakey = create_key('private/serfcakey.pem', 'serftest') + cakey = create_key('private/serfcakey.pem', b'serftest') cacert = create_cert(subjectkey=cakey, certfile='serfcacert.pem', issuer=rootcacert, issuerkey=rootcakey, @@ -178,7 +178,7 @@ # server key pair # server certificate, no errors - serverkey = create_key('private/serfserverkey.pem', 'serftest') + serverkey = create_key('private/serfserverkey.pem', b'serftest') servercert = create_cert(subjectkey=serverkey, certfile='serfservercert.pem', @@ -247,7 +247,7 @@ ocsp_signer=True) # client key pair and certificate - clientkey = create_key('private/serfclientkey.pem', 'serftest') + clientkey = create_key('private/serfclientkey.pem', b'serftest') clientcert = create_cert(subjectkey=clientkey, certfile='serfclientcert.pem', @@ -258,10 +258,10 @@ email='serfcli...@example.com') clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert, - 'serfclientcert.p12', 'serftest') + 'serfclientcert.p12', b'serftest') # Note that this creates a v1 CRL file without extensions set, and with # MD5 hash. Not ideal, but pyOpenSSL doesn't support more than this. # # crl - crl = create_crl(servercert, cakey, cacert, 'serfservercrl.pem') + crl = create_crl(servercert, cakey, cacert, b'serfservercrl.pem')