def _add_leaf_usages(csr: Any, domains: List[str], issuer: Credentials) -> Any: return csr.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ).add_extension( x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( issuer.certificate.extensions.get_extension_for_class( x509.SubjectKeyIdentifier).value), critical=False ).add_extension( x509.SubjectAlternativeName([x509.DNSName(domain) for domain in domains]), critical=True, ).add_extension( x509.ExtendedKeyUsage([ ExtendedKeyUsageOID.SERVER_AUTH, ]), critical=True )
def gen_csr(key): csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"), x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"), x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"), ])).add_extension( # Define SANs x509.SubjectAlternativeName([ x509.DNSName(u"mysite.com"), x509.DNSName(u"www.mysite.com"), x509.DNSName(u"subdomain.mysite.com"), ]), critical=False, # Sign the CSR with key ).sign(key, hashes.SHA256(), default_backend()) return str(csr.public_bytes(serialization.Encoding.PEM), 'utf-8')
def test_csr_disallowed_san(client, logged_in_user): """SAN name is disallowed by LEMUR_WHITELISTED_DOMAINS.""" from lemur.common import validators request, pkey = create_csr( common_name="CN with spaces isn't a domain and is thus allowed", owner='*****@*****.**', key_type='RSA2048', extensions={ 'sub_alt_names': { 'names': x509.SubjectAlternativeName([x509.DNSName('evilhacker.org')]) } }) with pytest.raises(ValidationError) as err: validators.csr(request) assert str(err.value).startswith( 'Domain evilhacker.org does not match whitelisted domain patterns')
def setUp(self): super(ApiSslServerTestBase, self).setUp() key = rdf_crypto.RSAPrivateKey.GenerateKey() key_path = os.path.join(self.temp_dir, "key.pem") with open(key_path, "wb") as f: f.write(key.AsPEM()) subject = issuer = x509.Name([ x509.NameAttribute(oid.NameOID.COMMON_NAME, u"localhost"), ]) cert = x509.CertificateBuilder().subject_name(subject).issuer_name( issuer).public_key(key.GetPublicKey().GetRawPublicKey()).serial_number( x509.random_serial_number()).not_valid_before( datetime.datetime.utcnow()).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=1)).add_extension( x509.SubjectAlternativeName( [x509.DNSName(u"localhost")]), critical=False, ).sign(key.GetRawPrivateKey(), hashes.SHA256(), backends.default_backend()) self.cert_path = os.path.join(self.temp_dir, "certificate.pem") with open(self.cert_path, "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) self.config_overrider = test_lib.ConfigOverrider({ "AdminUI.enable_ssl": True, "AdminUI.ssl_key_file": key_path, "AdminUI.ssl_cert_file": self.cert_path, }) self.config_overrider.Start() self.port = portpicker.PickUnusedPort() self.thread = wsgiapp_testlib.ServerThread(self.port) self.thread.StartAndWaitUntilServing() api_auth_manager.APIACLInit.InitApiAuthManager() self.token.username = "******" webauth.WEBAUTH_MANAGER.SetUserName(self.token.username) self.endpoint = "https://localhost:%s" % self.port
def generate_ssl_cert(subject_name, alternate_name): # Generate our key key = rsa.generate_private_key( public_exponent=65537, key_size=4096, ) # 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.COMMON_NAME, subject_name), ]) cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.datetime.utcnow() ).not_valid_after( # Our certificate will be valid for 10 days datetime.datetime.utcnow() + datetime.timedelta(days=10) ).add_extension( x509.SubjectAlternativeName([x509.DNSName(alternate_name)]), critical=True, ).add_extension( x509.ExtendedKeyUsage( [x509.oid.ExtendedKeyUsageOID.SERVER_AUTH if subject_name.endswith('_server') else x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH]), critical=True, # Sign our certificate with our private key ).sign(key, hashes.SHA256()) key_bytes = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ) crt_bytes = cert.public_bytes(serialization.Encoding.PEM) return (key_bytes, crt_bytes)
def generate_selfsigned_cert(hostname, ip_addresses=None, key=None): from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa # Generate key if key is None: key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend(), ) name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)]) alt_names = [x509.DNSName(hostname)] if ip_addresses: for addr in ip_addresses: alt_names.append(x509.DNSName(addr)) alt_names.append(x509.IPAddress(ipaddress.ip_address(addr))) san = x509.SubjectAlternativeName(alt_names) basic_contraints = x509.BasicConstraints(ca=True, path_length=0) now = datetime.utcnow() cert = (x509.CertificateBuilder().subject_name(name).issuer_name( name).public_key( key.public_key()).serial_number(1000).not_valid_before(now). not_valid_after(now + timedelta(days=10 * 365)).add_extension( basic_contraints, False).add_extension(san, False).sign(key, hashes.SHA256(), default_backend())) cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM) key_pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) return cert_pem, key_pem, key
def generate_root_cert(self) -> Tuple[str, str]: self.root_key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend()) root_public_key = self.root_key.public_key() root_builder = x509.CertificateBuilder() root_builder = root_builder.subject_name( x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'cephadm-root'), ])) root_builder = root_builder.issuer_name( x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'cephadm-root'), ])) root_builder = root_builder.not_valid_before(datetime.now()) root_builder = root_builder.not_valid_after(datetime.now() + timedelta( days=(365 * 10 + 3))) root_builder = root_builder.serial_number(x509.random_serial_number()) root_builder = root_builder.public_key(root_public_key) root_builder = root_builder.add_extension(x509.SubjectAlternativeName([ x509.IPAddress(ipaddress.IPv4Address(str(self.mgr.get_mgr_ip()))) ]), critical=False) root_builder = root_builder.add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True, ) self.root_cert = root_builder.sign(private_key=self.root_key, algorithm=hashes.SHA256(), backend=default_backend()) cert_str = crypto.dump_certificate(crypto.FILETYPE_PEM, self.root_cert).decode('utf-8') key_str = self.root_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()).decode('utf-8') return (cert_str, key_str)
def generate_selfsigned_cert(hostname, public_ip, private_ip): from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa # Generate our key key = rsa.generate_private_key(public_exponent=65537, key_size=1024, backend=default_backend()) name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)]) alt_names = x509.SubjectAlternativeName([ # best practice seem to be to include the hostname in the SAN, which *SHOULD* mean COMMON_NAME is ignored. x509.DNSName(hostname), # allow addressing by IP, for when you don't have real DNS (common in most testing scenarios) # openssl wants DNSnames for ips... # x509.DNSName(public_ip), # x509.DNSName(private_ip), # ... whereas golang's crypto/tls is stricter, and needs IPAddresses x509.IPAddress(public_ip), x509.IPAddress(private_ip), ]) # path_len=0 means this cert can only sign itself, not other certs. basic_contraints = x509.BasicConstraints(ca=True, path_length=0) now = datetime.utcnow() cert = (x509.CertificateBuilder().subject_name(name).issuer_name( name).public_key( key.public_key()).serial_number(1000).not_valid_before(now). not_valid_after(now + timedelta(days=10 * 365)).add_extension( basic_contraints, False).add_extension(alt_names, False).sign(key, hashes.SHA256(), default_backend())) cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM) key_pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) return cert_pem, key_pem
def profile_server(builder, ca_nick, _ca, warp=datetime.timedelta(days=0), dns_name=None, badusage=False): now = datetime.datetime.utcnow() + warp builder = builder.not_valid_before(now) builder = builder.not_valid_after(now + YEAR) crl_uri = 'file://{}.crl'.format(os.path.join(DIR, ca_nick)) builder = builder.add_extension( x509.CRLDistributionPoints([ x509.DistributionPoint( full_name=[x509.UniformResourceIdentifier(crl_uri)], relative_name=None, crl_issuer=None, reasons=None, ), ]), critical=False, ) if dns_name is not None: builder = builder.add_extension( x509.SubjectAlternativeName([x509.DNSName(dns_name)]), critical=False, ) if badusage: builder = builder.add_extension(x509.KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=True, key_agreement=True, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False), critical=False) return builder
def cert_gen(self): subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, u"PT"), x509.NameAttribute(NameOID.JURISDICTION_LOCALITY_NAME, u"Aveiro"), x509.NameAttribute(NameOID.LOCALITY_NAME, u"Aveiro"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"SIO"), x509.NameAttribute(NameOID.COMMON_NAME, u"serverSIO"), ]) if self.private_key is not None: cert = x509.CertificateBuilder().subject_name(subject).issuer_name( issuer).public_key( self.private_key.public_key()).serial_number( x509.random_serial_number()).not_valid_before( datetime.datetime.utcnow()).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=10)).add_extension( x509.SubjectAlternativeName( [x509.DNSName(u"serversio.io")]), critical=False, ).add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True, ).add_extension(x509.KeyUsage( digital_signature=True, key_encipherment=True, content_commitment=False, data_encipherment=False, key_agreement=False, encipher_only=False, decipher_only=False, key_cert_sign=True, crl_sign=False), critical=True).sign( self.private_key, hashes.SHA256(), default_backend()) if not os.path.exists("certs"): os.mkdir("certs") with open( "certs\\server.pem" if sys.platform == 'win32' else "certs/server.pem", "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM))
def generate_cert(cert_path: str = SSL_CERT_FILE, key_path: str = SSL_KEY_FILE, key_size: int = KEY_SIZE, key_days: int = KEY_DAYS): if os.path.exists(key_path): print('Skipping key generation as already exists.') return hostname = 'localhost' key = rsa.generate_private_key( public_exponent=65537, key_size=key_size, backend=default_backend(), ) name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)]) # best practice seem to be to include the hostname in the SAN, which *SHOULD* mean COMMON_NAME is ignored. alt_names = [x509.DNSName(hostname)] san = x509.SubjectAlternativeName(alt_names) # prevent this cert form being used to sign other certs basic_contraints = x509.BasicConstraints(ca=False, path_length=None) now = datetime.utcnow() cert = (x509.CertificateBuilder().subject_name(name).issuer_name( name).public_key( key.public_key()).serial_number(1000).not_valid_before(now). not_valid_after(now + timedelta(days=key_days)).add_extension( basic_contraints, False).add_extension(san, False).sign(key, hashes.SHA256(), default_backend())) cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM) key_pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) with open(key_path, 'wb') as f: f.write(key_pem) with open(cert_path, 'wb') as f: f.write(cert_pem)
def _generate_certificate( ip_address: str, ) -> typing.Tuple[str, bytes, bytes]: """Generate a private key and a certificate signed with it The key is encrypted before being stored. Returns the certificate as a string, the key as bytes (encrypted), and the password used for encrypting the key """ # Generate private key key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend()) # Generate the certificate and sign it with the private key cert_name = get_machine_name() subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, "NO"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Bergen"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Sandsli"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Equinor"), x509.NameAttribute(NameOID.COMMON_NAME, "{}".format(cert_name)), ]) cert = ( x509.CertificateBuilder().subject_name(subject).issuer_name( issuer).public_key(key.public_key()).serial_number( x509.random_serial_number()).not_valid_before( datetime.utcnow()).not_valid_after( datetime.utcnow() + timedelta(days=365)) # 1 year .add_extension( x509.SubjectAlternativeName([ x509.DNSName("{}".format(cert_name)), x509.DNSName(ip_address), x509.IPAddress(ipaddress.ip_address(ip_address)), ]), critical=False, ).sign(key, hashes.SHA256(), default_backend())) cert_str = cert.public_bytes(serialization.Encoding.PEM).decode("utf-8") pw = bytes(os.urandom(28)) key_bytes = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.BestAvailableEncryption(pw), ) return cert_str, key_bytes, pw
def generate_ssl_certs(country, country_code, location, org, email, org_unit="NBIS sysdevs", common_name="NBIS"): key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) priv_key = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, country_code), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, country), x509.NameAttribute(NameOID.LOCALITY_NAME, location), x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, org_unit), x509.NameAttribute(NameOID.COMMON_NAME, common_name), x509.NameAttribute(NameOID.EMAIL_ADDRESS, email), ]) cert = x509.CertificateBuilder().subject_name(subject).issuer_name( issuer).public_key(key.public_key()).serial_number( x509.random_serial_number()).not_valid_before( datetime.datetime.utcnow()).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=1000)).add_extension( x509.SubjectAlternativeName( [x509.DNSName(u"localhost")]), critical=False, ).sign(key, hashes.SHA256(), default_backend()) with open('certs' + '/' + 'ssl.cert', "w") as ssl_cert: ssl_cert.write( cert.public_bytes(serialization.Encoding.PEM).decode('utf-8')) with open('certs' + '/' + 'ssl.key', "w") as ssl_key: ssl_key.write(priv_key.decode('utf-8'))
def issue_self_signed_certificate(domains, private_key, logger): # Generates a self-signed certificate. from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.x509.oid import NameOID from cryptography.x509 import DNSName import datetime import uuid logger("Issuing self-signed certificate.") import sys if sys.version_info < (3,): # In Py2, pyca requires the CN to be a unicode instance. domains = [domain.decode("ascii") for domain in domains] # https://cryptography.io/en/latest/x509/reference/ one_day = datetime.timedelta(days=1) duration = datetime.timedelta(days=31) builder = x509.CertificateBuilder() builder = builder.subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, domains[0]), ])) builder = builder.issuer_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, domains[0]), ])) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + duration) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.public_key(private_key.public_key()) builder = builder.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ) if len(domains) > 1: builder = builder.add_extension(x509.SubjectAlternativeName([ x509.DNSName(domain) for domain in domains]), critical=False) certificate = builder.sign( private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend() ) return (cert_to_pem(certificate), []) # no chain
def test_csr_disallowed_san(client, logged_in_user): """SAN name is disallowed by LEMUR_ALLOWED_DOMAINS.""" from lemur.common import validators request, pkey = create_csr( common_name="CN with spaces isn't a domain and is thus allowed", owner="*****@*****.**", key_type="RSA2048", extensions={ "sub_alt_names": { "names": x509.SubjectAlternativeName([x509.DNSName("evilhacker.org")]) } }, ) with pytest.raises(ValidationError) as err: validators.csr(request) assert str(err.value).startswith( "Domain evilhacker.org does not match allowed domain patterns" )
def create_csr(self, common_name: str, key_size: int = _RSA_KEYSIZE, ca: bool = False) -> CSR: ''' Creates an RSA private key and a CSR. After calling this function, you can call Secret.get_csr_signature(issuing_ca) afterwards to generate the signed certificate :param common_name: common_name for the certificate :param key_size: length of the key in bits :param ca: create a secret for an CA :returns: the Certificate Signature Request :raises: ValueError if the Secret instance already has a private key or set ''' if self.private_key or self.cert: raise ValueError('Secret already has a cert or private key') # TODO: SECURITY: add constraints self.common_name = common_name _LOGGER.debug(f'Generating a private key with key size {key_size} ' f'and commonname {common_name}') self.private_key = rsa.generate_private_key( public_exponent=65537, key_size=_RSA_KEYSIZE, ) _LOGGER.debug(f'Generating a CSR for {self.common_name}') csr = x509.CertificateSigningRequestBuilder().subject_name( self._get_cert_name()).add_extension( x509.BasicConstraints(ca=ca, path_length=self.max_path_length), critical=True, ).add_extension(x509.SubjectAlternativeName( [x509.DNSName(self.common_name)]), critical=False).sign(self.private_key, hashes.SHA256()) return csr
def gen_alt_name(list): alt_name_objs = [] for name in list: try: addr = IPv4Address(name) alt_name_objs.append(x509.IPAddress(addr)) continue except AddressValueError: pass try: addr = IPv6Address(name) alt_name_objs.append(x509.IPAddress(addr)) continue except AddressValueError: pass alt_name_objs.append(x509.DNSName(name)) return x509.SubjectAlternativeName(alt_name_objs)
def generate_csr_pyca(domains, key): # Generates a CSR and returns a pyca/cryptography CSR object. from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend import sys if sys.version_info < (3,): # In Py2, pyca requires the CN to be a unicode instance. domains = [domain.decode("ascii") for domain in domains] csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, domains[0]), ])).add_extension( x509.SubjectAlternativeName([x509.DNSName(domain) for domain in domains]), critical=False, ).sign(key, hashes.SHA256(), default_backend()) return csr
def generate_self_signed_certificate(): one_day = datetime.timedelta(1, 0, 0) private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.subject_name( x509.Name( [x509.NameAttribute(NameOID.COMMON_NAME, socket.gethostname())])) builder = builder.issuer_name( x509.Name( [x509.NameAttribute(NameOID.COMMON_NAME, socket.gethostname())])) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + (one_day * 365 * 5)) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(public_key) logger.debug( "Adding SANs for %(hostname)s, *.%(hostname)s, localhost, and *.localhost", {"hostname": socket.gethostname()}, ) builder = builder.add_extension( x509.SubjectAlternativeName(sans), critical=False, ) builder = builder.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True) certificate = builder.sign(private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend()) return ( certificate.public_bytes(serialization.Encoding.PEM), private_key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), ), )
def test_create_basic_csr(client): csr_config = dict( common_name='example.com', organization='Example, Inc.', organizational_unit='Operations', country='US', state='CA', location='A place', owner='*****@*****.**', key_type='RSA2048', extensions=dict(names=dict(sub_alt_names=x509.SubjectAlternativeName([ x509.DNSName('test.example.com'), x509.DNSName('test2.example.com') ])))) csr, pem = create_csr(**csr_config) csr = x509.load_pem_x509_csr(csr.encode('utf-8'), default_backend()) for name in csr.subject: assert name.value in csr_config.values()
def generate_self_signed_certificate(private_key, certificate_path): """Generate a self signed certificate using a generated private key. The certificate will be created in 'CONFIG_PATH/ssl/server.crt'. Parameters ---------- private_key : RSAPrivateKey Private key. certificate_path : str Path where the self signed certificate will be generated. """ # Generate private key # 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.COUNTRY_NAME, u"US"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"), x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Wazuh"), x509.NameAttribute(NameOID.COMMON_NAME, u"wazuh.com"), ]) cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( private_key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.datetime.utcnow() ).not_valid_after( # Our certificate will be valid for 10 days datetime.datetime.utcnow() + datetime.timedelta(days=365) ).add_extension( x509.SubjectAlternativeName([x509.DNSName(u"localhost")]), critical=False, # Sign our certificate with our private key ).sign(private_key, hashes.SHA256(), crypto_default_backend()) # Write our certificate out to disk. with open(certificate_path, 'wb') as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) os.chmod(certificate_path, 0o400)
def create_csr(self, common_name: str, alt_names: Iterable[str] = (), must_staple=False) -> x509.CertificateSigningRequest: subject = [ # letencrypt ignores all other fields. x509.NameAttribute(x509.NameOID.COMMON_NAME, common_name) ] req = x509.CertificateSigningRequestBuilder(x509.Name(subject)) if alt_names: req = req.add_extension(x509.SubjectAlternativeName( general_names=(x509.DNSName(name) for name in alt_names)), critical=True) if must_staple: req = req.add_extension(x509.TLSFeature( [x509.TLSFeatureType.status_request]), critical=False) return req.sign(self._key, hashes.SHA256(), default_backend())
def main(): # gen private key key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) # save key to file with open("TesTkey.pem", "wb") as f: f.write( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption( b"passphrase"), )) # generate CSR csr = x509.CertificateSigningRequestBuilder() csr = csr.subject_name( x509.Name([ # Provide various details about who we are. x509.NameAttribute(NameOID.COUNTRY_NAME, 'NL'), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Noord-Holland"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Amsterdam"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Jenda Ltd."), x509.NameAttribute(NameOID.COMMON_NAME, "jenda.wtf.com") ])) csr = csr.add_extension( x509.SubjectAlternativeName([ # describe what sites we want this cert for. x509.DNSName('jenda.wtf.org'), x509.DNSName("www.jenda.wtf.org") ]), critical=False) print(csr) # Sign the CSR with our private key. csr.sign(key, hashes.SHA256(), backend=default_backend())
def _generate_cert(server_name, not_valid_before, not_valid_after, key=RSA_KEY_512_RAW): """ Generate a self-signed certificate for test purposes. :param str server_name: The SAN the certificate should have. :param ~datetime.datetime not_valid_before: Valid from this moment. :param ~datetime.datetime not_valid_after: Expiry time. :param key: The private key. :rtype: `str` :return: The certificate in PEM format. """ common_name = ( u'san.too.long.invalid' if len(server_name) > 64 else server_name) name = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, common_name)]) cert = ( x509.CertificateBuilder() .subject_name(name) .issuer_name(name) .not_valid_before(not_valid_before) .not_valid_after(not_valid_after) .serial_number(int(uuid.uuid4())) .public_key(key.public_key()) .add_extension( x509.SubjectAlternativeName([x509.DNSName(server_name)]), critical=False) .sign( private_key=key, algorithm=hashes.SHA256(), backend=default_backend()) ) return [ Certificate( cert.public_bytes(serialization.Encoding.PEM)), RSAPrivateKey( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())), ]
def __enter__(self): from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa subject = issuer = x509.Name([x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, "localhost")]) with contextlib.ExitStack() as stack: key = rsa.generate_private_key(public_exponent=65537, key_size=1024, backend=default_backend()) key_file = stack.enter_context(tempfile.NamedTemporaryFile()) key_file.write( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) ) key_file.flush() cert = ( x509.CertificateBuilder() .subject_name(subject) .issuer_name(issuer) .public_key(key.public_key()) .serial_number(x509.random_serial_number()) .not_valid_before(datetime.datetime.utcnow()) .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=1)) .add_extension( x509.SubjectAlternativeName([x509.DNSName("localhost"), x509.DNSName("127.0.0.1")]), critical=False ) .sign(key, hashes.SHA256(), default_backend()) ) cert_file = stack.enter_context(tempfile.NamedTemporaryFile()) cert_file.write(cert.public_bytes(serialization.Encoding.PEM)) cert_file.flush() self._key_file, self._cert_file = key_file, cert_file stack.pop_all() return self
def generate_adhoc_ssl_pair( cn: t.Optional[str] = None, ) -> t.Tuple["Certificate", "RSAPrivateKeyWithSerialization"]: try: from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa except ImportError: raise TypeError("Using ad-hoc certificates requires the cryptography library.") backend = default_backend() pkey = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=backend ) # pretty damn sure that this is not actually accepted by anyone if cn is None: cn = "*" subject = x509.Name( [ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Dummy Certificate"), x509.NameAttribute(NameOID.COMMON_NAME, cn), ] ) backend = default_backend() cert = ( x509.CertificateBuilder() .subject_name(subject) .issuer_name(subject) .public_key(pkey.public_key()) .serial_number(x509.random_serial_number()) .not_valid_before(dt.now(timezone.utc)) .not_valid_after(dt.now(timezone.utc) + timedelta(days=365)) .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False) .add_extension(x509.SubjectAlternativeName([x509.DNSName(cn)]), critical=False) .sign(pkey, hashes.SHA256(), backend) ) return cert, pkey
def generate_self_signed_cert(hostname, server_key, ip_addresses=None): """ Generates self signed certificate for a hostname, and optional IP addresses. """ name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)]) alt_names = [x509.DNSName(hostname)] if ip_addresses: for addr in ip_addresses: alt_names.append(x509.DNSName(addr)) alt_names.append(x509.IPAddress(ipaddress.ip_address(addr))) ca_crt = x509.CertificateBuilder().subject_name(name).issuer_name( name).public_key(server_key.public_key()).serial_number(uuid.uuid4( ).int).not_valid_before(datetime.datetime.utcnow()).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=365 * 100)).add_extension( extension=x509.KeyUsage(digital_signature=True, key_encipherment=True, key_cert_sign=True, crl_sign=True, content_commitment=True, data_encipherment=False, key_agreement=False, encipher_only=False, decipher_only=False), critical=False).add_extension( extension=x509.BasicConstraints(ca=True, path_length=0), critical=False).add_extension( extension=x509.SubjectKeyIdentifier.from_public_key( server_key.public_key()), critical=False).add_extension( extension=x509.AuthorityKeyIdentifier. from_issuer_public_key(server_key.public_key()), critical=False).add_extension( extension=x509.SubjectAlternativeName( alt_names), critical=False).sign(private_key=server_key, algorithm=hashes.SHA256(), backend=default_backend()) ca_cert_pem = ca_crt.public_bytes(encoding=serialization.Encoding.PEM) return ca_cert_pem
def make_key_cert_pair(self, hostname, ip): private_key = rsa.generate_private_key( backend=crypto_default_backend(), public_exponent=65537, key_size=2048 ) public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, hostname), ])) builder = builder.issuer_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, hostname), ])) builder = builder.not_valid_before(datetime.datetime.today() - day) builder = builder.not_valid_after(datetime.datetime.today() + EXPIRE_TIME) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(public_key) builder = builder.add_extension( x509.SubjectAlternativeName( [x509.DNSName(ip)] ), critical=True ) certificate = builder.sign( private_key=private_key, algorithm=hashes.SHA256(), backend=crypto_default_backend() ) ser_private_key = private_key.private_bytes( crypto_serialization.Encoding.PEM, crypto_serialization.PrivateFormat.PKCS8, crypto_serialization.NoEncryption()) ser_public_key = certificate.public_bytes( crypto_serialization.Encoding.PEM ) return ser_private_key, ser_public_key
def test_csr_empty_san(client): """Test that an empty "names" list does not produce a CSR with empty SubjectAltNames extension. The Lemur UI always submits this extension even when no alt names are defined. """ csr_text, pkey = create_csr(common_name='daniel-san.example.com', owner='*****@*****.**', key_type='RSA2048', extensions={ 'sub_alt_names': { 'names': x509.SubjectAlternativeName([]) } }) csr = x509.load_pem_x509_csr(csr_text.encode('utf-8'), default_backend()) with pytest.raises(x509.ExtensionNotFound): csr.extensions.get_extension_for_class(x509.SubjectAlternativeName)
def certificate_template(subject, issuer, public_key, certauthority=False): if certauthority: not_valid_after = datetime.datetime.utcnow() + datetime.timedelta( days=365 * 10) else: # shorter valid length for on-the-fly certificates not_valid_after = datetime.datetime.utcnow() + datetime.timedelta( days=7) return (x509.CertificateBuilder().subject_name(subject).issuer_name( issuer).public_key(public_key).serial_number( x509.random_serial_number()).not_valid_before( datetime.datetime.utcnow()).not_valid_after( not_valid_after).add_extension( x509.SubjectAlternativeName( [x509.DNSName("localhost")]), critical=True).add_extension(x509.BasicConstraints( ca=certauthority, path_length=None), critical=True))