201 lines
5.5 KiB
Python
201 lines
5.5 KiB
Python
#!/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
|
|
|