def create_self_sign_certs(pass_phase: str, client_config_map: "ClientConfigAdapter"): """ Create self-sign CA Cert """ cert_directory: str = get_gateway_paths( client_config_map).local_certs_path.as_posix() filepath_list = { 'ca_key': join(cert_directory, ca_key_filename), 'ca_cert': join(cert_directory, ca_cert_filename), 'server_key': join(cert_directory, server_key_filename), 'server_cert': join(cert_directory, server_cert_filename), 'server_csr': join(cert_directory, server_csr_filename), 'client_key': join(cert_directory, client_key_filename), 'client_cert': join(cert_directory, client_cert_filename), 'client_csr': join(cert_directory, client_csr_filename) } # Create CA Private & Public Keys for signing ca_private_key = generate_private_key(pass_phase, filepath_list['ca_key']) generate_public_key(ca_private_key, filepath_list['ca_cert']) # Create Server Private & Public Keys for signing server_private_key = generate_private_key(pass_phase, filepath_list['server_key']) # Create CSR generate_csr(server_private_key, filepath_list['server_csr']) # Load CSR with open(filepath_list['server_csr'], 'rb') as server_csr_file: server_csr = x509.load_pem_x509_csr(server_csr_file.read(), default_backend()) # Create Client CSR # local certificate must be unencrypted. Currently, Requests does not support using encrypted keys. client_private_key = generate_private_key(None, filepath_list['client_key']) # Create CSR generate_csr(client_private_key, filepath_list['client_csr']) # Load CSR with open(filepath_list['client_csr'], 'rb') as client_csr_file: client_csr = x509.load_pem_x509_csr(client_csr_file.read(), default_backend()) # Load CA public key with open(filepath_list['ca_cert'], 'rb') as ca_cert_file: ca_cert = x509.load_pem_x509_certificate(ca_cert_file.read(), default_backend()) # Load CA private key with open(filepath_list['ca_key'], 'rb') as ca_key_file: ca_key = serialization.load_pem_private_key( ca_key_file.read(), pass_phase.encode('utf-8'), default_backend(), ) # Sign Server Cert with CSR sign_csr(server_csr, ca_cert, ca_key, filepath_list['server_cert']) # Sign Client Cert with CSR sign_csr(client_csr, ca_cert, ca_key, filepath_list['client_cert'])
def create_self_sign_certs(pass_phase: str): """ Create self-sign CA Cert """ CERT_FILE_PATH = cert_path() filepath_list = { 'ca_key': join(CERT_FILE_PATH, ca_key_filename), 'ca_cert': join(CERT_FILE_PATH, ca_cert_filename), 'server_key': join(CERT_FILE_PATH, server_key_filename), 'server_cert': join(CERT_FILE_PATH, server_cert_filename), 'server_csr': join(CERT_FILE_PATH, server_csr_filename), 'client_key': join(CERT_FILE_PATH, client_key_filename), 'client_cert': join(CERT_FILE_PATH, client_cert_filename), 'client_csr': join(CERT_FILE_PATH, client_csr_filename) } # Create CA Private & Public Keys for signing ca_private_key = generate_private_key(pass_phase, filepath_list['ca_key']) generate_public_key(ca_private_key, filepath_list['ca_cert']) # Create Server Private & Public Keys for signing server_private_key = generate_private_key(pass_phase, filepath_list['server_key']) # Create CSR generate_csr(server_private_key, filepath_list['server_csr']) # Load CSR server_csr_file = open(filepath_list['server_csr'], 'rb') server_csr = x509.load_pem_x509_csr(server_csr_file.read(), default_backend()) # Create Client CSR # local certificate must be unencrypted. Currently, Requests does not support using encrypted keys. client_private_key = generate_private_key(None, filepath_list['client_key']) # Create CSR generate_csr(client_private_key, filepath_list['client_csr']) # Load CSR client_csr_file = open(filepath_list['client_csr'], 'rb') client_csr = x509.load_pem_x509_csr(client_csr_file.read(), default_backend()) # Load CA public key ca_cert_file = open(filepath_list['ca_cert'], 'rb') ca_cert = x509.load_pem_x509_certificate(ca_cert_file.read(), default_backend()) # Load CA private key ca_key_file = open(filepath_list['ca_key'], 'rb') ca_key = serialization.load_pem_private_key( ca_key_file.read(), pass_phase.encode('utf-8'), default_backend(), ) # Sign Server Cert with CSR sign_csr(server_csr, ca_cert, ca_key, filepath_list['server_cert']) # Sign Client Cert with CSR sign_csr(client_csr, ca_cert, ca_key, filepath_list['client_cert'])
def csr(data): """ Determines if the CSR is valid. :param data: :return: """ try: x509.load_pem_x509_csr(bytes(data), default_backend()) except Exception: raise ValidationError('CSR presented is not valid.')
def test_public_bytes_pem(self, backend): # Load an existing CSR. request = _load_cert( os.path.join("x509", "requests", "rsa_sha1.pem"), x509.load_pem_x509_csr, backend ) # Encode it to PEM and load it back. request = x509.load_pem_x509_csr(request.public_bytes( encoding=serialization.Encoding.PEM, ), backend) # We should recover what we had to start with. assert isinstance(request.signature_hash_algorithm, hashes.SHA1) public_key = request.public_key() assert isinstance(public_key, rsa.RSAPublicKey) subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'), x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, u'Texas'), x509.NameAttribute(x509.OID_LOCALITY_NAME, u'Austin'), x509.NameAttribute(x509.OID_ORGANIZATION_NAME, u'PyCA'), x509.NameAttribute(x509.OID_COMMON_NAME, u'cryptography.io'), ]
def load_client_csr(path): pem_csr = open(path, 'rb').read() try: csr = x509.load_pem_x509_csr(pem_csr, default_backend()) except Exception: raise Exception("CSR presented is not valid.") return csr
def get_domains_from_x509(file_path, file_type): """Retrieve the list of domains covered by specified x509 file (CSR or CRT) :param file_path: path to x509 file :type file_path: pathlib.Path :param file_type: type of x509 file. Supported types: [DataType.CertificateSigningRequest, DataType.Certificate] :type file_type: DataType :return: list of domain :rtype: set """ domains = set() # load csr first if file_type == DataType.CertificateSigningRequest: x509_object = x509.load_pem_x509_csr(data=file_path.read_bytes(), backend=default_backend()) elif file_type == DataType.Certificate: x509_object = x509.load_pem_x509_certificate(data=file_path.read_bytes(), backend=default_backend()) else: raise ValueError("x509 file type specified not supported: ''" % file_type) # common_name (optional, we can have only sans) common_name = x509_object.subject.get_attributes_for_oid(NameOID.COMMON_NAME) if len(common_name) > 0: domains.add(common_name[0].value) # sans try: for dns_name in x509_object.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value: domains.add(dns_name.value) except ExtensionNotFound: # no san in that CSR pass return domains
def load_or_create_signer_csr(signer_id, key_filename, csr_filename, org_name='Microchip Technology Inc', common_name='Crypto Authentication Signer '): # Validate signer ID if re.search('^[0-9A-F]{4}$', signer_id) is None: raise ValueError( 'signer_id={} must be 4 uppercase hex digits'.format(signer_id)) key_filename = Path(key_filename) csr_filename = Path(csr_filename) rebuild_cert = True # Load or create key pair private_key = load_or_create_key_pair(filename=key_filename) csr = None if csr_filename.is_file(): rebuild_cert = False # Found cached CSR file, read it in with open(str(csr_filename), 'rb') as f: csr = x509.load_pem_x509_csr(f.read(), get_backend()) if csr: if get_org_name(csr.subject) != org_name: rebuild_cert = True csr_pub_bytes = csr.public_key().public_bytes( format=PublicFormat.SubjectPublicKeyInfo, encoding=Encoding.DER) key_pub_bytes = private_key.public_key().public_bytes( format=PublicFormat.SubjectPublicKeyInfo, encoding=Encoding.DER) if csr_pub_bytes != key_pub_bytes: rebuild_cert = True if rebuild_cert: # Build new certificate print("Building new signer csr certificate") builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name( x509.Name([ x509.NameAttribute(x509.oid.NameOID.ORGANIZATION_NAME, org_name), x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, common_name + signer_id) ])) # Add extensions builder = add_signer_extensions(builder=builder, public_key=private_key.public_key()) csr_new = builder.sign(private_key=private_key, algorithm=hashes.SHA256(), backend=get_backend()) csr = update_csr(csr, csr_new, csr_filename) else: print("Using cached signer csr certificate") return {'private_key': private_key, 'csr': csr}
def sign(csr, issuer_name, ca_key, ca_key_password=None, skip_validation=False): """Sign a given csr :param csr: certificate signing request object or pem encoded csr :param issuer_name: issuer name :param ca_key: private key of CA :param ca_key_password: private key password for given ca key :param skip_validation: skip csr validation if true :returns: generated certificate """ ca_key = _load_pem_private_key(ca_key, ca_key_password) if not isinstance(issuer_name, six.text_type): issuer_name = six.text_type(issuer_name.decode('utf-8')) if isinstance(csr, six.text_type): csr = six.b(str(csr)) if not isinstance(csr, x509.CertificateSigningRequest): try: csr = x509.load_pem_x509_csr(csr, backend=default_backend()) except ValueError: LOG.exception("Received invalid csr {0}.".format(csr)) raise exception.InvalidCsr(csr=csr) term_of_validity = CONF.x509.term_of_validity one_day = datetime.timedelta(1, 0, 0) expire_after = datetime.timedelta(term_of_validity, 0, 0) builder = x509.CertificateBuilder() builder = builder.subject_name(csr.subject) # issuer_name is set as common name builder = builder.issuer_name( x509.Name([ x509.NameAttribute(x509.OID_COMMON_NAME, issuer_name), ])) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + expire_after) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.public_key(csr.public_key()) if skip_validation: extensions = csr.extensions else: extensions = validator.filter_extensions(csr.extensions) for extention in extensions: builder = builder.add_extension(extention.value, critical=extention.critical) certificate = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend()).public_bytes( serialization.Encoding.PEM) return certificate
def readCSR(pem_req_data): csr = None try: csr = x509.load_pem_x509_csr(pem_req_data, default_backend()) except Exception, e: print e return {'error': False, 'msg': u'CSR内容错误!'}
def test_generate_dv_csr_with_key_creation(tmp_path, common_name, sans): name = 'auto_example.com' key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=None, output_path=str(tmp_path), ) # check key + csr files have been created assert key_content.startswith(b'-----BEGIN RSA PRIVATE KEY-----\n') assert csr_path.is_file() # check csr file has right name assert csr_path.name == '%s.csr' % name # load csr first csr = x509.load_pem_x509_csr(data=csr_path.read_bytes(), backend=default_backend()) # check content of CSR if common_name is not None: assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name else: # common name is optional assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 0 assert sans == [dns_name.value for dns_name in csr.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value]
def load_from_pem(cls, module, cert_pem=None, csr_pem=None, auto_renew=False): """Return a CertificateProxy object initialized from PEM data. The argument `cert_pem` it's a certificate in PEM format. The argument `csr_pem` is a CSR in PEM format. If a CSR is provided it has precedence over the certificate itself. The reason behind that is that a certificate might not have all attributes from the CSR since the CA can choose which attributes to honor. Using the certificate as the primary source of information could lead to idempotency issues. If neither CSR or Certificate are available return None instead. """ # pylint: disable=protected-access if csr_pem: x509_obj = x509.load_pem_x509_csr(csr_pem, default_backend()) elif cert_pem: x509_obj = x509.load_pem_x509_certificate(cert_pem, default_backend()) else: return None cert_like = cls(module) info = cert_like._get_info_from_x509(x509_obj) info["auto_renew"] = auto_renew cert_like.cert_data = info return cert_like
def sign_csr(self, ipa_csr): """Sign certificate CSR. :param ipa_csr: CSR in PEM format. :type ipa_csr: bytes. :returns: bytes -- Signed CA in PEM format. """ csr_tbs = x509.load_pem_x509_csr(ipa_csr, default_backend()) csr_public_key = csr_tbs.public_key() csr_subject = csr_tbs.subject builder = x509.CertificateBuilder() builder = builder.public_key(csr_public_key) builder = builder.subject_name(csr_subject) builder = builder.serial_number(x509.random_serial_number()) builder = builder.issuer_name(self.issuer) builder = builder.not_valid_before(datetime.datetime.utcnow()) builder = builder.not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=365)) builder = builder.add_extension( x509.KeyUsage( digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False, ), critical=True, ) builder = builder.add_extension( x509.SubjectKeyIdentifier.from_public_key(csr_public_key), critical=False, ) builder = builder.add_extension( x509.AuthorityKeyIdentifier.from_issuer_public_key( self.ca_public_key ), critical=False, ) builder = builder.add_extension( x509.BasicConstraints(ca=True, path_length=1), critical=True, ) cert = builder.sign( private_key=self.ca_key, algorithm=hashes.SHA256(), backend=default_backend(), ) return cert.public_bytes(serialization.Encoding.PEM)
def signer_csr(self, nom_fichier_csr, nom_signataire): with open('%s.key.pem' % nom_signataire, 'rb') as fichier: private_bytes = fichier.read() signing_key = serialization.load_pem_private_key( private_bytes, password=None, backend=default_backend()) with open('%s.cert.pem' % nom_signataire, 'rb') as fichier: public_bytes = fichier.read() signing_cert = x509.load_pem_x509_certificate( public_bytes, backend=default_backend()) with open('%s.csr.pem' % nom_fichier_csr, 'rb') as fichier: public_bytes = fichier.read() fichier_csr = x509.load_pem_x509_csr(public_bytes, backend=default_backend()) one_day = datetime.timedelta(1, 0, 0) builder = x509.CertificateBuilder() builder = builder.subject_name(fichier_csr.subject) builder = builder.issuer_name(signing_cert.subject) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + self.__duree_cert_noeud) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(fichier_csr.public_key()) builder = builder.add_extension(x509.SubjectAlternativeName( [x509.DNSName(u'mon_serveur.ca')]), critical=False) builder = builder.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ) builder = builder.add_extension( x509.SubjectKeyIdentifier.from_public_key( fichier_csr.public_key()), critical=False) ski = signing_cert.extensions.get_extension_for_oid( x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER) builder = builder.add_extension(x509.AuthorityKeyIdentifier( ski.value.digest, None, None), critical=False) builder = builder.add_extension(x509.KeyUsage(digital_signature=True, content_commitment=True, key_encipherment=True, data_encipherment=True, key_agreement=True, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False), critical=False) certificate = builder.sign(private_key=signing_key, algorithm=hashes.SHA512(), backend=default_backend()) with open('%s.cert.pem' % nom_fichier_csr, 'wb') as fichier: fichier.write(certificate.public_bytes(serialization.Encoding.PEM))
def certify_p10(request): # Load CA certificate and private key key = load_pem_private_key(ca_private.encode('ascii'), ca_password.encode('ascii'), default_backend()) cacert = x509.load_pem_x509_certificate(ca_cert.encode('ascii'), default_backend()) # Load Request x509req = x509.load_pem_x509_csr(request, default_backend()) # Create certificate for it sernum = x509.random_serial_number() cert = x509.CertificateBuilder()\ .issuer_name(cacert.subject)\ .subject_name(x509req.subject)\ .public_key(x509req.public_key())\ .serial_number(sernum)\ .not_valid_before(datetime.now())\ .not_valid_after(datetime.now() + timedelta(days=366))\ .add_extension(x509.KeyUsage(digital_signature=True , content_commitment=True , key_encipherment=False , data_encipherment=False , key_agreement=False , key_cert_sign=False , crl_sign=False , encipher_only=False , decipher_only = False), critical=True)\ .sign(key, hashes.SHA256(), default_backend()) pemCert = cert.public_bytes(serialization.Encoding.PEM).decode('ascii') return pemCert
def issue_certificate(csr, options): csr = x509.load_pem_x509_csr(csr.encode('utf-8'), default_backend()) builder = x509.CertificateBuilder( issuer_name=x509.Name([ x509.NameAttribute( x509.OID_ORGANIZATION_NAME, options['authority'].authority_certificate.issuer) ]), subject_name=csr.subject, public_key=csr.public_key(), not_valid_before=options['validity_start'], not_valid_after=options['validity_end'], extensions=csr.extensions) # TODO figure out a better way to increment serial builder = builder.serial_number(int(uuid.uuid4())) private_key = serialization.load_pem_private_key(bytes( str(options['authority'].authority_certificate.private_key).encode( 'utf-8')), password=None, backend=default_backend()) cert = builder.sign(private_key, hashes.SHA256(), default_backend()) return cert.public_bytes( encoding=serialization.Encoding.PEM).decode('utf-8')
def migrate(apps, schema_editor): Certificate = apps.get_model("django_ca", "Certificate") CertificateAuthority = apps.get_model("django_ca", "CertificateAuthority") for cert in Certificate.objects.all(): if cert.csr != "": try: csr = x509.load_pem_x509_csr(cert.csr.encode()) except Exception: print(f"{cert}: Could not convert CSR.") continue cert.csr_tmp = csr try: cert.pub_tmp = x509.load_pem_x509_certificate(cert.pub.encode()) except Exception: print(f"{cert}: Could not convert PEM.") continue cert.save() for ca in CertificateAuthority.objects.all(): try: ca.pub_tmp = x509.load_pem_x509_certificate(ca.pub.encode()) except Exception: print(f"{cert}: Could not convert PEM.") continue ca.save()
def sign_dart(self): csr_data = request.data print(csr_data) csr = x509.load_pem_x509_csr(csr_data, default_backend()) issuer = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, 'CA')]) #build certif basic_contraints = x509.BasicConstraints(ca=False, path_length=None) now = datetime.utcnow() certbuilder = x509.CertificateBuilder() certbuilder = certbuilder.subject_name(csr.subject) certbuilder = certbuilder.issuer_name(issuer) certbuilder = certbuilder.public_key(csr.public_key()) certbuilder = certbuilder.serial_number(int(uuid4())) certbuilder = certbuilder.not_valid_before(now - timedelta(days=1)) certbuilder = certbuilder.not_valid_after(now + timedelta(days=10 * 365)) certbuilder = certbuilder.add_extension(basic_contraints, False) self.load_private_key() certificate = certbuilder.sign(self.private_key, hashes.SHA256(), default_backend()) cert_pem = certificate.public_bytes( encoding=serialization.Encoding.PEM) cert_pem = certificate.public_bytes( encoding=serialization.Encoding.PEM) numberlist = np.frombuffer(cert_pem, dtype='int8').tolist() print(cert_pem.decode("utf-8")) #print(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value) try: ldapFunctions.connect() edits = { 'userSMIMECertificate': [(MODIFY_REPLACE, str(numberlist))] } print(edits) res = ldapFunctions.conn.modify( dn='cn=' + csr.subject.get_attributes_for_oid( NameOID.COMMON_NAME)[0].value + ',ou=People,dc=insat,dc=chat,dc=com', changes=edits, ) #print(res) print(ldapFunctions.conn.result) ldapFunctions.conn.unbind() except ldap3.LDAPError: ldapFunctions.conn.unbind() #with open(certfile, "wb+") as f: #f.write(cert_pem) print(len(cert_pem.decode("utf-8"))) return cert_pem
def test_generate_dv_csr_with_existing_key(tmp_path, common_name, sans): name = 'auto_example.com' existing_key_content = tests_util.DATA_PATH.joinpath('auto_example.com.key').read_bytes() key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=existing_key_content, output_path=str(tmp_path), ) # check that returned key content is same than input key content assert key_content == existing_key_content # check csr files has been created assert csr_path.is_file() # check csr file has right name assert csr_path.name == '%s.csr' % name # load csr first csr = x509.load_pem_x509_csr(data=csr_path.read_bytes(), backend=default_backend()) # check content of CSR if common_name is not None: assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name else: # common name is optional assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 0 assert sans == [dns_name.value for dns_name in csr.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value]
def sign_csr(self, csr_file): with open(csr_file, 'rb') as f: csr = x509.load_pem_x509_csr(data=f.read(), backend=default_backend()) subject_common_name = csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value cert, _ = self.create_signed_cert_files(name=subject_common_name, overwrite=False, csr=csr) return cert.public_bytes(encoding=serialization.Encoding.PEM)
def _test_generate_csr(self, ykman_cli, tmp_file, algo): ykman_cli( "piv", "keys", "generate", "9a", "-a", algo, "-m", DEFAULT_MANAGEMENT_KEY, tmp_file, ) output = ykman_cli( "piv", "certificates", "request", "9a", tmp_file, "-s", "test-subject", "-P", DEFAULT_PIN, "-", ).output csr = x509.load_pem_x509_csr(output.encode(), default_backend()) assert csr.is_signature_valid
def stub_generer_certificat_localement(self, demande): role = demande['role'] csr_bytes = demande['csr'].encode('utf-8') csr = x509.load_pem_x509_csr(csr_bytes, backend=default_backend()) clecert_millegrille = EnveloppeCleCert() fichier_millegrille_cle = '/home/mathieu/mgdev/certs/pki.ca.millegrille.key' fichier_millegrille_cert = '/home/mathieu/mgdev/certs/pki.ca.millegrille.cert' fichier_millegrille_password = '******' with open(fichier_millegrille_password, 'r') as fichier: passwords = json.load(fichier) mot_de_passe = passwords['pki.ca.millegrille'] clecert_millegrille.from_files(fichier_millegrille_cle, fichier_millegrille_cert, mot_de_passe.encode('utf-8')) generateur = GenererDeployeur(self.idmg, self.role, self.node, dict(), autorite=clecert_millegrille) certificat = generateur.signer(csr) clecert = EnveloppeCleCert() clecert.cert = certificat fullchain = ['cert1', 'cert2'] reponse = { 'cert': clecert.cert_bytes.decode('utf-8'), 'fullchain': fullchain, 'role': role, } return reponse
def load(cls, data=None, filename=None): if filename is not None: with open(filename, 'rb') as fh: data = fh.read() csr = x509.load_pem_x509_csr( data, default_backend()) return CSR(csr)
def create_modhash_key_and_csr(common_name, public_exponent=None, key_size=None, key=None, csr=None, oids=None, sans=None, encoding='PEM'): if csr: csr = x509.load_pem_x509_csr(str.encode(csr), default_backend()) elif key: key = serialization.load_pem_private_key(str.encode(key), password=None, backend=default_backend()) csr = _create_csr(common_name, key, oids, sans) else: key = _create_key(common_name, public_exponent, key_size) csr = _create_csr(common_name, key, oids, sans) modhash = _create_modhash(csr) if isinstance(key, _RSAPrivateKey): key = key.private_bytes( encoding=ENCODING[encoding], format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()).decode('utf-8') if isinstance(csr, _CertificateSigningRequest): csr = csr.public_bytes(ENCODING[encoding]).decode('utf-8') return (modhash, key, csr)
def csr(data): """ Determines if the CSR is valid and allowed. :param data: :return: """ try: request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend()) except Exception: raise ValidationError("CSR presented is not valid.") # Validate common name and SubjectAltNames try: for name in request.subject.get_attributes_for_oid( NameOID.COMMON_NAME): common_name(name.value) except ValueError as err: current_app.logger.info("Error parsing Subject from CSR: %s", err) raise ValidationError("Invalid Subject value in supplied CSR") try: alt_names = request.extensions.get_extension_for_class( x509.SubjectAlternativeName) for name in alt_names.value.get_values_for_type(x509.DNSName): sensitive_domain(name) except x509.ExtensionNotFound: pass
def create_and_write_csr(http_key: rsa.RSAPrivateKeyWithSerialization, domains: list, overwrite=True) \ -> x509.CertificateSigningRequest: if not overwrite and HTTP_CERT_REQUEST_PATH.exists(): return x509.load_pem_x509_csr(data=HTTP_CERT_REQUEST_PATH.read_bytes(), backend=default_backend()) subject = x509.Name([ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "NepoJang"), x509.NameAttribute(NameOID.COMMON_NAME, f"NepoJang HTTP API Certificate"), ]) alt_names = [] for domain in domains: alt_names.append(x509.DNSName(domain)) certificate_request = x509.CertificateSigningRequestBuilder()\ .subject_name(subject)\ .add_extension(x509.SubjectAlternativeName(alt_names), critical=False)\ .sign(http_key, hashes.SHA512(), default_backend()) with open(HTTP_CERT_REQUEST_PATH, "wb") as http_csr_file: http_csr_file.write( certificate_request.public_bytes(serialization.Encoding.PEM)) return certificate_request
def issue_certificate(csr, options): csr = x509.load_pem_x509_csr(csr, default_backend()) builder = x509.CertificateBuilder( issuer_name=x509.Name([ x509.NameAttribute( x509.OID_ORGANIZATION_NAME, options['authority'].authority_certificate.issuer )] ), subject_name=csr.subject, public_key=csr.public_key(), not_valid_before=options['validity_start'], not_valid_after=options['validity_end'], extensions=csr.extensions) # TODO figure out a better way to increment serial builder = builder.serial_number(int(uuid.uuid4())) private_key = serialization.load_pem_private_key( options['authority'].authority_certificate.private_key, password=None, backend=default_backend() ) cert = builder.sign(private_key, hashes.SHA256(), default_backend()) return cert.public_bytes( encoding=serialization.Encoding.PEM )
def get_csr_from_certmonger(nickname): """ Get the csr for the provided nickname by asking certmonger. Returns the csr in ASCII format without the header/footer in a single line or None if not found. """ criteria = { 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, 'cert-nickname': nickname, } id = certmonger.get_request_id(criteria) if id: csr = certmonger.get_request_value(id, "csr") if csr: try: # Make sure the value can be parsed as valid CSR csr_obj = crypto_x509.load_pem_x509_csr( csr.encode('ascii'), default_backend()) val = base64.b64encode(csr_obj.public_bytes(x509.Encoding.DER)) return val.decode('ascii') except Exception as e: # Fallthrough and return None logger.debug("Unable to get CSR from certmonger: %s", e) return None
def _test_generate_csr(self, slot, algo): subject_input = "subject-" + algo pubkey_output = ykman_cli( "piv", "generate-key", slot, "-a", algo, "-m", NON_DEFAULT_MANAGEMENT_KEY, "-", ) csr_output = ykman_cli( "piv", "generate-csr", slot, "-P", DEFAULT_PIN, "-", "-", "-s", subject_input, input=pubkey_output, ) csr = x509.load_pem_x509_csr(csr_output.encode("utf-8"), default_backend()) subject_output = csr.subject.get_attributes_for_oid( x509.NameOID.COMMON_NAME)[0].value self.assertEqual(subject_input, subject_output)
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 parse_csr( csr: Union[x509.CertificateSigningRequest, str, bytes], csr_format: Encoding ) -> x509.CertificateSigningRequest: """Parse a CSR in the given format. .. deprecated:: 1.18.0 This function is no longer useful and will be removed in django-ca 1.20.0. Parameters ---------- csr : str or bytes or :py:class:`~cg:cryptography.x509.CertificateSigningRequest` The CSR to parse. csr_format : :py:class:`~cg:cryptography.hazmat.primitives.serialization.Encoding` The format that the CSR is in. """ if isinstance(csr, x509.CertificateSigningRequest): # pragma: no cover # not used since 1.18.0 return csr if csr_format == Encoding.PEM: return x509.load_pem_x509_csr(force_bytes(csr), default_backend()) if csr_format == Encoding.DER: return x509.load_der_x509_csr(force_bytes(csr), default_backend()) raise ValueError("Unknown CSR format passed: %s" % csr_format)
def generate_identity_certificate(csr_pem, ca_signing_key, ca_certificates, valid_days, device_id): # Load the CSR csr = load_pem_x509_csr(csr_pem, default_backend()) # TODO: check the CSR parameters signing_cert = ca_certificates[0] time_now = datetime.datetime.utcnow() # Generate a certificate from the CSR using the X.509 Certificate Builder cert = x509.CertificateBuilder().subject_name( x509.Name([ x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, u'{}'.format(device_id)) ])).issuer_name(signing_cert.subject).public_key( csr.public_key()).serial_number( x509.random_serial_number()).not_valid_before( time_now).not_valid_after(time_now + datetime.timedelta( days=valid_days)).sign(ca_signing_key, hashes.SHA256(), default_backend()) # Return the entire chain, DER encoded chain = [cert] + ca_certificates print('Certificate: \n{}'.format( cert.public_bytes(serialization.Encoding.PEM).decode('utf-8'))) return [x.public_bytes(serialization.Encoding.DER) for x in chain]
def validation_logic(payload): try: pub_key = x509.load_pem_x509_csr( payload['pub_key'].encode('utf-8'), default_backend()) if not is_valid_token_balance(): return {'error': 'You have no tokens to issue pub_key'}, 402 not_valid_before = payload.get('not_valid_before', None) not_valid_after = payload.get('not_valid_after', None) not_valid_before = datetime.datetime.fromtimestamp( not_valid_before ) if not_valid_before else datetime.datetime.utcnow() not_valid_after = datetime.datetime.fromtimestamp( not_valid_after ) if not_valid_after else not_valid_before + PUB_KEY_MAX_VALIDITY if not_valid_after: if not_valid_before >= not_valid_after: return { 'error': 'not_valid_before pub_key property has to occur before the not_valid_after' }, 400 if not_valid_after - not_valid_before > PUB_KEY_MAX_VALIDITY: return { 'error': 'The pub_key validity exceeds the maximum value.' }, 400 except ValueError: return {'error': 'Unable to load pub_key request entity'}, 422 return func(pub_key, not_valid_before, not_valid_after)
def get_sans_from_csr(data): """ Fetches SubjectAlternativeNames from CSR. Works with any kind of SubjectAlternativeName :param data: PEM-encoded string with CSR :return: List of LemurAPI-compatible subAltNames """ sub_alt_names = [] try: request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend()) except Exception: raise ValidationError("CSR presented is not valid.") try: alt_names = request.extensions.get_extension_for_class( x509.SubjectAlternativeName ) for alt_name in alt_names.value: sub_alt_names.append( {"nameType": type(alt_name).__name__, "value": alt_name.value} ) except x509.ExtensionNotFound: pass return sub_alt_names
def store_request(buf, overwrite=False): """ Store CSR for later processing """ if not buf: return # No certificate supplied csr = x509.load_pem_x509_csr(buf, backend=default_backend()) for name in csr.subject: if name.oid == NameOID.COMMON_NAME: common_name = name.value break else: raise ValueError("No common name in %s" % csr.subject) request_path = os.path.join(config.REQUESTS_DIR, common_name + ".pem") if not re.match(RE_HOSTNAME, common_name): raise ValueError("Invalid common name") # If there is cert, check if it's the same if os.path.exists(request_path): if open(request_path).read() == buf: raise errors.RequestExists("Request already exists") else: raise errors.DuplicateCommonNameError("Another request with same common name already exists") else: with open(request_path + ".part", "w") as fh: fh.write(buf) os.rename(request_path + ".part", request_path) req = Request(open(request_path)) mailer.send("request-stored.md", attachments=(req,), request=req) return req
def sign_csr(self, ipa_csr, path_length=1): """Sign certificate CSR. :param ipa_csr: CSR in PEM format. :type ipa_csr: bytes. :returns: bytes -- Signed CA in PEM format. """ csr_tbs = x509.load_pem_x509_csr(ipa_csr, default_backend()) csr_public_key = csr_tbs.public_key() csr_subject = csr_tbs.subject builder = x509.CertificateBuilder() builder = builder.public_key(csr_public_key) builder = builder.subject_name(csr_subject) builder = builder.serial_number(x509.random_serial_number()) builder = builder.issuer_name(self.issuer) builder = builder.not_valid_before(self.now) builder = builder.not_valid_after(self.now + self.delta) builder = builder.add_extension( x509.KeyUsage( digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False, ), critical=True, ) builder = builder.add_extension( x509.SubjectKeyIdentifier.from_public_key(csr_public_key), critical=False, ) builder = builder.add_extension( x509.AuthorityKeyIdentifier.from_issuer_public_key( self.ca_public_key ), critical=False, ) builder = builder.add_extension( x509.BasicConstraints(ca=True, path_length=path_length), critical=True, ) cert = builder.sign( private_key=self.ca_key, algorithm=hashes.SHA256(), backend=default_backend(), ) return cert.public_bytes(serialization.Encoding.PEM)
def sign(csr, issuer_name, ca_key, ca_key_password=None, skip_validation=False): """Sign a given csr :param csr: certificate signing request object or pem encoded csr :param issuer_name: issuer name :param ca_key: private key of CA :param ca_key_password: private key password for given ca key :param skip_validation: skip csr validation if true :returns: generated certificate """ if not isinstance(ca_key, rsa.RSAPrivateKey): ca_key = serialization.load_pem_private_key(ca_key, password=ca_key_password, backend=default_backend()) if not isinstance(issuer_name, six.text_type): issuer_name = six.text_type(issuer_name.decode('utf-8')) if isinstance(csr, six.text_type): csr = six.b(str(csr)) if not isinstance(csr, x509.CertificateSigningRequest): try: csr = x509.load_pem_x509_csr(csr, backend=default_backend()) except ValueError: LOG.exception(_LE("Received invalid csr {0}.").format(csr)) raise exception.InvalidCsr(csr=csr) term_of_validity = cfg.CONF.x509.term_of_validity one_day = datetime.timedelta(1, 0, 0) expire_after = datetime.timedelta(term_of_validity, 0, 0) builder = x509.CertificateBuilder() builder = builder.subject_name(csr.subject) # issuer_name is set as common name builder = builder.issuer_name(x509.Name([ x509.NameAttribute(x509.OID_COMMON_NAME, issuer_name), ])) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + expire_after) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.public_key(csr.public_key()) if skip_validation: extensions = csr.extensions else: extensions = validator.filter_extensions(csr.extensions) for extention in extensions: builder = builder.add_extension(extention.value, critical=extention.critical) certificate = builder.sign( private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend() ).public_bytes(serialization.Encoding.PEM) return certificate
def check_mscs_extension(ipa_csr, template): csr = x509.load_pem_x509_csr(ipa_csr, default_backend()) extensions = [ ext for ext in csr.extensions if ext.oid.dotted_string == template.ext_oid ] assert extensions assert extensions[0].value.value == template.get_ext_data()
def parse_csr(csr): """ Helper function that parses a CSR. :param csr: :return: """ assert isinstance(csr, str) return x509.load_pem_x509_csr(csr.encode('utf-8'), default_backend())
def sign_certificate_request(self, csr): if csr.status != 'VALIDATING' and csr.status != 'FAILED': raise Exception("Certificate could not be validated, in %s state instead of VALIDATING or FAILED" % csr.status) one_day = datetime.timedelta(1,0,0) logger.info('Signing CSR %s' % csr.common_name) csr.status = 'SIGNING' csr.save() request = x509.load_pem_x509_csr(str(csr.request), default_backend()) ca_cert = x509.load_pem_x509_certificate(str(csr.certification_authority.certificate), default_backend()) ca_key = serialization.load_pem_private_key(str(csr.certification_authority.private_key), None, default_backend()) builder = x509.CertificateBuilder() name = x509.Name(request.subject) builder = builder.subject_name(name) builder = builder.issuer_name(ca_cert.subject) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + datetime.timedelta(days=365)) builder = builder.serial_number(csr.id) builder = builder.public_key(request.public_key()) for extension in request.extensions: builder = builder.add_extension(extension.value, critical=extension.critical) certificate = builder.sign( private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend() ) logger.info("Exporting certificate") signed_cert_str = certificate.public_bytes(serialization.Encoding.PEM) logger.info('Saving model') signed_cert = SSLCertificate( certificate_request = csr, serial_number = csr.id, certification_authority=csr.certification_authority, certificate = signed_cert_str, expires_at = datetime.datetime.today() + datetime.timedelta(days=365), status = "VALID", user=csr.user ) signed_cert.save() csr.status = "SIGNED" csr.save() logger.info('Certificate signing complete') send_mail(subject="Certificate for %s" % csr.common_name, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[csr.user.email], message="""Your certificate has been signed. The certificate is this one: %s""" % (signed_cert.certificate) )
def load_csr(filename): try: with open(filename, "rb") as csr_file: csr_data = csr_file.read() csr = x509.load_pem_x509_csr(csr_data, default_backend()) return csr except IOError: return None except InvalidKey: return None
def _test_generate_csr(self, slot): for algo in ('ECCP256', 'RSA1024'): subject_input = 'subject-' + algo pubkey_output = ykman_cli( 'piv', 'generate-key', slot, '-a', algo, '-m', NON_DEFAULT_MANAGEMENT_KEY, '-') csr_output = ykman_cli( 'piv', 'generate-csr', slot, '-P', DEFAULT_PIN, '-', '-', '-s', subject_input, input=pubkey_output) csr = x509.load_pem_x509_csr(csr_output.encode('utf-8'), default_backend()) subject_output = csr.subject.get_attributes_for_oid( x509.NameOID.COMMON_NAME)[0].value self.assertEqual(subject_input, subject_output)
def test_generate_csr(self): cn = 'test_cn' # Attempt to generate a CSR csr = local_cert_gen.LocalCertGenerator._generate_csr( cn=cn, private_key=self.ca_private_key, passphrase=self.ca_private_key_passphrase ) # Attempt to load the generated CSR csro = x509.load_pem_x509_csr(data=csr, backend=backends.default_backend()) # Make sure the CN is correct self.assertEqual(cn, csro.subject.get_attributes_for_oid( x509.oid.NameOID.COMMON_NAME)[0].value)
def access_keys(): access_key_data = request.get_json() identity = access_key_data['identity'] csr_data = base64.decodebytes(access_key_data['csr'].encode()) signature = base64.decodebytes(access_key_data['signature'].encode()) key_string = database_functions.get_key(DATABASE_FILE, identity) # ...and we need to restore the key to the full PEM format that the RSA functions are expecting. restored_key = KeyEx_helpers.fixkey(key_string) # Now we can import that restored key string into a full RSA key object, get the SAH256 hash for the # message (the device ID), and create a verifier object to check the signature... pbkey = serialization.load_pem_public_key(restored_key.encode(), backend=default_backend()) # Validate that the signature is valid for the csr_data signed by this device... try: pbkey.verify(signature, csr_data, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256()) # We're okay – so sign it... with open(CA_KEY, 'rb') as f: ca_key_data = f.read() ca_key = serialization.load_pem_private_key(ca_key_data, b'rabbit', default_backend()) csr = x509.load_pem_x509_csr(csr_data, default_backend()) with open(CA_CRT, 'rb') as f: ca_crt_data = f.read() ca_crt = x509.load_pem_x509_certificate(ca_crt_data, default_backend()) if isinstance(csr.signature_hash_algorithm, hashes.SHA256): cert = x509.CertificateBuilder().subject_name(csr.subject).issuer_name(ca_crt.issuer).public_key\ (csr.public_key()).serial_number(x509.random_serial_number()).not_valid_before\ (datetime.datetime.utcnow()).not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365))\ .sign(ca_key, hashes.SHA256(), default_backend()) return_data = {'certificate': base64.encodebytes(cert.public_bytes(serialization.Encoding.PEM)).decode(), 'CA_certificate': base64.encodebytes(ca_crt_data).decode()} rv = KeyExReturn.OK(json.dumps(return_data)) return rv() except (InvalidSignature, ValueError, TypeError) as e: rv = KeyExReturn.CSRVerificationError() return rv()
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 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 sign_csr_with_ca(caKey, caCert, csr): req = x509.load_pem_x509_csr(csr, default_backend()) ca = x509.load_pem_x509_certificate(caCert, default_backend()) key = serialization.load_pem_private_key(caKey, b"mypassword", default_backend()) builder = x509.CertificateBuilder() builder = builder.subject_name(req.subject) builder = builder.issuer_name(ca.subject) builder = builder.public_key(req.public_key()) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.not_valid_before(ca.not_valid_before) builder = builder.not_valid_after(ca.not_valid_after) for e in req.extensions: builder = builder.add_extension(e.value, critical=e.critical) cert = builder.sign( private_key = key, algorithm = hashes.SHA256(), backend = default_backend() ) return cert.public_bytes(serialization.Encoding.PEM)
def signcsr(csrpem, key, period): csr = x509.load_pem_x509_csr(csrpem, default_backend()) builder = x509.CertificateBuilder() builder = builder.subject_name(csr.subject) builder = builder.issuer_name(csr.subject) builder = builder.public_key(csr.public_key()) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ) builder = builder.not_valid_before(datetime.now() - timedelta(1, 0, 0)) builder = builder.not_valid_after(datetime.now() + period) cert = builder.sign( private_key=key, algorithm=hashes.SHA256(), backend=default_backend() ) return '\n'.join([ cert.public_bytes(pem_serialization.Encoding.PEM).decode('utf-8'), cert.public_bytes(pem_serialization.Encoding.PEM).decode('utf-8') ])
def test_build_ca_request_with_unicode(self, backend): private_key = RSA_KEY_2048.private_key(backend) request = x509.CertificateSigningRequestBuilder().subject_name( x509.Name([ x509.NameAttribute(x509.OID_ORGANIZATION_NAME, u'PyCA\U0001f37a'), ]) ).add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ).sign(private_key, hashes.SHA1(), backend) loaded_request = x509.load_pem_x509_csr( request.public_bytes(encoding=serialization.Encoding.PEM), backend ) subject = loaded_request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ x509.NameAttribute(x509.OID_ORGANIZATION_NAME, u'PyCA\U0001f37a'), ]
def test_create_basic_csr(client): from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from lemur.certificates.service import create_csr csr_config = dict( common_name='example.com', organization='Example, Inc.', organizational_unit='Operations', country='US', state='CA', location='A place', extensions=dict(names=dict(sub_alt_names=['test.example.com', 'test2.example.com'])) ) csr, pem = create_csr(csr_config) private_key = serialization.load_pem_private_key(pem, password=None, backend=default_backend()) csr = x509.load_pem_x509_csr(csr, default_backend()) for name in csr.subject: assert name.value in csr_config.values()
def __init__(self, data: bytes): """ Creates a new ``x509CertSignReq object from the given bytes. Changing the produced object will NOT change the underlying bytes. The new object must first be exported. :param data: The bytes of the CSR to load. :return: A new ``x509CertSignReq`` representing the loaded CSR. :raises TypeError: If the value for ``data`` cannot be treated as bytes. :raises ValueError: If the given value for ``data`` cannot be properly decoded """ if not isinstance(data, bytes): raise TypeError("Value of 'data' must be bytes") args = (data, default_backend()) # (1) Try loading as DER try: super().__init__(x509_obj=x509.load_der_x509_csr(*args)) self.encoding = EncodingType.DER return except ValueError: pass # (2) Try loading as PEM try: super().__init__(x509_obj=x509.load_pem_x509_csr(*args)) self.encoding = EncodingType.PEM return except ValueError: pass # Could not load - bytes not in suitable format. raise ValueError("Could not find a suitable encoding for 'data' " "bytes, the data may not be a valid X509 CSR")
def csr(data): """ Determines if the CSR is valid and allowed. :param data: :return: """ try: request = x509.load_pem_x509_csr(data.encode('utf-8'), default_backend()) except Exception: raise ValidationError('CSR presented is not valid.') # Validate common name and SubjectAltNames for name in request.subject.get_attributes_for_oid(NameOID.COMMON_NAME): common_name(name.value) try: alt_names = request.extensions.get_extension_for_class(x509.SubjectAlternativeName) for name in alt_names.value.get_values_for_type(x509.DNSName): sensitive_domain(name) except x509.ExtensionNotFound: pass
def get_sans_from_csr(data): """ Fetches SubjectAlternativeNames from CSR. Works with any kind of SubjectAlternativeName :param data: PEM-encoded string with CSR :return: List of LemurAPI-compatible subAltNames """ sub_alt_names = [] try: request = x509.load_pem_x509_csr(data.encode('utf-8'), default_backend()) except Exception: raise ValidationError('CSR presented is not valid.') try: alt_names = request.extensions.get_extension_for_class(x509.SubjectAlternativeName) for alt_name in alt_names.value: sub_alt_names.append({ 'nameType': type(alt_name).__name__, 'value': alt_name.value }) except x509.ExtensionNotFound: pass return sub_alt_names
def load_req(fn): """Read CSR file. """ data = open(fn, 'rb').read() req = x509.load_pem_x509_csr(data, get_backend()) return req
def csr(self): if self._str_csr: return x509.load_pem_x509_csr(self._str_csr, default_backend()) else: return None
def issue_certificate(csr, options, private_key=None): csr = x509.load_pem_x509_csr(csr.encode('utf-8'), default_backend()) if options.get("parent"): # creating intermediate authorities will have options['parent'] to specify the issuer # creating certificates will have options['authority'] to specify the issuer # This works around that by making sure options['authority'] can be referenced for either options['authority'] = options['parent'] if options.get("authority"): # Issue certificate signed by an existing lemur_certificates authority issuer_subject = options['authority'].authority_certificate.subject issuer_private_key = options['authority'].authority_certificate.private_key chain_cert_pem = options['authority'].authority_certificate.body authority_key_identifier_public = options['authority'].authority_certificate.public_key authority_key_identifier_subject = x509.SubjectKeyIdentifier.from_public_key(authority_key_identifier_public) authority_key_identifier_issuer = issuer_subject authority_key_identifier_serial = int(options['authority'].authority_certificate.serial) # TODO figure out a better way to increment serial # New authorities have a value at options['serial_number'] that is being ignored here. serial = int(uuid.uuid4()) else: # Issue certificate that is self-signed (new lemur_certificates root authority) issuer_subject = csr.subject issuer_private_key = private_key chain_cert_pem = "" authority_key_identifier_public = csr.public_key() authority_key_identifier_subject = None authority_key_identifier_issuer = csr.subject authority_key_identifier_serial = options['serial_number'] # TODO figure out a better way to increment serial serial = int(uuid.uuid4()) extensions = normalize_extensions(csr) builder = x509.CertificateBuilder( issuer_name=issuer_subject, subject_name=csr.subject, public_key=csr.public_key(), not_valid_before=options['validity_start'], not_valid_after=options['validity_end'], serial_number=serial, extensions=extensions) for k, v in options.get('extensions', {}).items(): if k == 'authority_key_identifier': # One or both of these options may be present inside the aki extension (authority_key_identifier, authority_identifier) = (False, False) for k2, v2 in v.items(): if k2 == 'use_key_identifier' and v2: authority_key_identifier = True if k2 == 'use_authority_cert' and v2: authority_identifier = True if authority_key_identifier: if authority_key_identifier_subject: # FIXME in python-cryptography. # from_issuer_subject_key_identifier(cls, ski) is looking for ski.value.digest # but the digest of the ski is at just ski.digest. Until that library is fixed, # this function won't work. The second line has the same result. # aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(authority_key_identifier_subject) aki = x509.AuthorityKeyIdentifier(authority_key_identifier_subject.digest, None, None) else: aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(authority_key_identifier_public) elif authority_identifier: aki = x509.AuthorityKeyIdentifier(None, [x509.DirectoryName(authority_key_identifier_issuer)], authority_key_identifier_serial) builder = builder.add_extension(aki, critical=False) if k == 'certificate_info_access': # FIXME: Implement the AuthorityInformationAccess extension # descriptions = [ # x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.OCSP, x509.UniformResourceIdentifier(u"http://FIXME")), # x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.CA_ISSUERS, x509.UniformResourceIdentifier(u"http://FIXME")) # ] # for k2, v2 in v.items(): # if k2 == 'include_aia' and v2 == True: # builder = builder.add_extension( # x509.AuthorityInformationAccess(descriptions), # critical=False # ) pass if k == 'crl_distribution_points': # FIXME: Implement the CRLDistributionPoints extension # FIXME: Not implemented in lemur/schemas.py yet https://github.com/Netflix/lemur/issues/662 pass private_key = serialization.load_pem_private_key( bytes(str(issuer_private_key).encode('utf-8')), password=None, backend=default_backend() ) cert = builder.sign(private_key, hashes.SHA256(), default_backend()) cert_pem = cert.public_bytes( encoding=serialization.Encoding.PEM ).decode('utf-8') return cert_pem, chain_cert_pem
def sign_cert(cls, csr, validity, ca_cert=None, ca_key=None, ca_key_pass=None, ca_digest=None): """Signs a certificate using our private CA based on the specified CSR The signed certificate will be valid from now until <validity> seconds from now. :param csr: A Certificate Signing Request :param validity: Valid for <validity> seconds from the current time :param ca_cert: Signing Certificate (default: config) :param ca_key: Signing Certificate Key (default: config) :param ca_key_pass: Signing Certificate Key Pass (default: config) :param ca_digest: Digest method to use for signing (default: config) :return: Signed certificate :raises Exception: if certificate signing fails """ LOG.info(_LI( "Signing a certificate request using OpenSSL locally." )) cls._validate_cert(ca_cert, ca_key, ca_key_pass) if not ca_digest: ca_digest = CONF.certificates.signing_digest try: algorithm = getattr(hashes, ca_digest.upper())() except AttributeError: raise crypto_exceptions.UnsupportedAlgorithm( "Supplied digest method not found: %s" % ca_digest ) if not ca_cert: with open(CONF.certificates.ca_certificate, 'r') as f: ca_cert = f.read() if not ca_key: with open(CONF.certificates.ca_private_key, 'r') as f: ca_key = f.read() if not ca_key_pass: ca_key_pass = CONF.certificates.ca_private_key_passphrase try: lo_cert = x509.load_pem_x509_certificate( data=ca_cert, backend=backends.default_backend()) lo_key = serialization.load_pem_private_key( data=ca_key, password=ca_key_pass, backend=backends.default_backend()) lo_req = x509.load_pem_x509_csr(data=csr, backend=backends.default_backend()) new_cert = x509.CertificateBuilder() new_cert = new_cert.serial_number(cls._new_serial()) valid_from_datetime = datetime.datetime.utcnow() valid_to_datetime = (datetime.datetime.utcnow() + datetime.timedelta(seconds=validity)) new_cert = new_cert.not_valid_before(valid_from_datetime) new_cert = new_cert.not_valid_after(valid_to_datetime) new_cert = new_cert.issuer_name(lo_cert.subject) new_cert = new_cert.subject_name(lo_req.subject) new_cert = new_cert.public_key(lo_req.public_key()) new_cert = new_cert.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True ) new_cert = new_cert.add_extension( x509.ExtendedKeyUsage([ x509.oid.ExtendedKeyUsageOID.SERVER_AUTH, x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH ]), critical=True ) signed_cert = new_cert.sign(private_key=lo_key, algorithm=algorithm, backend=backends.default_backend()) return signed_cert.public_bytes( encoding=serialization.Encoding.PEM) except Exception as e: LOG.error(_LE("Unable to sign certificate.")) raise exceptions.CertificateGenerationException(msg=e)
def ParseFromString(self, csr_as_pem): self._value = x509.load_pem_x509_csr(csr_as_pem, backend=openssl.backend)
def csr_to_crt(csr_pem, ca_crt_pem, ca_key_pem, password=None, cn=None, ou=None, org=None, serial=None, duration=None): logger.debug("csr_pem:\n{}".format(csr_pem)) logger.debug("cn: {}".format(cn)) logger.debug("ou: {}".format(ou)) logger.debug("org: {}".format(org)) logger.debug("duration: {}".format(duration)) logger.debug("serial: {}".format(serial)) if isinstance(csr_pem, str): csr_pem = csr_pem.encode() if isinstance(ca_key_pem, str): ca_key_pem = ca_key_pem.encode() if isinstance(ca_crt_pem, str): ca_crt_pem = ca_crt_pem.encode() if isinstance(password, str): password = password.encode() be = default_backend() csr = x509.load_pem_x509_csr(csr_pem, be) ca_crt = x509.load_pem_x509_certificate(ca_crt_pem, be) ca_key = serialization.load_pem_private_key(ca_key_pem, password, be) if not cn: cn = csr.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value if not ou: ou = csr.subject.get_attributes_for_oid(x509.NameOID.ORGANIZATIONAL_UNIT_NAME)[0].value if not org: org = csr.subject.get_attributes_for_oid(x509.NameOID.ORGANIZATION_NAME)[0].value if not duration: duration = constants.DUR_ONE_YEAR if not serial: serial = uuid.uuid4() sub_attrs = [] sub_attrs += csr.subject.get_attributes_for_oid(x509.NameOID.COUNTRY_NAME) sub_attrs += csr.subject.get_attributes_for_oid(x509.NameOID.LOCALITY_NAME) sub_attrs += csr.subject.get_attributes_for_oid(x509.NameOID.STATE_OR_PROVINCE_NAME) sub_attrs.append(x509.NameAttribute(x509.NameOID.COMMON_NAME, cn)) sub_attrs.append(x509.NameAttribute(x509.NameOID.ORGANIZATIONAL_UNIT_NAME, ou)) sub_attrs.append(x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, org)) logger.debug("sub_attr: {}".format(sub_attrs)) builder = x509.CertificateBuilder() builder = builder.issuer_name(ca_crt.subject) builder = builder.subject_name(x509.Name(sub_attrs)) builder = builder.not_valid_before(datetime.datetime.today() - constants.DUR_ONE_DAY) builder = builder.not_valid_after(datetime.datetime.today() + duration) builder = builder.serial_number(int(serial)) builder = builder.public_key(csr.public_key()) extensions = [] extensions.append(x509.BasicConstraints(ca=False, path_length=None)) logger.debug("extensions: {}".format(extensions)) for ext in extensions: builder = builder.add_extension(ext, critical=True) crt = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=be) crt_pem = crt.public_bytes(serialization.Encoding.PEM).decode() logger.debug("crt_pem:\n{}".format(crt_pem)) return crt_pem
def __call__(self, parser, namespace, values, option_string): setattr(namespace, self.dest, x509.load_pem_x509_csr(raw_loader(values), backend))