From 56da2a50cd96e7214f4fdb254610bc19d8c0f255 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Feb 2015 23:35:07 -0600 Subject: add support for signature_algorithm in x509.Certificate --- docs/x509.rst | 84 ++++++++++++++++++++++++ src/cryptography/hazmat/backends/openssl/x509.py | 11 ++++ src/cryptography/hazmat/bindings/openssl/x509.py | 1 + src/cryptography/x509.py | 34 ++++++++++ tests/test_x509.py | 4 ++ 5 files changed, 134 insertions(+) diff --git a/docs/x509.rst b/docs/x509.rst index 0298d94d..8043b367 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -182,6 +182,18 @@ X.509 Certificate Object The :class:`Name` of the subject. + .. attribute:: signature_algorithm + + :type: :class:`ObjectIdentifier` + + An :class:`ObjectIdentifier` instance corresponding to the signature + algorithm used to sign the certificate. This is both the digest + used as well as the asymmetric type. + + .. doctest:: + + >>> cert.signature_algorithm + .. class:: Name @@ -266,6 +278,9 @@ Object Identifiers X.509 elements are frequently identified by :class:`ObjectIdentifier` instances. The following common OIDs are available as constants. +Name OIDs +~~~~~~~~~ + .. data:: OID_COMMON_NAME Corresponds to the dotted string ``"2.5.4.3"``. Historically the domain @@ -346,6 +361,75 @@ instances. The following common OIDs are available as constants. Corresponds to the dotted string ``"1.2.840.113549.1.9.1"``. This OID is typically seen in X.509 names. +Signature Algorithm OIDs +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. data:: OID_MD5_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.4"``. This is + an MD5 digest signed by an RSA key. + +.. data:: OID_SHA1_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.5"``. This is + a SHA1 digest signed by an RSA key. + +.. data:: OID_SHA224_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.14"``. This is + a SHA224 digest signed by an RSA key. + +.. data:: OID_SHA256_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.11"``. This is + a SHA256 digest signed by an RSA key. + +.. data:: OID_SHA384_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.12"``. This is + a SHA384 digest signed by an RSA key. + +.. data:: OID_SHA512_WITH_RSA + + Corresponds to the dotted string ``"1.2.840.113549.1.1.13"``. This is + a SHA512 digest signed by an RSA key. + +.. data:: OID_ECDSA_WITH_SHA224 + + Corresponds to the dotted string ``"1.2.840.10045.4.3.1"``. This is + a SHA224 digest signed by an ECDSA key. + +.. data:: OID_ECDSA_WITH_SHA256 + + Corresponds to the dotted string ``"1.2.840.10045.4.3.2"``. This is + a SHA256 digest signed by an ECDSA key. + +.. data:: OID_ECDSA_WITH_SHA384 + + Corresponds to the dotted string ``"1.2.840.10045.4.3.3"``. This is + a SHA384 digest signed by an ECDSA key. + +.. data:: OID_ECDSA_WITH_SHA512 + + Corresponds to the dotted string ``"1.2.840.10045.4.3.4"``. This is + a SHA512 digest signed by an ECDSA key. + +.. data:: OID_DSA_WITH_SHA1 + + Corresponds to the dotted string ``"1.2.840.10040.4.3"``. This is + a SHA1 digest signed by a DSA key. + +.. data:: OID_DSA_WITH_SHA224 + + Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.1"``. This is + a SHA224 digest signed by a DSA key. + +.. data:: OID_DSA_WITH_SHA256 + + Corresponds to the dotted string ``2.16.840.1.101.3.4.3.2"``. This is + a SHA256 digest signed by a DSA key. + + Exceptions ~~~~~~~~~~ diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 76dcf32f..a3dddc49 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -136,3 +136,14 @@ class _Certificate(object): ) return x509.Name(attributes) + + @property + def signature_algorithm(self): + buf_len = 50 + buf = self._backend._ffi.new("char[]", buf_len) + res = self._backend._lib.OBJ_obj2txt( + buf, buf_len, self._x509.sig_alg.algorithm, 1 + ) + assert res <= 50 and res > 0 + oid = self._backend._ffi.buffer(buf, res)[:].decode() + return x509.ObjectIdentifier(oid) diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/cryptography/hazmat/bindings/openssl/x509.py index e30d23b7..bf689e33 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509.py +++ b/src/cryptography/hazmat/bindings/openssl/x509.py @@ -65,6 +65,7 @@ typedef struct { } X509_CRL; typedef struct { + X509_ALGOR *sig_alg; X509_CINF *cert_info; ...; } X509; diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 8a888d2a..c4d87bb7 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -28,6 +28,19 @@ _OID_NAMES = { "2.5.4.65": "pseudonym", "0.9.2342.19200300.100.1.25": "domainComponent", "1.2.840.113549.1.9.1": "emailAddress", + "1.2.840.113549.1.1.4": "md5WithRSA", + "1.2.840.113549.1.1.5": "sha1WithRSA", + "1.2.840.113549.1.1.14": "sha224WithRSAEncryption", + "1.2.840.113549.1.1.11": "sha256WithRSAEncryption", + "1.2.840.113549.1.1.12": "sha384WithRSAEncryption", + "1.2.840.113549.1.1.13": "sha512WithRSAEncryption", + "1.2.840.10045.4.3.1": "ecdsa_with_SHA224", + "1.2.840.10045.4.3.2": "ecdsa_with_SHA256", + "1.2.840.10045.4.3.3": "ecdsa_with_SHA384", + "1.2.840.10045.4.3.4": "ecdsa_with_SHA512", + "1.2.840.10040.4.3": "dsaWithSHA1", + "2.16.840.1.101.3.4.3.1": "dsa_with_SHA224", + "2.16.840.1.101.3.4.3.2": "dsa_with_SHA256", } @@ -143,6 +156,20 @@ OID_PSEUDONYM = ObjectIdentifier("2.5.4.65") OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") +OID_MD5_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.4") +OID_SHA1_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.5") +OID_SHA224_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.14") +OID_SHA256_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.11") +OID_SHA384_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.12") +OID_SHA512_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.13") +OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") +OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") +OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") +OID_ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") +OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") +OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") +OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") + @six.add_metaclass(abc.ABCMeta) class Certificate(object): @@ -193,3 +220,10 @@ class Certificate(object): """ Returns the subject name object. """ + + @abc.abstractproperty + def signature_algorithm(self): + """ + Returns an ObjectIdentifier corresponding to the signature algorithm of + the certificate. + """ diff --git a/tests/test_x509.py b/tests/test_x509.py index 55a94084..613263d1 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -45,6 +45,7 @@ class TestRSACertificate(object): assert cert.serial == 11559813051657483483 fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) assert fingerprint == b"2b619ed04bfc9c3b08eb677d272192286a0947a8" + assert cert.signature_algorithm == x509.OID_SHA1_WITH_RSA def test_load_der_cert(self, backend): cert = _load_cert( @@ -56,6 +57,7 @@ class TestRSACertificate(object): assert cert.serial == 2 fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d" + assert cert.signature_algorithm == x509.OID_SHA256_WITH_RSA def test_issuer(self, backend): cert = _load_cert( @@ -338,6 +340,7 @@ class TestDSACertificate(object): x509.load_pem_x509_certificate, backend ) + assert cert.signature_algorithm == x509.OID_DSA_WITH_SHA1 public_key = cert.public_key() assert isinstance(public_key, interfaces.DSAPublicKey) if isinstance(public_key, interfaces.DSAPublicKeyWithNumbers): @@ -390,6 +393,7 @@ class TestECDSACertificate(object): x509.load_pem_x509_certificate, backend ) + assert cert.signature_algorithm == x509.OID_ECDSA_WITH_SHA384 public_key = cert.public_key() assert isinstance(public_key, interfaces.EllipticCurvePublicKey) if isinstance( -- cgit v1.2.3 From b0a803942a73382599424bb3d1353c8d5c8ecd1b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Feb 2015 23:39:49 -0600 Subject: add changelog entry --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a25ec6db..df78acd3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,9 @@ Changelog * :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key` can now load elliptic curve public keys. +* Added + :attr:`~cryptography.x509.Certificate.signature_algorithm` support to + :class:`~cryptography.x509.Certificate`. * Added :func:`~cryptography.hazmat.primitives.asymmetric.rsa.rsa_recover_prime_factors` * :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` and -- cgit v1.2.3 From b01622d15441068324af7ac68e1a1e26a4757704 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 11:59:15 -0600 Subject: add legacy Verisign PCA (MD2) root to vectors --- docs/development/test-vectors.rst | 2 ++ vectors/cryptography_vectors/x509/verisign_md2_root.pem | 14 ++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/verisign_md2_root.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 4c048abf..be98c6f1 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -80,6 +80,8 @@ X.509 * ``v1_cert.pem`` from the OpenSSL source tree (`testx509.pem`_). * ``ecdsa_root.pem`` - `DigiCert Global Root G3`_, a ``secp384r1`` ECDSA root certificate. +* ``verisign-md2-root.pem`` - A legacy Verisign public root signed using the + MD2 algorithm. Custom X.509 Vectors ~~~~~~~~~~~~~~~~~~~~ diff --git a/vectors/cryptography_vectors/x509/verisign_md2_root.pem b/vectors/cryptography_vectors/x509/verisign_md2_root.pem new file mode 100644 index 00000000..87676acf --- /dev/null +++ b/vectors/cryptography_vectors/x509/verisign_md2_root.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- -- cgit v1.2.3 From 8802a5bae7138d10c289361e5204fb1ea72fc099 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 12:06:57 -0600 Subject: implement signature_hash_algorithm instead --- CHANGELOG.rst | 2 +- docs/spelling_wordlist.txt | 1 + docs/x509.rst | 15 ++++++++------- src/cryptography/hazmat/backends/openssl/x509.py | 12 +++++++++++- src/cryptography/x509.py | 23 ++++++++++++++++++++--- tests/test_x509.py | 18 ++++++++++++++---- 6 files changed, 55 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index df78acd3..f903b7f9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,7 +9,7 @@ Changelog * :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key` can now load elliptic curve public keys. * Added - :attr:`~cryptography.x509.Certificate.signature_algorithm` support to + :attr:`~cryptography.x509.Certificate.signature_hash_algorithm` support to :class:`~cryptography.x509.Certificate`. * Added :func:`~cryptography.hazmat.primitives.asymmetric.rsa.rsa_recover_prime_factors` diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index fefd26b3..ddd37897 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -51,3 +51,4 @@ Ubuntu unencrypted unpadded unpadding +Verisign diff --git a/docs/x509.rst b/docs/x509.rst index 8043b367..193b8452 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -182,18 +182,19 @@ X.509 Certificate Object The :class:`Name` of the subject. - .. attribute:: signature_algorithm + .. attribute:: signature_hash_algorithm - :type: :class:`ObjectIdentifier` + :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - An :class:`ObjectIdentifier` instance corresponding to the signature - algorithm used to sign the certificate. This is both the digest - used as well as the asymmetric type. + A :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` + corresponding to the hash algorithm used within the certificate + signature. .. doctest:: - >>> cert.signature_algorithm - + >>> from cryptography.hazmat.primitives import hashes + >>> isinstance(cert.signature_hash_algorithm, hashes.SHA256) + True .. class:: Name diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index a3dddc49..989a9dd7 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -16,6 +16,7 @@ from __future__ import absolute_import, division, print_function import datetime from cryptography import utils, x509 +from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import hashes @@ -138,7 +139,16 @@ class _Certificate(object): return x509.Name(attributes) @property - def signature_algorithm(self): + def signature_hash_algorithm(self): + oid = self._signature_algorithm() + try: + return x509._SIG_OIDS_TO_HASH[oid.dotted_string] + except KeyError: + raise UnsupportedAlgorithm( + "Signature algorithm {0} not recognized".format(oid) + ) + + def _signature_algorithm(self): buf_len = 50 buf = self._backend._ffi.new("char[]", buf_len) res = self._backend._lib.OBJ_obj2txt( diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index c4d87bb7..c6ce61d1 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -10,6 +10,7 @@ from enum import Enum import six from cryptography import utils +from cryptography.hazmat.primitives import hashes _OID_NAMES = { @@ -170,6 +171,22 @@ OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") +_SIG_OIDS_TO_HASH = { + "1.2.840.113549.1.1.4": hashes.MD5(), + "1.2.840.113549.1.1.5": hashes.SHA1(), + "1.2.840.113549.1.1.14": hashes.SHA224(), + "1.2.840.113549.1.1.11": hashes.SHA256(), + "1.2.840.113549.1.1.12": hashes.SHA384(), + "1.2.840.113549.1.1.13": hashes.SHA512(), + "1.2.840.10045.4.3.1": hashes.SHA224(), + "1.2.840.10045.4.3.2": hashes.SHA256(), + "1.2.840.10045.4.3.3": hashes.SHA384(), + "1.2.840.10045.4.3.4": hashes.SHA512(), + "1.2.840.10040.4.3": hashes.SHA1(), + "2.16.840.1.101.3.4.3.1": hashes.SHA224(), + "2.16.840.1.101.3.4.3.2": hashes.SHA256() +} + @six.add_metaclass(abc.ABCMeta) class Certificate(object): @@ -222,8 +239,8 @@ class Certificate(object): """ @abc.abstractproperty - def signature_algorithm(self): + def signature_hash_algorithm(self): """ - Returns an ObjectIdentifier corresponding to the signature algorithm of - the certificate. + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. """ diff --git a/tests/test_x509.py b/tests/test_x509.py index 613263d1..8f00eeed 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -13,6 +13,7 @@ import pytest import six from cryptography import x509 +from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.interfaces import ( DSABackend, EllipticCurveBackend, RSABackend, X509Backend ) @@ -45,7 +46,7 @@ class TestRSACertificate(object): assert cert.serial == 11559813051657483483 fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) assert fingerprint == b"2b619ed04bfc9c3b08eb677d272192286a0947a8" - assert cert.signature_algorithm == x509.OID_SHA1_WITH_RSA + assert isinstance(cert.signature_hash_algorithm, hashes.SHA1) def test_load_der_cert(self, backend): cert = _load_cert( @@ -57,7 +58,7 @@ class TestRSACertificate(object): assert cert.serial == 2 fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d" - assert cert.signature_algorithm == x509.OID_SHA256_WITH_RSA + assert isinstance(cert.signature_hash_algorithm, hashes.SHA256) def test_issuer(self, backend): cert = _load_cert( @@ -330,6 +331,15 @@ class TestRSACertificate(object): with pytest.raises(ValueError): x509.load_der_x509_certificate(b"notacert", backend) + def test_unsupported_signature_hash_algorithm_cert(self, backend): + cert = _load_cert( + os.path.join("x509", "verisign_md2_root.pem"), + x509.load_pem_x509_certificate, + backend + ) + with pytest.raises(UnsupportedAlgorithm): + cert.signature_hash_algorithm + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) @@ -340,7 +350,7 @@ class TestDSACertificate(object): x509.load_pem_x509_certificate, backend ) - assert cert.signature_algorithm == x509.OID_DSA_WITH_SHA1 + assert isinstance(cert.signature_hash_algorithm, hashes.SHA1) public_key = cert.public_key() assert isinstance(public_key, interfaces.DSAPublicKey) if isinstance(public_key, interfaces.DSAPublicKeyWithNumbers): @@ -393,7 +403,7 @@ class TestECDSACertificate(object): x509.load_pem_x509_certificate, backend ) - assert cert.signature_algorithm == x509.OID_ECDSA_WITH_SHA384 + assert isinstance(cert.signature_hash_algorithm, hashes.SHA384) public_key = cert.public_key() assert isinstance(public_key, interfaces.EllipticCurvePublicKey) if isinstance( -- cgit v1.2.3 From 42a87cbde14c23b2f10af665c6977697a1d0c034 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 18:53:24 -0600 Subject: address review feedback --- src/cryptography/hazmat/backends/openssl/x509.py | 16 ++++++--------- src/cryptography/x509.py | 26 ++++++++++++------------ 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 989a9dd7..c69e9148 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -140,15 +140,6 @@ class _Certificate(object): @property def signature_hash_algorithm(self): - oid = self._signature_algorithm() - try: - return x509._SIG_OIDS_TO_HASH[oid.dotted_string] - except KeyError: - raise UnsupportedAlgorithm( - "Signature algorithm {0} not recognized".format(oid) - ) - - def _signature_algorithm(self): buf_len = 50 buf = self._backend._ffi.new("char[]", buf_len) res = self._backend._lib.OBJ_obj2txt( @@ -156,4 +147,9 @@ class _Certificate(object): ) assert res <= 50 and res > 0 oid = self._backend._ffi.buffer(buf, res)[:].decode() - return x509.ObjectIdentifier(oid) + try: + return x509._SIG_OIDS_TO_HASH[oid] + except KeyError: + raise UnsupportedAlgorithm( + "Signature algorithm OID:{0} not recognized".format(oid) + ) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index c6ce61d1..0273ca86 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -172,19 +172,19 @@ OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") _SIG_OIDS_TO_HASH = { - "1.2.840.113549.1.1.4": hashes.MD5(), - "1.2.840.113549.1.1.5": hashes.SHA1(), - "1.2.840.113549.1.1.14": hashes.SHA224(), - "1.2.840.113549.1.1.11": hashes.SHA256(), - "1.2.840.113549.1.1.12": hashes.SHA384(), - "1.2.840.113549.1.1.13": hashes.SHA512(), - "1.2.840.10045.4.3.1": hashes.SHA224(), - "1.2.840.10045.4.3.2": hashes.SHA256(), - "1.2.840.10045.4.3.3": hashes.SHA384(), - "1.2.840.10045.4.3.4": hashes.SHA512(), - "1.2.840.10040.4.3": hashes.SHA1(), - "2.16.840.1.101.3.4.3.1": hashes.SHA224(), - "2.16.840.1.101.3.4.3.2": hashes.SHA256() + OID_MD5_WITH_RSA.dotted_string: hashes.MD5(), + OID_SHA1_WITH_RSA.dotted_string: hashes.SHA1(), + OID_SHA224_WITH_RSA.dotted_string: hashes.SHA224(), + OID_SHA256_WITH_RSA.dotted_string: hashes.SHA256(), + OID_SHA384_WITH_RSA.dotted_string: hashes.SHA384(), + OID_SHA512_WITH_RSA.dotted_string: hashes.SHA512(), + OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(), + OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(), + OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(), + OID_ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(), + OID_DSA_WITH_SHA1.dotted_string: hashes.SHA1(), + OID_DSA_WITH_SHA224.dotted_string: hashes.SHA224(), + OID_DSA_WITH_SHA256.dotted_string: hashes.SHA256() } -- cgit v1.2.3 From 2e776e20eb60378e0af9b7439000d0e80da7c7e3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 19:18:03 -0600 Subject: refactor obj2txt to be a separate method --- src/cryptography/hazmat/backends/openssl/x509.py | 26 ++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index c69e9148..b712f1f9 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -122,14 +122,7 @@ class _Certificate(object): buf, lambda buf: self._backend._lib.OPENSSL_free(buf[0]) ) value = self._backend._ffi.buffer(buf[0], res)[:].decode('utf8') - # Set to 80 on the recommendation of - # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html - buf_len = 80 - buf = self._backend._ffi.new("char[]", buf_len) - res = self._backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) - assert res > 0 - oid = self._backend._ffi.buffer(buf, res)[:].decode() - + oid = self._obj2txt(obj) attributes.append( x509.NameAttribute( x509.ObjectIdentifier(oid), value @@ -138,15 +131,18 @@ class _Certificate(object): return x509.Name(attributes) + def _obj2txt(self, obj): + # Set to 80 on the recommendation of + # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values + buf_len = 80 + buf = self._backend._ffi.new("char[]", buf_len) + res = self._backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) + assert res > 0 + return self._backend._ffi.buffer(buf, res)[:].decode() + @property def signature_hash_algorithm(self): - buf_len = 50 - buf = self._backend._ffi.new("char[]", buf_len) - res = self._backend._lib.OBJ_obj2txt( - buf, buf_len, self._x509.sig_alg.algorithm, 1 - ) - assert res <= 50 and res > 0 - oid = self._backend._ffi.buffer(buf, res)[:].decode() + oid = self._obj2txt(self._x509.sig_alg.algorithm) try: return x509._SIG_OIDS_TO_HASH[oid] except KeyError: -- cgit v1.2.3 From 2b6ba0c633ef672a6d8ef2ca109d3ffd508e044e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 14 Feb 2015 18:58:20 -0600 Subject: document vector provenance --- docs/development/test-vectors.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index be98c6f1..2cd9faa6 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -81,7 +81,8 @@ X.509 * ``ecdsa_root.pem`` - `DigiCert Global Root G3`_, a ``secp384r1`` ECDSA root certificate. * ``verisign-md2-root.pem`` - A legacy Verisign public root signed using the - MD2 algorithm. + MD2 algorithm. This is a PEM conversion of the `root data`_ in the NSS source + tree. Custom X.509 Vectors ~~~~~~~~~~~~~~~~~~~~ @@ -221,3 +222,4 @@ header format (substituting the correct information): .. _`NIST PKI Testing`: http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html .. _`testx509.pem`: https://github.com/openssl/openssl/blob/master/test/testx509.pem .. _`DigiCert Global Root G3`: http://cacerts.digicert.com/DigiCertGlobalRootG3.crt +.. _`root data`: https://hg.mozilla.org/projects/nss/file/25b2922cc564/security/nss/lib/ckfw/builtins/certdata.txt#l2053 -- cgit v1.2.3 From e612ec74f68f344ee4bde5d6e377ffc03cdb1ec6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 16 Feb 2015 14:33:35 -0600 Subject: try to make this a bit more clear --- docs/x509.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/x509.rst b/docs/x509.rst index 193b8452..e16e79e9 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -186,9 +186,9 @@ X.509 Certificate Object :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - A :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - corresponding to the hash algorithm used within the certificate - signature. + Returns the + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` used in + the signature. .. doctest:: -- cgit v1.2.3 From e19201e6250cf0f60bbf2362938294ab7c533d3b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 16 Feb 2015 18:05:20 -0600 Subject: attempt to clarify signature hash algorithm a bit more --- docs/x509.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/x509.rst b/docs/x509.rst index e16e79e9..262ba301 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -188,7 +188,11 @@ X.509 Certificate Object Returns the :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` used in - the signature. + the certificate's signature. + + .. note:: + Items signed by the parsed certificate do not have to use the same + hash algorithm. .. doctest:: -- cgit v1.2.3 From 71d40c6af6c70f38da3bf1f65c8b8f16ae7d567e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 19 Feb 2015 08:21:04 -0600 Subject: address review feedback, fix short names for sig alg OIDs --- docs/x509.rst | 20 ++++++++------------ src/cryptography/x509.py | 42 +++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/docs/x509.rst b/docs/x509.rst index 262ba301..a3426a2b 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -187,12 +187,8 @@ X.509 Certificate Object :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` Returns the - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` used in - the certificate's signature. - - .. note:: - Items signed by the parsed certificate do not have to use the same - hash algorithm. + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which + was used in signing the certificate. .. doctest:: @@ -369,32 +365,32 @@ Name OIDs Signature Algorithm OIDs ~~~~~~~~~~~~~~~~~~~~~~~~ -.. data:: OID_MD5_WITH_RSA +.. data:: OID_MD5_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.4"``. This is an MD5 digest signed by an RSA key. -.. data:: OID_SHA1_WITH_RSA +.. data:: OID_SHA1_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.5"``. This is a SHA1 digest signed by an RSA key. -.. data:: OID_SHA224_WITH_RSA +.. data:: OID_SHA224_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.14"``. This is a SHA224 digest signed by an RSA key. -.. data:: OID_SHA256_WITH_RSA +.. data:: OID_SHA256_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.11"``. This is a SHA256 digest signed by an RSA key. -.. data:: OID_SHA384_WITH_RSA +.. data:: OID_SHA384_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.12"``. This is a SHA384 digest signed by an RSA key. -.. data:: OID_SHA512_WITH_RSA +.. data:: OID_SHA512_WITH_RSA_ENCRYPTION Corresponds to the dotted string ``"1.2.840.113549.1.1.13"``. This is a SHA512 digest signed by an RSA key. diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 0273ca86..774830df 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -29,19 +29,19 @@ _OID_NAMES = { "2.5.4.65": "pseudonym", "0.9.2342.19200300.100.1.25": "domainComponent", "1.2.840.113549.1.9.1": "emailAddress", - "1.2.840.113549.1.1.4": "md5WithRSA", - "1.2.840.113549.1.1.5": "sha1WithRSA", + "1.2.840.113549.1.1.4": "md5WithRSAEncryption", + "1.2.840.113549.1.1.5": "sha1WithRSAEncryption", "1.2.840.113549.1.1.14": "sha224WithRSAEncryption", "1.2.840.113549.1.1.11": "sha256WithRSAEncryption", "1.2.840.113549.1.1.12": "sha384WithRSAEncryption", "1.2.840.113549.1.1.13": "sha512WithRSAEncryption", - "1.2.840.10045.4.3.1": "ecdsa_with_SHA224", - "1.2.840.10045.4.3.2": "ecdsa_with_SHA256", - "1.2.840.10045.4.3.3": "ecdsa_with_SHA384", - "1.2.840.10045.4.3.4": "ecdsa_with_SHA512", - "1.2.840.10040.4.3": "dsaWithSHA1", - "2.16.840.1.101.3.4.3.1": "dsa_with_SHA224", - "2.16.840.1.101.3.4.3.2": "dsa_with_SHA256", + "1.2.840.10045.4.3.1": "ecdsa-with-SHA224", + "1.2.840.10045.4.3.2": "ecdsa-with-SHA256", + "1.2.840.10045.4.3.3": "ecdsa-with-SHA384", + "1.2.840.10045.4.3.4": "ecdsa-with-SHA512", + "1.2.840.10040.4.3": "dsa-with-sha1", + "2.16.840.1.101.3.4.3.1": "dsa-with-sha224", + "2.16.840.1.101.3.4.3.2": "dsa-with-sha256", } @@ -157,12 +157,12 @@ OID_PSEUDONYM = ObjectIdentifier("2.5.4.65") OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") -OID_MD5_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.4") -OID_SHA1_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.5") -OID_SHA224_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.14") -OID_SHA256_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.11") -OID_SHA384_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.12") -OID_SHA512_WITH_RSA = ObjectIdentifier("1.2.840.113549.1.1.13") +OID_MD5_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.4") +OID_SHA1_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.5") +OID_SHA224_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.14") +OID_SHA256_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.11") +OID_SHA384_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.12") +OID_SHA512_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.13") OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") @@ -172,12 +172,12 @@ OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") _SIG_OIDS_TO_HASH = { - OID_MD5_WITH_RSA.dotted_string: hashes.MD5(), - OID_SHA1_WITH_RSA.dotted_string: hashes.SHA1(), - OID_SHA224_WITH_RSA.dotted_string: hashes.SHA224(), - OID_SHA256_WITH_RSA.dotted_string: hashes.SHA256(), - OID_SHA384_WITH_RSA.dotted_string: hashes.SHA384(), - OID_SHA512_WITH_RSA.dotted_string: hashes.SHA512(), + OID_MD5_WITH_RSA_ENCRYPTION.dotted_string: hashes.MD5(), + OID_SHA1_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA1(), + OID_SHA224_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA224(), + OID_SHA256_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA256(), + OID_SHA384_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA384(), + OID_SHA512_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA512(), OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(), OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(), OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(), -- cgit v1.2.3 From 1a7ba87dcc9c44178c9dae3351484707730d6a18 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 19 Feb 2015 18:09:05 -0600 Subject: surrender to alex's feels and name our constants consistently --- docs/x509.rst | 14 +++++++------- src/cryptography/x509.py | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/x509.rst b/docs/x509.rst index a3426a2b..27f1d544 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -188,7 +188,7 @@ X.509 Certificate Object Returns the :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which - was used in signing the certificate. + was used in signing this certificate. .. doctest:: @@ -365,32 +365,32 @@ Name OIDs Signature Algorithm OIDs ~~~~~~~~~~~~~~~~~~~~~~~~ -.. data:: OID_MD5_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_MD5 Corresponds to the dotted string ``"1.2.840.113549.1.1.4"``. This is an MD5 digest signed by an RSA key. -.. data:: OID_SHA1_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_SHA1 Corresponds to the dotted string ``"1.2.840.113549.1.1.5"``. This is a SHA1 digest signed by an RSA key. -.. data:: OID_SHA224_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_SHA224 Corresponds to the dotted string ``"1.2.840.113549.1.1.14"``. This is a SHA224 digest signed by an RSA key. -.. data:: OID_SHA256_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_SHA256 Corresponds to the dotted string ``"1.2.840.113549.1.1.11"``. This is a SHA256 digest signed by an RSA key. -.. data:: OID_SHA384_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_SHA384 Corresponds to the dotted string ``"1.2.840.113549.1.1.12"``. This is a SHA384 digest signed by an RSA key. -.. data:: OID_SHA512_WITH_RSA_ENCRYPTION +.. data:: OID_RSA_WITH_SHA512 Corresponds to the dotted string ``"1.2.840.113549.1.1.13"``. This is a SHA512 digest signed by an RSA key. diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 774830df..a46367ed 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -157,12 +157,12 @@ OID_PSEUDONYM = ObjectIdentifier("2.5.4.65") OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") -OID_MD5_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.4") -OID_SHA1_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.5") -OID_SHA224_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.14") -OID_SHA256_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.11") -OID_SHA384_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.12") -OID_SHA512_WITH_RSA_ENCRYPTION = ObjectIdentifier("1.2.840.113549.1.1.13") +OID_RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") +OID_RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") +OID_RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") +OID_RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") +OID_RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") +OID_RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") @@ -172,12 +172,12 @@ OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") _SIG_OIDS_TO_HASH = { - OID_MD5_WITH_RSA_ENCRYPTION.dotted_string: hashes.MD5(), - OID_SHA1_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA1(), - OID_SHA224_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA224(), - OID_SHA256_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA256(), - OID_SHA384_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA384(), - OID_SHA512_WITH_RSA_ENCRYPTION.dotted_string: hashes.SHA512(), + OID_RSA_WITH_MD5.dotted_string: hashes.MD5(), + OID_RSA_WITH_SHA1.dotted_string: hashes.SHA1(), + OID_RSA_WITH_SHA224.dotted_string: hashes.SHA224(), + OID_RSA_WITH_SHA256.dotted_string: hashes.SHA256(), + OID_RSA_WITH_SHA384.dotted_string: hashes.SHA384(), + OID_RSA_WITH_SHA512.dotted_string: hashes.SHA512(), OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(), OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(), OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(), -- cgit v1.2.3