From 3b95cd7f563809c136205c0642b4d54395e6b2eb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 22 Dec 2015 21:40:20 -0600 Subject: CRLNumber needs to be a class for reasons. --- CHANGELOG.rst | 2 +- docs/x509/reference.rst | 21 ++++++++++++++++++++ src/cryptography/hazmat/backends/openssl/x509.py | 2 +- src/cryptography/x509/__init__.py | 3 ++- src/cryptography/x509/extensions.py | 25 ++++++++++++++++++++++++ tests/test_x509.py | 2 +- tests/test_x509_ext.py | 15 ++++++++++++++ 7 files changed, 66 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3dc5249c..3e24633e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,7 +29,7 @@ Changelog * :class:`~cryptography.x509.AuthorityInformationAccess` * :class:`~cryptography.x509.AuthorityKeyIdentifier` - * ``CRLNumber`` + * :class:`~cryptography.x509.CRLNumber` * :class:`~cryptography.x509.IssuerAlternativeName` 1.1.2 - 2015-12-10 diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index dace8c1b..f53eae0a 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1695,6 +1695,27 @@ X.509 Extensions :type: int +.. class:: CRLNumber(crl_number) + + .. versionadded:: 1.2 + + The CRL number is a non-critical CRL extension that conveys a + monotonically increasing sequence number for a given CRL scope and + CRL issuer. This extension allows users to easily determine when a + particular CRL supersedes another CRL. :rfc:`5280` requires that this + extension be present in conforming CRLs. + + .. attribute:: oid + + :type: :class:`ObjectIdentifier` + + Returns + :attr:`~cryptography.x509.oid.ExtensionOID.CRL_NUMBER`. + + .. attribute:: crl_number + + :type: int + .. class:: CertificatePolicies(policies) .. versionadded:: 0.9 diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 45c0df50..7e89ac67 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -182,7 +182,7 @@ def _decode_ocsp_no_check(backend, ext): def _decode_crl_number(backend, ext): asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) - return backend._asn1_integer_to_int(asn1_int) + return x509.CRLNumber(backend._asn1_integer_to_int(asn1_int)) class _X509ExtensionParser(object): diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 70e1d3da..c4434fd1 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -14,7 +14,7 @@ from cryptography.x509.base import ( from cryptography.x509.extensions import ( AccessDescription, AuthorityInformationAccess, AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints, - CertificatePolicies, DistributionPoint, DuplicateExtension, + CRLNumber, CertificatePolicies, DistributionPoint, DuplicateExtension, ExtendedKeyUsage, Extension, ExtensionNotFound, ExtensionType, Extensions, GeneralNames, InhibitAnyPolicy, IssuerAlternativeName, KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, PolicyInformation, @@ -124,6 +124,7 @@ __all__ = [ "ExtendedKeyUsage", "OCSPNoCheck", "BasicConstraints", + "CRLNumber", "KeyUsage", "AuthorityInformationAccess", "AccessDescription", diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 71ce8a15..15feb717 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -108,6 +108,31 @@ class Extensions(object): ) +@utils.register_interface(ExtensionType) +class CRLNumber(object): + oid = ExtensionOID.CRL_NUMBER + + def __init__(self, crl_number): + if not isinstance(crl_number, six.integer_types): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + def __eq__(self, other): + if not isinstance(other, CRLNumber): + return NotImplemented + + return self.crl_number == other.crl_number + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return "".format(self.crl_number) + + crl_number = utils.read_only_property("_crl_number") + + @utils.register_interface(ExtensionType) class AuthorityKeyIdentifier(object): oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER diff --git a/tests/test_x509.py b/tests/test_x509.py index b39e1891..ae2746e3 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -192,7 +192,7 @@ class TestCertificateRevocationList(object): ian = crl.extensions.get_extension_for_class( x509.IssuerAlternativeName ) - assert crl_number.value == 1 + assert crl_number.value == x509.CRLNumber(1) assert crl_number.critical is False assert aki.value == x509.AuthorityKeyIdentifier( key_identifier=( diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 83145cd0..4b1d6a5a 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -1488,6 +1488,21 @@ class TestRSAIssuerAlternativeNameExtension(object): ] +class TestCRLNumber(object): + def test_eq(self): + crl_number = x509.CRLNumber(15) + assert crl_number == x509.CRLNumber(15) + + def test_ne(self): + crl_number = x509.CRLNumber(15) + assert crl_number != x509.CRLNumber(14) + assert crl_number != object() + + def test_repr(self): + crl_number = x509.CRLNumber(15) + assert repr(crl_number) == "" + + class TestSubjectAlternativeName(object): def test_get_values_for_type(self): san = x509.SubjectAlternativeName( -- cgit v1.2.3 From e32b994e73449f2c709298378de89467b30dbf21 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 22 Dec 2015 22:26:53 -0600 Subject: update the language --- docs/x509/reference.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index f53eae0a..4f4ce4fa 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1699,11 +1699,10 @@ X.509 Extensions .. versionadded:: 1.2 - The CRL number is a non-critical CRL extension that conveys a - monotonically increasing sequence number for a given CRL scope and - CRL issuer. This extension allows users to easily determine when a - particular CRL supersedes another CRL. :rfc:`5280` requires that this - extension be present in conforming CRLs. + The CRL number is a CRL extension that conveys a monotonically increasing + sequence number for a given CRL scope and CRL issuer. This extension allows + users to easily determine when a particular CRL supersedes another CRL. + :rfc:`5280` requires that this extension be present in conforming CRLs. .. attribute:: oid -- cgit v1.2.3 From a9718fce3687a6a787ae8a03b989580dc68be260 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 22 Dec 2015 22:55:35 -0600 Subject: missed a test for CRLNumber not being an integer, oops --- tests/test_x509_ext.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 4b1d6a5a..d9743c8e 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -1502,6 +1502,10 @@ class TestCRLNumber(object): crl_number = x509.CRLNumber(15) assert repr(crl_number) == "" + def test_invalid_number(self): + with pytest.raises(TypeError): + x509.CRLNumber("notanumber") + class TestSubjectAlternativeName(object): def test_get_values_for_type(self): -- cgit v1.2.3