Last active
August 29, 2015 13:56
-
-
Save kalloc/9226971 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from OpenSSL.crypto import ( | |
X509Extension, PKey, X509 | |
) | |
from OpenSSL.crypto import ( | |
TYPE_RSA, FILETYPE_PEM | |
) | |
from OpenSSL.crypto import ( | |
dump_privatekey, dump_certificate, | |
load_privatekey, load_certificate | |
) | |
from time import time | |
from socket import gethostname | |
from os.path import exists | |
import argparse | |
def set_common_names(cert, name): | |
cert.get_subject().C = "US" | |
cert.get_subject().ST = "Minnesota" | |
cert.get_subject().L = "Minnetonka" | |
cert.get_subject().O = "my company" | |
cert.get_subject().OU = "my organization" | |
cert.get_subject().CN = name | |
return cert | |
def create_server_cert(args, ca_cert, ca_key): | |
print '[I] generate new certificate for', args.hostname | |
# create a key pair | |
k = PKey() | |
k.generate_key(TYPE_RSA, 4096) | |
cert = X509() | |
cert.set_serial_number(int(time())) | |
cert.gmtime_adj_notBefore(0) | |
cert.gmtime_adj_notAfter(1 * 365 * 24 * 60 * 60) | |
cert.set_issuer(ca_cert.get_subject()) | |
cert.set_pubkey(k) | |
set_common_names(cert, args.hostname) | |
ext = [] | |
ext.append(X509Extension('basicConstraints', True, 'CA:FALSE')) | |
ext.append(X509Extension('nsCertType', True, | |
'server, email, objsign')) | |
ext.append(X509Extension('extendedKeyUsage', True, 'serverAuth')) | |
ext.append(X509Extension('subjectKeyIdentifier', False, 'hash', cert)) | |
ext.append(X509Extension('authorityKeyIdentifier', False, | |
'keyid, issuer:always', issuer=ca_cert)) | |
ext.append(X509Extension( | |
'keyUsage', True, | |
'nonRepudiation, digitalSignature, keyEncipherment')) | |
cert.add_extensions(ext) | |
cert.sign(ca_key, 'sha1') | |
open(args.cert, "w").write( | |
dump_certificate(FILETYPE_PEM, cert)) | |
open(args.cert, "a").write( | |
dump_certificate(FILETYPE_PEM, ca_cert)) | |
open(args.cert, "a").write( | |
dump_privatekey(FILETYPE_PEM, k)) | |
return [cert, k] | |
def create_self_signed_cert(args): | |
if not exists(args.ca): | |
print '[W] unable to found exists CA' | |
print '[I] generate new CA certificate' | |
# create a key pair | |
k = PKey() | |
k.generate_key(TYPE_RSA, 4096) | |
# create a self-signed cert | |
cert = X509() | |
set_common_names(cert, gethostname()) | |
cert.set_serial_number(1000) | |
cert.gmtime_adj_notBefore(0) | |
cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) | |
cert.set_issuer(cert.get_subject()) | |
cert.set_pubkey(k) | |
cert_extensions = ( | |
('nsCertType', False, 'sslCA, emailCA'), | |
('basicConstraints', True, 'CA:TRUE'), | |
('subjectKeyIdentifier', False, 'hash', cert), | |
('keyUsage', True, 'keyCertSign,cRLSign') | |
) | |
ext = map(lambda e: X509Extension(*e), cert_extensions) | |
cert.add_extensions(ext) | |
cert.sign(k, 'sha1') | |
open(args.ca, "w").write( | |
dump_certificate(FILETYPE_PEM, cert)) | |
if args.ca_cert: | |
open(args.ca_cert, "w").write( | |
dump_certificate(FILETYPE_PEM, cert)) | |
open(args.ca, "a").write( | |
dump_privatekey(FILETYPE_PEM, k)) | |
return [cert, k] | |
else: | |
print '[I] CA exists' | |
ca_cert = load_certificate(FILETYPE_PEM, open(args.ca).read()) | |
ca_key = load_privatekey(FILETYPE_PEM, open(args.ca).read()) | |
return [ca_cert, ca_key] | |
if __name__ == '__main__': | |
""" | |
python ssl_for_web.py --ca ca.pem --ca-cert ca.crt --cert cert.pem --hostname *.ssl.ru | |
[W] I can't found an existing CA | |
[I] generate the new CA certificate | |
[I] generate the new certificate for *.ssl.ru | |
[I] done | |
openssl verify -verbose -CAfile ca.pem -purpose sslserver cert.pem | |
cert.pem: OK | |
""" | |
parser = argparse.ArgumentParser( | |
description='Create SSL certificate for the web server') | |
parser.add_argument('--ca', required=True, help='path to the CA pem') | |
parser.add_argument('--ca-cert', required=False, help='path to the CA cert pem') | |
parser.add_argument('--cert', required=True, help='path to a webserver pem') | |
parser.add_argument('--hostname', required=True, help='a host name') | |
args = parser.parse_args() | |
create_server_cert(args, *create_self_signed_cert(args)) | |
print '[I] done' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment