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 _decode_cert_issuer(backend, ext): """ This handler decodes the CertificateIssuer entry extension directly from the X509_EXTENSION object. This is necessary because this entry extension is not directly supported by OpenSSL 0.9.8. """ data_ptr_ptr = backend._ffi.new("const unsigned char **") value = backend._lib.X509_EXTENSION_get_data(ext) data_ptr_ptr[0] = value.data gns = backend._lib.d2i_GENERAL_NAMES( backend._ffi.NULL, data_ptr_ptr, value.length ) # Check the result of d2i_GENERAL_NAMES() is valid. Usually this is covered # in _X509ExtensionParser but since we are responsible for decoding this # entry extension ourselves, we have to this here. if gns == backend._ffi.NULL: backend._consume_errors() raise ValueError( "The {0} extension is corrupted and can't be parsed".format( CRLEntryExtensionOID.CERTIFICATE_ISSUER)) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) return x509.CertificateIssuer(_decode_general_names(backend, gns))
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 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 _decode_cert_issuer(backend, gns): gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) general_names = _decode_general_names(backend, gns) return x509.CertificateIssuer(general_names)
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