From 2eb4ed943feded29fb635e722784682bc232553d Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 11 Apr 2015 15:33:45 -0400 Subject: AuthorityKeyIdentifier support --- docs/x509.rst | 19 ++++++++++++++++++ src/cryptography/x509.py | 37 +++++++++++++++++++++++++++++++++++ tests/test_x509_ext.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/docs/x509.rst b/docs/x509.rst index e0e05b6b..932801bd 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -652,6 +652,25 @@ X.509 Extensions purposes indicated in the key usage extension. The object is iterable to obtain the list of :ref:`extended key usage OIDs `. +.. class:: AuthorityKeyIdentifier + + .. versionadded:: 0.9 + + The authority key identifier extension provides a means of identifying the + public key corresponding to the private key used to sign a certificate. + + .. attribute:: key_identifier + + :type: bytes + + .. attribute:: authority_cert_issuer + + :type: :class:`Name` or None + + .. attribute:: authority_cert_serial_number + + :type: int or None + .. class:: SubjectKeyIdentifier .. versionadded:: 0.9 diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 55b17460..cdc0e430 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -557,6 +557,43 @@ class SubjectAlternativeName(object): return "".format(self._general_names) +class AuthorityKeyIdentifier(object): + def __init__(self, key_identifier, authority_cert_issuer, + authority_cert_serial_number): + if authority_cert_issuer or authority_cert_serial_number: + if not authority_cert_issuer or not authority_cert_serial_number: + raise ValueError( + "authority_cert_issuer and authority_cert_serial_number " + "must both be present or both None" + ) + + if not isinstance(authority_cert_issuer, Name): + raise TypeError("authority_cert_issuer must be a Name") + + if not isinstance(authority_cert_serial_number, six.integer_types): + raise TypeError( + "authority_cert_serial_number must be an integer" + ) + + self._key_identifier = key_identifier + self._authority_cert_issuer = authority_cert_issuer + self._authority_cert_serial_number = authority_cert_serial_number + + def __repr__(self): + return ( + "".format(self) + ) + + key_identifier = utils.read_only_property("_key_identifier") + authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") + authority_cert_serial_number = utils.read_only_property( + "_authority_cert_serial_number" + ) + + OID_COMMON_NAME = ObjectIdentifier("2.5.4.3") OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6") OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7") diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 4811541f..8516a339 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -220,6 +220,57 @@ class TestSubjectKeyIdentifier(object): assert ski != object() +class TestAuthorityKeyIdentifier(object): + def test_authority_cert_issuer_not_name(self): + with pytest.raises(TypeError): + x509.AuthorityKeyIdentifier(b"identifier", "notname", 3) + + def test_authority_cert_serial_number_not_integer(self): + name = x509.Name([ + x509.NameAttribute(x509.ObjectIdentifier('oid'), 'value1'), + x509.NameAttribute(x509.ObjectIdentifier('oid2'), 'value2'), + ]) + with pytest.raises(TypeError): + x509.AuthorityKeyIdentifier(b"identifier", name, "notanint") + + def test_authority_issuer_none_serial_not_none(self): + with pytest.raises(ValueError): + x509.AuthorityKeyIdentifier(b"identifier", None, 3) + + def test_authority_issuer_not_none_serial_none(self): + name = x509.Name([ + x509.NameAttribute(x509.ObjectIdentifier('oid'), 'value1'), + x509.NameAttribute(x509.ObjectIdentifier('oid2'), 'value2'), + ]) + with pytest.raises(ValueError): + x509.AuthorityKeyIdentifier(b"identifier", name, None) + + def test_authority_cert_serial_and_issuer_none(self): + aki = x509.AuthorityKeyIdentifier(b"id", None, None) + assert aki.key_identifier == b"id" + assert aki.authority_cert_issuer is None + assert aki.authority_cert_serial_number is None + + def test_repr(self): + name = x509.Name([x509.NameAttribute(x509.OID_COMMON_NAME, 'myCN')]) + aki = x509.AuthorityKeyIdentifier(b"digest", name, 1234) + + if six.PY3: + assert repr(aki) == ( + ", value='myCN')>])>, authority_cer" + "t_serial_number=1234)>" + ) + else: + assert repr(aki) == ( + ", value='myCN')>])>, authority_cert_se" + "rial_number=1234)>" + ) + + class TestBasicConstraints(object): def test_ca_not_boolean(self): with pytest.raises(TypeError): -- cgit v1.2.3 From 9104b1d5a97c6a416fe9ef453523b0e067113420 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 18 Apr 2015 09:23:44 -0500 Subject: add more prose for AKI --- docs/x509.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/x509.rst b/docs/x509.rst index 932801bd..ade80763 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -663,14 +663,21 @@ X.509 Extensions :type: bytes + A value derived from the public key used to verify the certificate's + signature. + .. attribute:: authority_cert_issuer :type: :class:`Name` or None + The :class:`Name` of the issuer's issuer. + .. attribute:: authority_cert_serial_number :type: int or None + The serial number of the issuer's issuer. + .. class:: SubjectKeyIdentifier .. versionadded:: 0.9 -- cgit v1.2.3 From d729cd378ea55f8e59073c3c57e1deb2f04819bf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 18 Apr 2015 22:37:38 -0500 Subject: add more words --- docs/x509.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/x509.rst b/docs/x509.rst index ade80763..02c51dda 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -664,7 +664,8 @@ X.509 Extensions :type: bytes A value derived from the public key used to verify the certificate's - signature. + signature. See :rfc:`5280` section 4.2.1.2 for more details on the + recommended way to compute this value. .. attribute:: authority_cert_issuer -- cgit v1.2.3 From 8c8cd72bd9f55db65f56a829ac0acb646e966088 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Apr 2015 09:15:04 -0500 Subject: update doc language to point more strongly at rfc 5280 --- docs/x509.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/x509.rst b/docs/x509.rst index 02c51dda..d99fae64 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -658,14 +658,16 @@ X.509 Extensions The authority key identifier extension provides a means of identifying the public key corresponding to the private key used to sign a certificate. + This extension is typically used to assist in determining the appropriate + certificate chain. For more information about generation and use of this + extension see `RFC 5280 section 4.2.1.1`_. .. attribute:: key_identifier :type: bytes A value derived from the public key used to verify the certificate's - signature. See :rfc:`5280` section 4.2.1.2 for more details on the - recommended way to compute this value. + signature. .. attribute:: authority_cert_issuer @@ -965,3 +967,4 @@ Exceptions .. _`public key infrastructure`: https://en.wikipedia.org/wiki/Public_key_infrastructure .. _`TLS`: https://en.wikipedia.org/wiki/Transport_Layer_Security +.. _`RFC 5280 section 4.2.1.1`: http://tools.ietf.org/html/rfc5280#section-4.2.1.1 -- cgit v1.2.3 From c7c9a43d39c0018b0e32e43f9c523dc768b462e9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Apr 2015 09:20:13 -0500 Subject: https --- docs/x509.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/x509.rst b/docs/x509.rst index d99fae64..da6bd85c 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -967,4 +967,4 @@ Exceptions .. _`public key infrastructure`: https://en.wikipedia.org/wiki/Public_key_infrastructure .. _`TLS`: https://en.wikipedia.org/wiki/Transport_Layer_Security -.. _`RFC 5280 section 4.2.1.1`: http://tools.ietf.org/html/rfc5280#section-4.2.1.1 +.. _`RFC 5280 section 4.2.1.1`: https://tools.ietf.org/html/rfc5280#section-4.2.1.1 -- cgit v1.2.3