committed by
JackDandy
2 changed files with 127 additions and 100 deletions
@ -1,82 +1,127 @@ |
|||||
# -*- coding: latin-1 -*- |
#!/usr/bin/env python |
||||
# |
|
||||
# Copyright (C) Martin Sjögren and AB Strakt 2001, All rights reserved |
|
||||
# Copyright (C) Jean-Paul Calderone 2008, All rights reserved |
|
||||
# This file is licenced under the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 or later (aka LGPL v2.1) |
|
||||
# Please see LGPL2.1.txt for more information |
|
||||
""" |
""" |
||||
Certificate generation module. |
Adapted from the docs of cryptography |
||||
|
|
||||
|
Creates a key and self-signed certificate for local use |
||||
""" |
""" |
||||
|
|
||||
from OpenSSL import crypto |
import datetime |
||||
import time |
import os |
||||
|
import socket |
||||
TYPE_RSA = crypto.TYPE_RSA |
|
||||
TYPE_DSA = crypto.TYPE_DSA |
# noinspection PyPackageRequirements |
||||
|
from cryptography.hazmat.backends import default_backend |
||||
serial = int(time.time()) |
# noinspection PyPackageRequirements |
||||
|
from cryptography.hazmat.primitives import hashes, serialization |
||||
|
# noinspection PyPackageRequirements |
||||
def createKeyPair(type, bits): |
from cryptography.hazmat.primitives.asymmetric import rsa |
||||
""" |
# noinspection PyPackageRequirements |
||||
Create a public/private key pair. |
from cryptography import x509 |
||||
|
# noinspection PyPackageRequirements |
||||
Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA |
from cryptography.x509.oid import NameOID |
||||
bits - Number of bits to use in the key |
|
||||
Returns: The public/private key pair in a PKey object |
from six import PY2, text_type |
||||
""" |
|
||||
pkey = crypto.PKey() |
|
||||
pkey.generate_key(type, bits) |
def localipv4(): |
||||
return pkey |
try: |
||||
|
s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||
def createCertRequest(pkey, digest="md5", **name): |
s_ipv4.connect(('1.2.3.4', 80)) # Option: use 100.64.1.1 (IANA-Reserved IPv4 Prefix for Shared Address Space) |
||||
""" |
ipv4 = s_ipv4.getsockname()[0] |
||||
Create a certificate request. |
s_ipv4.close() |
||||
|
except (BaseException, Exception): |
||||
Arguments: pkey - The key to associate with the request |
ipv4 = None |
||||
digest - Digestion method to use for signing, default is md5 |
return ipv4 |
||||
**name - The name of the subject of the request, possible |
|
||||
arguments are: |
|
||||
C - Country name |
# Ported from cryptography/utils.py |
||||
ST - State or province name |
def int_from_bytes(data, byteorder, signed=False): |
||||
L - Locality name |
assert 'big' == byteorder |
||||
O - Organization name |
assert not signed |
||||
OU - Organizational unit name |
|
||||
CN - Common name |
if not PY2: |
||||
emailAddress - E-mail address |
import binascii |
||||
Returns: The certificate request in an X509Req object |
return int(binascii.hexlify(data), 16) |
||||
""" |
|
||||
req = crypto.X509Req() |
# call bytes() on data to allow the use of bytearrays |
||||
subj = req.get_subject() |
# noinspection PyUnresolvedReferences |
||||
|
return int(bytes(data).encode('hex'), 16) |
||||
for (key,value) in name.items(): |
|
||||
setattr(subj, key, value) |
|
||||
|
# Ported from cryptography/x509/base.py |
||||
req.set_pubkey(pkey) |
def random_serial_number(): |
||||
req.sign(pkey, digest) |
return int_from_bytes(os.urandom(20), 'big') >> 1 |
||||
return req |
|
||||
|
|
||||
def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), digest="md5"): |
# Ported from cryptography docs/x509/tutorial.rst (set with no encryption) |
||||
""" |
def generate_key(key_size=4096, output_file='server.key'): |
||||
Generate a certificate given a certificate request. |
# Generate our key |
||||
|
private_key = rsa.generate_private_key( |
||||
Arguments: req - Certificate reqeust to use |
public_exponent=65537, |
||||
issuerCert - The certificate of the issuer |
key_size=key_size, |
||||
issuerKey - The private key of the issuer |
backend=default_backend() |
||||
serial - Serial number for the certificate |
) |
||||
notBefore - Timestamp (relative to now) when the certificate |
|
||||
starts being valid |
# Write our key to disk for safe keeping |
||||
notAfter - Timestamp (relative to now) when the certificate |
with open(output_file, 'wb') as f: |
||||
stops being valid |
f.write(private_key.private_bytes( |
||||
digest - Digest method to use for signing, default is md5 |
encoding=serialization.Encoding.PEM, |
||||
Returns: The signed certificate in an X509 object |
format=serialization.PrivateFormat.TraditionalOpenSSL, |
||||
""" |
encryption_algorithm=serialization.NoEncryption() |
||||
cert = crypto.X509() |
)) |
||||
cert.set_serial_number(serial) |
|
||||
cert.gmtime_adj_notBefore(notBefore) |
return private_key |
||||
cert.gmtime_adj_notAfter(notAfter) |
|
||||
cert.set_issuer(issuerCert.get_subject()) |
|
||||
cert.set_subject(req.get_subject()) |
# Ported from cryptography docs/x509/tutorial.rst |
||||
cert.set_pubkey(req.get_pubkey()) |
def generate_local_cert(private_key, days_valid=3650, output_file='server.crt', loc_name=None, org_name=None): |
||||
cert.sign(issuerKey, digest) |
|
||||
|
def_name = u'SickGear' |
||||
|
|
||||
|
# Various details about who we are. For a self-signed certificate the |
||||
|
# subject and issuer are always the same. |
||||
|
subject = issuer = x509.Name([ |
||||
|
x509.NameAttribute(NameOID.LOCALITY_NAME, loc_name or def_name), |
||||
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name or def_name) |
||||
|
]) |
||||
|
|
||||
|
# build Subject Alternate Names (aka SAN) list |
||||
|
# First the host names, add with x509.DNSName(): |
||||
|
san_list = [x509.DNSName(u'localhost')] |
||||
|
try: |
||||
|
thishostname = text_type(socket.gethostname()) |
||||
|
san_list.append(x509.DNSName(thishostname)) |
||||
|
except (BaseException, Exception): |
||||
|
pass |
||||
|
|
||||
|
# Then the host IP addresses, add with x509.IPAddress() |
||||
|
# Inside a try-except, just to be sure |
||||
|
try: |
||||
|
# noinspection PyCompatibility |
||||
|
from ipaddress import IPv4Address, IPv6Address |
||||
|
san_list.append(x509.IPAddress(IPv4Address(u'127.0.0.1'))) |
||||
|
san_list.append(x509.IPAddress(IPv6Address(u'::1'))) |
||||
|
|
||||
|
# append local v4 ip |
||||
|
mylocalipv4 = localipv4() |
||||
|
if mylocalipv4: |
||||
|
san_list.append(x509.IPAddress(IPv4Address(u'' + mylocalipv4))) |
||||
|
except (ImportError, Exception): |
||||
|
pass |
||||
|
|
||||
|
cert = x509.CertificateBuilder() \ |
||||
|
.subject_name(subject) \ |
||||
|
.issuer_name(issuer) \ |
||||
|
.public_key(private_key.public_key()) \ |
||||
|
.not_valid_before(datetime.datetime.utcnow()) \ |
||||
|
.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=days_valid)) \ |
||||
|
.serial_number(random_serial_number()) \ |
||||
|
.add_extension(x509.SubjectAlternativeName(san_list), critical=True) \ |
||||
|
.sign(private_key, hashes.SHA256(), default_backend()) |
||||
|
|
||||
|
# Write the certificate out to disk. |
||||
|
with open(output_file, 'wb') as f: |
||||
|
f.write(cert.public_bytes(serialization.Encoding.PEM)) |
||||
|
|
||||
return cert |
return cert |
||||
|
Loading…
Reference in new issue