def test_add_extension_checks_for_duplicates(self): builder = x509.RevokedCertificateBuilder().add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False) with pytest.raises(ValueError): builder.add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False)
def test_add_multiple_extensions(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) invalidity_date = x509.InvalidityDate( datetime.datetime(2015, 1, 1, 0, 0) ) certificate_issuer = x509.CertificateIssuer( [x509.DNSName(u"cryptography.io")] ) crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise) builder = ( x509.RevokedCertificateBuilder() .serial_number(serial_number) .revocation_date(revocation_date) .add_extension(invalidity_date, True) .add_extension(crl_reason, True) .add_extension(certificate_issuer, True) ) revoked_certificate = builder.build(backend) assert len(revoked_certificate.extensions) == 3 for ext_data in [invalidity_date, certificate_issuer, crl_reason]: ext = revoked_certificate.extensions.get_extension_for_class( type(ext_data) ) assert ext.critical is True assert ext.value == ext_data
def create_crl(crl_path, ca_key, ca_cert): now = datetime.utcnow() builder = ( x509.CertificateRevocationListBuilder() .last_update(now) .next_update(now + timedelta(days=1)) .issuer_name(ca_cert.subject) ) for i in [3,4,5]: cert = ( x509.RevokedCertificateBuilder() .revocation_date(now) .serial_number(i) .add_extension( x509.CRLReason(x509.ReasonFlags.key_compromise), critical=False) .build(default_backend()) ) builder = builder.add_revoked_certificate(cert) cert = builder.sign( private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend()) write_public(cert, crl_path)
def test_single_extensions(self, backend): resp = _load_data( os.path.join("x509", "ocsp", "resp-single-extension-reason.der"), ocsp.load_der_ocsp_response, ) assert len(resp.single_extensions) == 1 ext = resp.single_extensions[0] assert ext.oid == x509.CRLReason.oid assert ext.value == x509.CRLReason(x509.ReasonFlags.unspecified)
def _decode_crl_reason(backend, enum): enum = backend._ffi.cast("ASN1_ENUMERATED *", enum) enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free) code = backend._lib.ASN1_ENUMERATED_get(enum) try: return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code]) except KeyError: raise ValueError("Unsupported reason code: {}".format(code))
def _generate_crl(self): backend = default_backend() crl = CertificateRevocationListBuilder() try: crl = crl.issuer_name( Name([ NameAttribute(cryptography_name_to_oid(entry[0]), to_text(entry[1])) for entry in self.issuer ])) except ValueError as e: raise CRLError(e) crl = crl.last_update(self.last_update) crl = crl.next_update(self.next_update) if self.update and self.crl: new_entries = set([ self._compress_entry(entry) for entry in self.revoked_certificates ]) for entry in self.crl: decoded_entry = self._compress_entry( cryptography_decode_revoked_certificate(entry)) if decoded_entry not in new_entries: crl = crl.add_revoked_certificate(entry) for entry in self.revoked_certificates: revoked_cert = RevokedCertificateBuilder() revoked_cert = revoked_cert.serial_number(entry['serial_number']) revoked_cert = revoked_cert.revocation_date( entry['revocation_date']) if entry['issuer'] is not None: revoked_cert = revoked_cert.add_extension( x509.CertificateIssuer([ cryptography_get_name(name, 'issuer') for name in entry['issuer'] ]), entry['issuer_critical']) if entry['reason'] is not None: revoked_cert = revoked_cert.add_extension( x509.CRLReason(entry['reason']), entry['reason_critical']) if entry['invalidity_date'] is not None: revoked_cert = revoked_cert.add_extension( x509.InvalidityDate(entry['invalidity_date']), entry['invalidity_date_critical']) crl = crl.add_revoked_certificate(revoked_cert.build(backend)) self.crl = crl.sign(self.privatekey, self.digest, backend=backend) if self.format == 'pem': return self.crl.public_bytes(Encoding.PEM) else: return self.crl.public_bytes(Encoding.DER)
def get_revocation(self): """Get a crypto.Revoked object or None if the cert is not revoked.""" if self.revoked is False: raise ValueError('Certificate is not revoked.') revoked_cert = x509.RevokedCertificateBuilder().serial_number( self.x509.serial).revocation_date(self.revoked_date) if self.revoked_reason: reason_flag = getattr(x509.ReasonFlags, self.revoked_reason) revoked_cert = revoked_cert.add_extension( x509.CRLReason(reason_flag), critical=False) return revoked_cert.build(default_backend())
def _upki_generate_crl(self, params): self.output('Start CRL generation') now = datetime.datetime.utcnow() try: builder = ( x509.CertificateRevocationListBuilder() .issuer_name(self._ca['cert'].issuer) .last_update(now) .next_update(now + datetime.timedelta(days=3)) ) except Exception as err: raise Exception('Unable to build CRL: {e}'.format(e=err)) for entry in self._storage.get_revoked(): try: revoked_cert = ( x509.RevokedCertificateBuilder() .serial_number(entry['Serial']) .revocation_date(datetime.datetime.strptime(entry['Revoke_Date'],'%Y%m%d%H%M%SZ')) .add_extension(x509.CRLReason(x509.ReasonFlags.cessation_of_operation), critical=False) .build(self._backend) ) except Exception as err: self.output('Unable to build CRL entry for {d}: {e}'.format(d=entry['DN'], e=err), level='ERROR') continue try: builder = builder.add_revoked_certificate(revoked_cert) except Exception as err: self.output('Unable to add CRL entry for {d}: {e}'.format(d=entry['DN'], e=err), level='ERROR') continue try: crl = builder.sign(private_key=self._ca['key'], algorithm=hashes.SHA256(), backend=self._backend) except Exception as err: raise Exception('Unable to sign CSR: {e}'.format(e=err)) try: crl_pem = crl.public_bytes(serialization.Encoding.PEM) self._storage.store_crl(crl_pem) except Exception as err: raise Exception(err) return {'state': 'OK'}
def test_sign_with_revoked_certificates(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) next_update = datetime.datetime(2030, 1, 1, 12, 1) invalidity_date = x509.InvalidityDate( datetime.datetime(2002, 1, 1, 0, 0)) revoked_cert0 = ( x509.RevokedCertificateBuilder().serial_number(38).revocation_date( datetime.datetime(2011, 1, 1, 1, 1)).build(backend)) revoked_cert1 = ( x509.RevokedCertificateBuilder().serial_number(2).revocation_date( datetime.datetime(2012, 1, 1, 1, 1)).add_extension( invalidity_date, False).add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False).build(backend)) ci = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) revoked_cert2 = ( x509.RevokedCertificateBuilder().serial_number(40).revocation_date( datetime.datetime(2011, 1, 1, 1, 1)).add_extension(ci, False).build(backend)) builder = ( x509.CertificateRevocationListBuilder().issuer_name( x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io CA") ])).last_update(last_update).next_update(next_update). add_revoked_certificate(revoked_cert0).add_revoked_certificate( revoked_cert1).add_revoked_certificate(revoked_cert2)) crl = builder.sign(private_key, hashes.SHA256(), backend) assert len(crl) == 3 assert crl.last_update == last_update assert crl.next_update == next_update assert crl[0].serial_number == revoked_cert0.serial_number assert crl[0].revocation_date == revoked_cert0.revocation_date assert len(crl[0].extensions) == 0 assert crl[1].serial_number == revoked_cert1.serial_number assert crl[1].revocation_date == revoked_cert1.revocation_date assert len(crl[1].extensions) == 2 ext = crl[1].extensions.get_extension_for_class(x509.InvalidityDate) assert ext.critical is False assert ext.value == invalidity_date assert (crl[2].extensions.get_extension_for_class( x509.CertificateIssuer).value == ci)
def get_revocation(self): if self.revoked is False: raise ValueError('Certificate is not revoked.') revoked_cert = x509.RevokedCertificateBuilder().serial_number( self.x509.serial_number).revocation_date(self.revoked_date) reason = self.get_revocation_reason() if reason != x509.ReasonFlags.unspecified: # RFC 5270, 5.3.1: "reason code CRL entry extension SHOULD be absent instead of using the # unspecified (0) reasonCode value" revoked_cert = revoked_cert.add_extension(x509.CRLReason(reason), critical=False) compromised = self.get_compromised_time() if compromised: # RFC 5280, 5.3.2 says that this extension MUST be non-critical revoked_cert = revoked_cert.add_extension(x509.InvalidityDate(compromised), critical=False) return revoked_cert.build(default_backend())
class TestRevokedCertificateBuilder(object): def test_serial_number_must_be_integer(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().serial_number("notanx509name") def test_serial_number_must_be_non_negative(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(-1) def test_serial_number_must_be_positive(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(0) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_minimal_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = x509.RevokedCertificateBuilder().serial_number( 1).revocation_date(revocation_date) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == 1 @pytest.mark.requires_backend_interface(interface=X509Backend) def test_biggest_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = x509.RevokedCertificateBuilder().serial_number( (1 << 159) - 1).revocation_date(revocation_date) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == (1 << 159) - 1 def test_serial_number_must_be_less_than_160_bits_long(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(1 << 159) def test_set_serial_number_twice(self): builder = x509.RevokedCertificateBuilder().serial_number(3) with pytest.raises(ValueError): builder.serial_number(4) def test_revocation_date_invalid(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().revocation_date("notadatetime") def test_revocation_date_before_unix_epoch(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(1960, 8, 10)) def test_set_revocation_date_twice(self): builder = x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(2002, 1, 1, 12, 1)) with pytest.raises(ValueError): builder.revocation_date(datetime.datetime(2002, 1, 1, 12, 1)) def test_add_extension_checks_for_duplicates(self): builder = x509.RevokedCertificateBuilder().add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False) with pytest.raises(ValueError): builder.add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False) def test_add_invalid_extension(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().add_extension( "notanextension", False) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_serial_number(self, backend): builder = x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(2002, 1, 1, 12, 1)) with pytest.raises(ValueError): builder.build(backend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_revocation_date(self, backend): builder = x509.RevokedCertificateBuilder().serial_number(3) with pytest.raises(ValueError): builder.build(backend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_create_revoked(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == serial_number assert revoked_certificate.revocation_date == revocation_date assert len(revoked_certificate.extensions) == 0 @pytest.mark.parametrize("extension", [ x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)), x509.CRLReason(x509.ReasonFlags.ca_compromise), x509.CertificateIssuer([ x509.DNSName(u"cryptography.io"), ]) ]) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_add_extensions(self, backend, extension): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date).add_extension( extension, False) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == serial_number assert revoked_certificate.revocation_date == revocation_date assert len(revoked_certificate.extensions) == 1 ext = revoked_certificate.extensions.get_extension_for_class( type(extension)) assert ext.critical is False assert ext.value == extension @pytest.mark.requires_backend_interface(interface=X509Backend) def test_add_multiple_extensions(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) invalidity_date = x509.InvalidityDate( datetime.datetime(2015, 1, 1, 0, 0)) certificate_issuer = x509.CertificateIssuer([ x509.DNSName(u"cryptography.io"), ]) crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise) builder = x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date).add_extension( invalidity_date, True).add_extension(crl_reason, True).add_extension( certificate_issuer, True) revoked_certificate = builder.build(backend) assert len(revoked_certificate.extensions) == 3 for ext_data in [invalidity_date, certificate_issuer, crl_reason]: ext = revoked_certificate.extensions.get_extension_for_class( type(ext_data)) assert ext.critical is True assert ext.value == ext_data
class TestRevokedCertificateBuilder(object): def test_serial_number_must_be_integer(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().serial_number( "notanx509name" # type: ignore[arg-type] ) def test_serial_number_must_be_non_negative(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(-1) def test_serial_number_must_be_positive(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(0) def test_minimal_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = (x509.RevokedCertificateBuilder().serial_number( 1).revocation_date(revocation_date)) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == 1 def test_biggest_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = (x509.RevokedCertificateBuilder().serial_number( (1 << 159) - 1).revocation_date(revocation_date)) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == (1 << 159) - 1 def test_serial_number_must_be_less_than_160_bits_long(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(1 << 159) def test_set_serial_number_twice(self): builder = x509.RevokedCertificateBuilder().serial_number(3) with pytest.raises(ValueError): builder.serial_number(4) def test_aware_revocation_date(self, backend): time = datetime.datetime(2012, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") time = tz.localize(time) utc_time = datetime.datetime(2012, 1, 17, 6, 43) serial_number = 333 builder = (x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(time)) revoked_certificate = builder.build(backend) assert revoked_certificate.revocation_date == utc_time def test_revocation_date_invalid(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().revocation_date( "notadatetime" # type: ignore[arg-type] ) def test_revocation_date_before_1950(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(1940, 8, 10)) def test_set_revocation_date_twice(self): builder = x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(2002, 1, 1, 12, 1)) with pytest.raises(ValueError): builder.revocation_date(datetime.datetime(2002, 1, 1, 12, 1)) def test_add_extension_checks_for_duplicates(self): builder = x509.RevokedCertificateBuilder().add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False) with pytest.raises(ValueError): builder.add_extension( x509.CRLReason(x509.ReasonFlags.ca_compromise), False) def test_add_invalid_extension(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().add_extension( "notanextension", False # type: ignore[arg-type] ) def test_no_serial_number(self, backend): builder = x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(2002, 1, 1, 12, 1)) with pytest.raises(ValueError): builder.build(backend) def test_no_revocation_date(self, backend): builder = x509.RevokedCertificateBuilder().serial_number(3) with pytest.raises(ValueError): builder.build(backend) def test_create_revoked(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = (x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date)) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == serial_number assert revoked_certificate.revocation_date == revocation_date assert len(revoked_certificate.extensions) == 0 @pytest.mark.parametrize( "extension", [ x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)), x509.CRLReason(x509.ReasonFlags.ca_compromise), x509.CertificateIssuer([x509.DNSName("cryptography.io")]), ], ) def test_add_extensions(self, backend, extension): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = (x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date).add_extension( extension, False)) revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == serial_number assert revoked_certificate.revocation_date == revocation_date assert len(revoked_certificate.extensions) == 1 ext = revoked_certificate.extensions.get_extension_for_class( type(extension)) assert ext.critical is False assert ext.value == extension def test_add_multiple_extensions(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) invalidity_date = x509.InvalidityDate( datetime.datetime(2015, 1, 1, 0, 0)) certificate_issuer = x509.CertificateIssuer( [x509.DNSName("cryptography.io")]) crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise) builder = (x509.RevokedCertificateBuilder().serial_number( serial_number).revocation_date(revocation_date).add_extension( invalidity_date, True).add_extension(crl_reason, True).add_extension( certificate_issuer, True)) revoked_certificate = builder.build(backend) assert len(revoked_certificate.extensions) == 3 for ext_data in [invalidity_date, certificate_issuer, crl_reason]: ext = revoked_certificate.extensions.get_extension_for_class( type(ext_data)) assert ext.critical is True assert ext.value == ext_data
def _get_revoked(self, serial): return x509.RevokedCertificateBuilder().serial_number( int(serial)).revocation_date( datetime.datetime.today()).add_extension( x509.CRLReason(x509.ReasonFlags.unspecified), critical=False).build(backend=backends.default_backend())