#!/usr/bin/env python # -*- coding: utf-8 -*- from OpenSSL import crypto, SSL from socket import gethostname from pprint import pprint import time from os.path import exists, join def crt_import(str): return crypto.load_certificate(crypto.FILETYPE_PEM, open(str).read()) def key_import(str): return crypto.load_privatekey(crypto.FILETYPE_PEM, open(str).read()) def crt_write(crt, file): open(file, "wt").write( crypto.dump_certificate(crypto.FILETYPE_PEM, crt)) def key_write(key, file, cipher=None, passphrase=None): open(file, "wt").write( crypto.dump_privatekey(crypto.FILETYPE_PEM, key, cipher, passphrase) if cipher else crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) def write((cert, key), cert_dir="."): common_name = cert.get_subject().CN CERT_FILE = "%s.crt" % common_name KEY_FILE = "%s.key" % common_name C_F = join(cert_dir, CERT_FILE) K_F = join(cert_dir, KEY_FILE) if not exists(C_F) or not exists(K_F): crt_write(cert,C_F) key_write(key,K_F) else: print "Les fichiers %s et %s existent déjà" % (C_F, K_F) def crl_gen(crl=None, add_crt=[]): if not crl: crl=crypto.CRL() for crt in add_crt: revoked = crypto.Revoked() revoked.set_serial(hex(crt.get_serial_number())) crl.add_revoked(revoked) return crl def crl_export(crl, (ca_cert, ca_key)): return crl.export(ca_cert, ca_key) def crt_create( common_name, params={}, not_after=365*24*3600, size=4096, key=None, parent=None, extentions=[] ): """ @param parent: tuple (X509 certificate, private key) @return: (X509 certificate, private key) """ params["CN"] = common_name # common name params.setdefault("C", "FR") # country params.setdefault("ST", "Val de Marne") # state params.setdefault("L", "Cachan") # city params.setdefault("O", "Association CRANS") # organization params.setdefault("OU", "") # organization unit if not key: # create a key pair k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, size) else: k = key if k.bits() != size: raise ValueError("Key of %s bits but requesting %s bits" % (k.bits, size)) # create a certificate cert = crypto.X509() cert.get_subject().C = params["C"] cert.get_subject().ST = params["ST"] cert.get_subject().L = params["L"] cert.get_subject().O = params["O"] if params["OU"]: cert.get_subject().OU = params["OU"] cert.get_subject().CN = params["CN"] cert.set_serial_number(int((time.time() - 1386340000)*100)) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(not_after) cert.set_pubkey(k) cert.add_extensions(extentions) if parent: cert.set_issuer(parent[0].get_subject()) cert.sign(parent[1], 'sha1') else: cert.set_issuer(cert.get_subject()) cert.sign(k, 'sha1') return (cert, k) def crt_ca_root_create( common_name, params={}, size=4096, key=None, not_after=365*24*3600*10, ): extentions=[ crypto.X509Extension("basicConstraints", True, "CA:TRUE"), crypto.X509Extension("keyUsage", True, "keyCertSign, cRLSign"), ] return crt_create( common_name, params, not_after, size, key, extentions=extentions ) def crt_ca_subroot_create( common_name, parent, params={}, size=4096, key=None, not_after=365*24*3600*10, ): extentions=[ crypto.X509Extension("basicConstraints", True, "CA:TRUE, pathlen:0"), crypto.X509Extension("keyUsage", True, "keyCertSign, cRLSign"), ] return crt_create( common_name, params, not_after, size, key, parent=parent, extentions=extentions ) def crt_client_create( common_name, parent, params={}, size=4096, key=None, not_after=365*24*3600, alt_names=[] ): extentions=[ crypto.X509Extension("basicConstraints", True, "CA:FALSE"), crypto.X509Extension("keyUsage", True, "digitalSignature, nonRepudiation, keyEncipherment"), crypto.X509Extension("nsCertType", True, "sslCA"), crypto.X509Extension("extendedKeyUsage", True, "clientAuth"), # crypto.X509Extension("crlDistributionPoints", False, "URI:http://myhost.com/myca.crl"), ] for name in alt_names: extentions.append(crypto.X509Extension("subjectAltName", True, "%s" % name)) return crt_create( common_name, params, not_after, size, key, parent=parent, extentions=extentions ) def createCertRequest(pkey, digest="sha1", subjectAltName=[], **name): """ Create a certificate request. Arguments: pkey - The key to associate with the request digest - Digestion method to use for signing, default is md5 **name - The name of the subject of the request, possible arguments are: C - Country name ST - State or province name L - Locality name O - Organization name OU - Organizational unit name CN - Common name emailAddress - E-mail address Returns: The certificate request in an X509Req object """ req = crypto.X509Req() subj = req.get_subject() for (key,value) in name.items(): setattr(subj, key, value) if subjectAltName: exts = [] for altName in subjectAltName: exts.append(crypto.X509Extension("subjectAltName", True, "DNS:%s" % altName)) req.add_extensions(exts) req.set_pubkey(pkey) req.sign(pkey, digest) return req