add support for signature_algorithm_oid to cert, CSR, and CRL (#3124)

* add support for signature_algorithm_oid to cert, CSR, and CRL

* refactor _SIG_OIDS_TO_HASH to use ObjectIdentifiers and use that
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fabc913..4ec7d72 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,6 +11,15 @@
 * Added support for :class:`~cryptography.hazmat.primitives.hashes.BLAKE2b` and
   :class:`~cryptography.hazmat.primitives.hashes.BLAKE2s` when using OpenSSL
   1.1.0.
+* Added
+  :attr:`~cryptography.x509.Certificate.signature_algorithm_oid` support to
+  :class:`~cryptography.x509.Certificate`.
+* Added
+  :attr:`~cryptography.x509.CertificateSigningRequest.signature_algorithm_oid`
+  support to :class:`~cryptography.x509.CertificateSigningRequest`.
+* Added
+  :attr:`~cryptography.x509.CertificateRevocationList.signature_algorithm_oid`
+  support to :class:`~cryptography.x509.CertificateRevocationList`.
 
 1.5 - 2016-08-26
 ~~~~~~~~~~~~~~~~
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index ea32c3b..bd88b02 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -354,6 +354,22 @@
             >>> isinstance(cert.signature_hash_algorithm, hashes.SHA256)
             True
 
+    .. attribute:: signature_algorithm_oid
+
+        .. versionadded:: 1.6
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns the :class:`ObjectIdentifier` of the signature algorithm used
+        to sign the certificate. This will be one of the OIDs from
+        :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+
+        .. doctest::
+
+            >>> cert.signature_algorithm_oid
+            <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
+
     .. attribute:: extensions
 
         :type: :class:`Extensions`
@@ -464,6 +480,21 @@
             >>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
             True
 
+    .. attribute:: signature_algorithm_oid
+
+        .. versionadded:: 1.6
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns the :class:`ObjectIdentifier` of the signature algorithm used
+        to sign the CRL. This will be one of the OIDs from
+        :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+        .. doctest::
+
+            >>> crl.signature_algorithm_oid
+            <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
+
     .. attribute:: issuer
 
         :type: :class:`Name`
@@ -711,6 +742,21 @@
             >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
             True
 
+    .. attribute:: signature_algorithm_oid
+
+        .. versionadded:: 1.6
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns the :class:`ObjectIdentifier` of the signature algorithm used
+        to sign the request. This will be one of the OIDs from
+        :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+        .. doctest::
+
+            >>> csr.signature_algorithm_oid
+            <ObjectIdentifier(oid=1.2.840.113549.1.1.5, name=sha1WithRSAEncryption)>
+
     .. attribute:: extensions
 
         :type: :class:`Extensions`
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 6f7270c..1f63d85 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -107,12 +107,7 @@
 
     @property
     def signature_hash_algorithm(self):
-        alg = self._backend._ffi.new("X509_ALGOR **")
-        self._backend._lib.X509_get0_signature(
-            self._backend._ffi.NULL, alg, self._x509
-        )
-        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
-        oid = _obj2txt(self._backend, alg[0].algorithm)
+        oid = self.signature_algorithm_oid
         try:
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
@@ -121,6 +116,16 @@
             )
 
     @property
+    def signature_algorithm_oid(self):
+        alg = self._backend._ffi.new("X509_ALGOR **")
+        self._backend._lib.X509_get0_signature(
+            self._backend._ffi.NULL, alg, self._x509
+        )
+        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+        oid = _obj2txt(self._backend, alg[0].algorithm)
+        return x509.ObjectIdentifier(oid)
+
+    @property
     def extensions(self):
         return _CERTIFICATE_EXTENSION_PARSER.parse(self._backend, self._x509)
 
@@ -223,12 +228,7 @@
 
     @property
     def signature_hash_algorithm(self):
-        alg = self._backend._ffi.new("X509_ALGOR **")
-        self._backend._lib.X509_CRL_get0_signature(
-            self._x509_crl, self._backend._ffi.NULL, alg
-        )
-        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
-        oid = _obj2txt(self._backend, alg[0].algorithm)
+        oid = self.signature_algorithm_oid
         try:
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
@@ -237,6 +237,16 @@
             )
 
     @property
+    def signature_algorithm_oid(self):
+        alg = self._backend._ffi.new("X509_ALGOR **")
+        self._backend._lib.X509_CRL_get0_signature(
+            self._x509_crl, self._backend._ffi.NULL, alg
+        )
+        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+        oid = _obj2txt(self._backend, alg[0].algorithm)
+        return x509.ObjectIdentifier(oid)
+
+    @property
     def issuer(self):
         issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl)
         self._backend.openssl_assert(issuer != self._backend._ffi.NULL)
@@ -355,12 +365,7 @@
 
     @property
     def signature_hash_algorithm(self):
-        alg = self._backend._ffi.new("X509_ALGOR **")
-        self._backend._lib.X509_REQ_get0_signature(
-            self._x509_req, self._backend._ffi.NULL, alg
-        )
-        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
-        oid = _obj2txt(self._backend, alg[0].algorithm)
+        oid = self.signature_algorithm_oid
         try:
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
@@ -369,6 +374,16 @@
             )
 
     @property
+    def signature_algorithm_oid(self):
+        alg = self._backend._ffi.new("X509_ALGOR **")
+        self._backend._lib.X509_REQ_get0_signature(
+            self._x509_req, self._backend._ffi.NULL, alg
+        )
+        self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+        oid = _obj2txt(self._backend, alg[0].algorithm)
+        return x509.ObjectIdentifier(oid)
+
+    @property
     def extensions(self):
         x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req)
         return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts)
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index 156bc49..498ccbb 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -126,6 +126,12 @@
         """
 
     @abc.abstractproperty
+    def signature_algorithm_oid(self):
+        """
+        Returns the ObjectIdentifier of the signature algorithm.
+        """
+
+    @abc.abstractproperty
     def extensions(self):
         """
         Returns an Extensions object.
@@ -190,6 +196,12 @@
         """
 
     @abc.abstractproperty
+    def signature_algorithm_oid(self):
+        """
+        Returns the ObjectIdentifier of the signature algorithm.
+        """
+
+    @abc.abstractproperty
     def issuer(self):
         """
         Returns the X509Name with the issuer of this CRL.
@@ -278,6 +290,12 @@
         """
 
     @abc.abstractproperty
+    def signature_algorithm_oid(self):
+        """
+        Returns the ObjectIdentifier of the signature algorithm.
+        """
+
+    @abc.abstractproperty
     def extensions(self):
         """
         Returns the extensions in the signing request.
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index 48e9d69..17fa42e 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -135,20 +135,20 @@
     DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
 
 _SIG_OIDS_TO_HASH = {
-    SignatureAlgorithmOID.RSA_WITH_MD5.dotted_string: hashes.MD5(),
-    SignatureAlgorithmOID.RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
-    SignatureAlgorithmOID.RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
-    SignatureAlgorithmOID.RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
-    SignatureAlgorithmOID.RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
-    SignatureAlgorithmOID.RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
-    SignatureAlgorithmOID.ECDSA_WITH_SHA1.dotted_string: hashes.SHA1(),
-    SignatureAlgorithmOID.ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
-    SignatureAlgorithmOID.ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
-    SignatureAlgorithmOID.ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
-    SignatureAlgorithmOID.ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
-    SignatureAlgorithmOID.DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
-    SignatureAlgorithmOID.DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
-    SignatureAlgorithmOID.DSA_WITH_SHA256.dotted_string: hashes.SHA256()
+    SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(),
+    SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(),
+    SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(),
+    SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(),
+    SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(),
+    SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(),
+    SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(),
+    SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(),
+    SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(),
+    SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(),
+    SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(),
+    SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(),
+    SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(),
+    SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256()
 }
 
 
diff --git a/tests/test_x509.py b/tests/test_x509.py
index e281579..dcfbe4f 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -31,7 +31,8 @@
     decode_dss_signature
 )
 from cryptography.x509.oid import (
-    AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID, NameOID
+    AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
+    NameOID, SignatureAlgorithmOID
 )
 
 from .hazmat.primitives.fixtures_dsa import DSA_KEY_2048
@@ -75,6 +76,10 @@
         fingerprint = binascii.hexlify(crl.fingerprint(hashes.SHA1()))
         assert fingerprint == b"3234b0cb4c0cedf6423724b736729dcfc9e441ef"
         assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
+        assert (
+            crl.signature_algorithm_oid ==
+            SignatureAlgorithmOID.RSA_WITH_SHA256
+        )
 
     def test_load_der_crl(self, backend):
         crl = _load_cert(
@@ -493,6 +498,9 @@
         fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
         assert fingerprint == b"2b619ed04bfc9c3b08eb677d272192286a0947a8"
         assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
+        assert (
+            cert.signature_algorithm_oid == SignatureAlgorithmOID.RSA_WITH_SHA1
+        )
 
     def test_cert_serial_number(self, backend):
         cert = _load_cert(
@@ -1053,6 +1061,10 @@
     def test_load_rsa_certificate_request(self, path, loader_func, backend):
         request = _load_cert(path, loader_func, backend)
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
+        assert (
+            request.signature_algorithm_oid ==
+            SignatureAlgorithmOID.RSA_WITH_SHA1
+        )
         public_key = request.public_key()
         assert isinstance(public_key, rsa.RSAPublicKey)
         subject = request.subject