Merge pull request #1612 from reaperhulk/x509-dn

X509 distinguished name parsing support in the OpenSSL backend
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index cee4a32..a25ec6d 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -10,6 +10,10 @@
   now load elliptic curve public keys.
 * Added
   :func:`~cryptography.hazmat.primitives.asymmetric.rsa.rsa_recover_prime_factors`
+* :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` and
+  :class:`~cryptography.hazmat.primitives.hashes.HashContext` were moved from
+  :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.hashes`.
 * :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`,
   :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParametersWithNumbers`,
   :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
@@ -102,11 +106,8 @@
   ``load_elliptic_curve_private_numbers`` and
   ``load_elliptic_curve_public_numbers`` on
   :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
-* Added
-  :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePrivateKeyWithNumbers`
-  and
-  :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePublicKeyWithNumbers`
-  support.
+* Added ``EllipticCurvePrivateKeyWithNumbers`` and
+  ``EllipticCurvePublicKeyWithNumbers`` support.
 * Work around three GCM related bugs in CommonCrypto and OpenSSL.
 
   * On the CommonCrypto backend adding AAD but not subsequently calling update
@@ -135,17 +136,15 @@
 0.5.2 - 2014-07-09
 ~~~~~~~~~~~~~~~~~~
 
-* Add
-  :class:`~cryptography.hazmat.backends.interfaces.TraditionalOpenSSLSerializationBackend`
-  support to :doc:`/hazmat/backends/multibackend`.
+* Add ``TraditionalOpenSSLSerializationBackend`` support to
+  :doc:`/hazmat/backends/multibackend`.
 * Fix compilation error on OS X 10.8 (Mountain Lion).
 
 0.5.1 - 2014-07-07
 ~~~~~~~~~~~~~~~~~~
 
-* Add
-  :class:`~cryptography.hazmat.backends.interfaces.PKCS8SerializationBackend`
-  support to :doc:`/hazmat/backends/multibackend`.
+* Add ``PKCS8SerializationBackend`` support to
+  :doc:`/hazmat/backends/multibackend`.
 
 0.5 - 2014-07-07
 ~~~~~~~~~~~~~~~~
@@ -166,36 +165,34 @@
   :doc:`/hazmat/backends/commoncrypto` and :doc:`/hazmat/backends/openssl`.
 * Added ``AES`` :class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`
   support to the OpenSSL backend when linked against 0.9.8.
-* Added
-  :class:`~cryptography.hazmat.backends.interfaces.PKCS8SerializationBackend`
-  and
-  :class:`~cryptography.hazmat.backends.interfaces.TraditionalOpenSSLSerializationBackend`
-  support to the :doc:`/hazmat/backends/openssl`.
+* Added ``PKCS8SerializationBackend`` and
+  ``TraditionalOpenSSLSerializationBackend`` support to the
+  :doc:`/hazmat/backends/openssl`.
 * Added :doc:`/hazmat/primitives/asymmetric/ec` and
   :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
 * Added :class:`~cryptography.hazmat.primitives.ciphers.modes.ECB` support
   for :class:`~cryptography.hazmat.primitives.ciphers.algorithms.TripleDES` on
   :doc:`/hazmat/backends/commoncrypto` and :doc:`/hazmat/backends/openssl`.
-* Deprecated
-  :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` in
-  favor of backend specific providers of the
-  :class:`~cryptography.hazmat.primitives.interfaces.RSAPrivateKey` interface.
-* Deprecated
-  :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` in favor
-  of backend specific providers of the
-  :class:`~cryptography.hazmat.primitives.interfaces.RSAPublicKey` interface.
-* Deprecated
-  :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` in
-  favor of backend specific providers of the
-  :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey` interface.
-* Deprecated
-  :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` in favor
-  of backend specific providers of the
-  :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey` interface.
-* Deprecated
-  :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters` in
-  favor of backend specific providers of the
-  :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters` interface.
+* Deprecated the concrete ``RSAPrivateKey`` class in favor of backend
+  specific providers of the
+  :class:`cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
+  interface.
+* Deprecated the concrete ``RSAPublicKey`` in favor of backend specific
+  providers of the
+  :class:`cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
+  interface.
+* Deprecated the concrete ``DSAPrivateKey`` class in favor of backend
+  specific providers of the
+  :class:`cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
+  interface.
+* Deprecated the concrete ``DSAPublicKey`` class in favor of backend specific
+  providers of the
+  :class:`cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
+  interface.
+* Deprecated the concrete ``DSAParameters`` class in favor of backend specific
+  providers of the
+  :class:`cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
+  interface.
 * Deprecated ``encrypt_rsa``, ``decrypt_rsa``, ``create_rsa_signature_ctx`` and
   ``create_rsa_verification_ctx`` on
   :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
diff --git a/docs/conf.py b/docs/conf.py
index f674ebe..5a4c41b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -58,6 +58,8 @@
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
 
+nitpicky = True
+
 # The suffix of source filenames.
 source_suffix = '.rst'
 
@@ -268,6 +270,6 @@
 # texinfo_show_urls = 'footnote'
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}
+intersphinx_mapping = {'https://docs.python.org/3': None}
 
 epub_theme = 'epub'
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index e3dc96c..15d8b98 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -91,7 +91,7 @@
         Check if the specified ``algorithm`` is supported by this backend.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns: ``True`` if the specified ``algorithm`` is supported by this
@@ -101,15 +101,15 @@
     .. method:: create_hash_ctx(algorithm)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashContext` that
+        :class:`~cryptography.hazmat.primitives.hashes.HashContext` that
         uses the specified ``algorithm`` to calculate a message digest.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.HashContext`
+            :class:`~cryptography.hazmat.primitives.hashes.HashContext`
 
 
 .. class:: HMACBackend
@@ -127,7 +127,7 @@
         Check if the specified ``algorithm`` is supported by this backend.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns: ``True`` if the specified ``algorithm`` is supported for HMAC
@@ -136,16 +136,16 @@
     .. method:: create_hmac_ctx(algorithm)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashContext` that
+        :class:`~cryptography.hazmat.primitives.hashes.HashContext` that
         uses the specified ``algorithm`` to calculate a hash-based message
         authentication code.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.HashContext`
+            :class:`~cryptography.hazmat.primitives.hashes.HashContext`
 
 
 .. class:: CMACBackend
@@ -191,7 +191,7 @@
         Check if the specified ``algorithm`` is supported by this backend.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns: ``True`` if the specified ``algorithm`` is supported for
@@ -200,7 +200,7 @@
     .. method:: derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material)
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :param int length: The desired length of the derived key. Maximum is
@@ -334,7 +334,7 @@
             restricted to only the 1024-bit keys specified in FIPS 186-2.
 
         :return: A new instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
             provider.
 
         :raises ValueError: This is raised if the key size is not supported
@@ -343,7 +343,7 @@
     .. method:: dsa_hash_supported(algorithm)
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns: ``True`` if the specified ``algorithm`` is supported by this
@@ -401,7 +401,7 @@
     .. method:: elliptic_curve_supported(curve)
 
         :param curve: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurve`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
             provider.
 
         :returns: True if the elliptic curve is supported by this backend.
@@ -409,11 +409,11 @@
     .. method:: elliptic_curve_signature_algorithm_supported(signature_algorithm, curve)
 
         :param signature_algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurveSignatureAlgorithm`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurveSignatureAlgorithm`
             provider.
 
         :param curve: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurve`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
             provider.
 
         :returns: True if the signature algorithm and curve are supported by this backend.
@@ -421,27 +421,27 @@
     .. method:: generate_elliptic_curve_private_key(curve)
 
         :param curve: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurve`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
             provider.
 
     .. method:: load_elliptic_curve_private_numbers(numbers)
 
         :param numbers: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePrivateNumbers`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers`
             provider.
 
         :returns: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
             provider.
 
     .. method:: load_elliptic_curve_public_numbers(numbers)
 
         :param numbers: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePublicNumbers`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`
             provider.
 
         :returns: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePublicKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
             provider.
 
 .. class:: PEMSerializationBackend
diff --git a/docs/hazmat/bindings/commoncrypto.rst b/docs/hazmat/bindings/commoncrypto.rst
index 9484cfa..4f58a6d 100644
--- a/docs/hazmat/bindings/commoncrypto.rst
+++ b/docs/hazmat/bindings/commoncrypto.rst
@@ -17,7 +17,7 @@
 
     .. attribute:: ffi
 
-        This is a :class:`cffi.FFI` instance. It can be used to allocate and
+        This is a ``cffi.FFI`` instance. It can be used to allocate and
         otherwise manipulate CommonCrypto structures.
 
     .. attribute:: lib
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
index ccd36e3..8075be1 100644
--- a/docs/hazmat/bindings/index.rst
+++ b/docs/hazmat/bindings/index.rst
@@ -3,7 +3,7 @@
 Bindings
 ========
 
-.. currentmodule:: cryptography.hazmat.bindings
+.. module:: cryptography.hazmat.bindings
 
 ``cryptography`` aims to provide low-level CFFI based bindings to multiple
 native C libraries. These provide no automatic initialization of the library
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
index 36255b5..446c450 100644
--- a/docs/hazmat/bindings/openssl.rst
+++ b/docs/hazmat/bindings/openssl.rst
@@ -16,7 +16,7 @@
 
     .. attribute:: ffi
 
-        This is a :class:`cffi.FFI` instance. It can be used to allocate and
+        This is a ``cffi.FFI`` instance. It can be used to allocate and
         otherwise manipulate OpenSSL structures.
 
     .. attribute:: lib
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index ff934a6..36bc801 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -3,7 +3,7 @@
 DSA
 ===
 
-.. currentmodule:: cryptography.hazmat.primitives.asymmetric.dsa
+.. module:: cryptography.hazmat.primitives.asymmetric.dsa
 
 `DSA`_ is a `public-key`_ algorithm for signing messages.
 
@@ -267,7 +267,7 @@
         :rfc:`6979`.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :param backend: A
@@ -330,7 +330,7 @@
             specified in :rfc:`6979`.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :param backend: A
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 4b8177e..5b11471 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -3,7 +3,7 @@
 Elliptic curve cryptography
 ===========================
 
-.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ec
+.. module:: cryptography.hazmat.primitives.asymmetric.ec
 
 
 .. function:: generate_private_key(curve, backend)
@@ -32,7 +32,7 @@
     `FIPS 186-3`_, and later in `FIPS 186-4`_.
 
     :param algorithm: An instance of a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider.
 
     .. doctest::
@@ -282,7 +282,7 @@
 
     .. attribute:: algorithm
 
-        :type: :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
 
         The digest algorithm to be used with the signature scheme.
 
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index c37961e..4855a45 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -3,7 +3,7 @@
 RSA
 ===
 
-.. currentmodule:: cryptography.hazmat.primitives.asymmetric.rsa
+.. module:: cryptography.hazmat.primitives.asymmetric.rsa
 
 `RSA`_ is a `public-key`_ algorithm for encrypting and signing messages.
 
@@ -252,7 +252,7 @@
     in :class:`PSS` padding. It takes a hash algorithm and a salt length.
 
     :param algorithm: An instance of a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider.
 
 Numbers
@@ -307,7 +307,7 @@
 
     .. attribute:: public_numbers
 
-        :type: :class:`~cryptography.hazmat.primitives.rsa.RSAPublicNumbers`
+        :type: :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
 
         The :class:`RSAPublicNumbers` which makes up the RSA public key
         associated with this RSA private key.
@@ -316,19 +316,19 @@
 
         :type: int
 
-        ``p``, one of the two primes composing the :attr:`modulus`.
+        ``p``, one of the two primes composing ``n``.
 
     .. attribute:: q
 
         :type: int
 
-        ``q``, one of the two primes composing the :attr:`modulus`.
+        ``q``, one of the two primes composing ``n``.
 
     .. attribute:: d
 
         :type: int
 
-        The private exponent. Alias for :attr:`private_exponent`.
+        The private exponent.
 
     .. attribute:: dmp1
 
@@ -429,7 +429,7 @@
             provider.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns:
@@ -499,7 +499,7 @@
             provider.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
         :returns:
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index 7ff4ce3..8155e6f 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -104,9 +104,9 @@
         not encrypted. Or if the key was encrypted but no
         password was supplied.
 
-    :raises UnsupportedAlgorithm: If the serialized key is of a type that
-        is not supported by the backend or if the key is encrypted with a
-        symmetric cipher that is not supported by the backend.
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
+        is of a type that is not supported by the backend or if the key is
+        encrypted with a symmetric cipher that is not supported by the backend.
 
 .. function:: load_pem_public_key(data, backend)
 
@@ -133,8 +133,8 @@
     :raises ValueError: If the PEM data's structure could not be decoded
         successfully.
 
-    :raises UnsupportedAlgorithm: If the serialized key is of a type that
-        is not supported by the backend.
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
+        is of a type that is not supported by the backend.
 
 
 OpenSSH Public Key
@@ -181,5 +181,5 @@
     :raises ValueError: If the OpenSSH data could not be properly decoded or
         if the key is not in the proper format.
 
-    :raises UnsupportedAlgorithm: If the serialized key is of a type that is
-        not supported.
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
+        key is of a type that is not supported.
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 7e5295c..4928832 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -3,7 +3,7 @@
 Message digests
 ===============
 
-.. currentmodule:: cryptography.hazmat.primitives.hashes
+.. module:: cryptography.hazmat.primitives.hashes
 
 .. class:: Hash(algorithm, backend)
 
@@ -12,9 +12,9 @@
     results (with a high probability) in different digests.
 
     This is an implementation of
-    :class:`~cryptography.hazmat.primitives.interfaces.HashContext` meant to
+    :class:`~cryptography.hazmat.primitives.hashes.HashContext` meant to
     be used with
-    :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+    :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
     implementations to provide an incremental interface to calculating
     various message digests.
 
@@ -39,7 +39,7 @@
     `Lifetimes of cryptographic hash functions`_.
 
     :param algorithm: A
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider such as those described in
         :ref:`below <cryptographic-hash-algorithms>`.
     :param backend: A
@@ -146,4 +146,48 @@
     message digest and has practical known collision attacks.
 
 
+Interfaces
+~~~~~~~~~~
+
+.. class:: HashAlgorithm
+
+    .. attribute:: name
+
+        :type: str
+
+        The standard name for the hash algorithm, for example: ``"sha256"`` or
+        ``"whirlpool"``.
+
+    .. attribute:: digest_size
+
+        :type: int
+
+        The size of the resulting digest in bytes.
+
+    .. attribute:: block_size
+
+        :type: int
+
+        The internal block size of the hash algorithm in bytes.
+
+
+.. class:: HashContext
+
+    .. attribute:: algorithm
+
+        A :class:`HashAlgorithm` that will be used by this context.
+
+    .. method:: update(data)
+
+        :param bytes data: The data you want to hash.
+
+    .. method:: finalize()
+
+        :return: The final digest as bytes.
+
+    .. method:: copy()
+
+        :return: A :class:`HashContext` that is a copy of the current context.
+
+
 .. _`Lifetimes of cryptographic hash functions`: http://valerieaurora.org/hash.html
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 0995489..86a3a7e 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -1,5 +1,7 @@
 .. hazmat::
 
+.. module:: cryptography.hazmat.primitives.interfaces
+
 Interfaces
 ==========
 
@@ -15,9 +17,6 @@
 Symmetric ciphers
 -----------------
 
-.. currentmodule:: cryptography.hazmat.primitives.interfaces
-
-
 .. class:: CipherAlgorithm
 
     A named symmetric encryption algorithm.
@@ -75,9 +74,10 @@
         meets any necessary invariants. This should raise an exception if they
         are not met.
 
-        For example, the :class:`~cryptography.hazmat.primitives.modes.CBC`
-        mode uses this method to check that the provided initialization
-        vector's length matches the block size of the algorithm.
+        For example, the
+        :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode uses
+        this method to check that the provided initialization vector's length
+        matches the block size of the algorithm.
 
 
 .. class:: ModeWithInitializationVector
@@ -160,52 +160,6 @@
 :mod:`cryptography.hazmat.primitives.asymmetric.ec` module.
 
 
-Hash algorithms
----------------
-
-.. class:: HashAlgorithm
-
-    .. attribute:: name
-
-        :type: str
-
-        The standard name for the hash algorithm, for example: ``"sha256"`` or
-        ``"whirlpool"``.
-
-    .. attribute:: digest_size
-
-        :type: int
-
-        The size of the resulting digest in bytes.
-
-    .. attribute:: block_size
-
-        :type: int
-
-        The internal block size of the hash algorithm in bytes.
-
-
-.. class:: HashContext
-
-    .. attribute:: algorithm
-
-        A :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` that
-        will be used by this context.
-
-    .. method:: update(data)
-
-        :param bytes data: The data you want to hash.
-
-    .. method:: finalize()
-
-        :return: The final digest as bytes.
-
-    .. method:: copy()
-
-        :return: A :class:`~cryptography.hazmat.primitives.interfaces.HashContext`
-             that is a copy of the current context.
-
-
 Key derivation functions
 ------------------------
 
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index 6009687..4a47159 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -69,7 +69,7 @@
         >>> kdf.verify(b"my great password", key)
 
     :param algorithm: An instance of a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider.
     :param int length: The desired length of the derived key. Maximum is
         (2\ :sup:`32` - 1) * ``algorithm.digest_size``.
@@ -169,7 +169,7 @@
         >>> hkdf.verify(b"input key", key)
 
     :param algorithm: An instance of a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider.
 
     :param int length: The desired length of the derived key. Maximum is
@@ -270,7 +270,7 @@
         >>> hkdf.verify(key_material, key)
 
     :param algorithm: An instance of a
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider.
 
     :param int length: The desired length of the derived key. Maximum is
diff --git a/docs/hazmat/primitives/mac/hmac.rst b/docs/hazmat/primitives/mac/hmac.rst
index ce566c5..2515ac9 100644
--- a/docs/hazmat/primitives/mac/hmac.rst
+++ b/docs/hazmat/primitives/mac/hmac.rst
@@ -18,7 +18,7 @@
 .. class:: HMAC(key, algorithm, backend)
 
     HMAC objects take a ``key`` and a
-    :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` provider.
+    :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` provider.
     The ``key`` should be :doc:`randomly generated bytes </random-numbers>` and
     is recommended to be equal in length to the ``digest_size`` of the hash
     function chosen. You must keep the ``key`` secret.
@@ -39,7 +39,7 @@
     raised.
 
     If ``algorithm`` isn't a
-    :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` provider
+    :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` provider
     then ``TypeError`` will be raised.
 
     To check that a given signature is correct use the :meth:`verify` method.
@@ -56,7 +56,7 @@
 
     :param bytes key: Secret key as ``bytes``.
     :param algorithm: An
-        :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         provider such as those described in
         :ref:`Cryptographic Hashes <cryptographic-hash-algorithms>`.
     :param backend: An
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index d532ad1..b2ce376 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -422,6 +422,7 @@
 
 Interfaces
 ----------
+.. currentmodule:: cryptography.hazmat.primitives.interfaces
 
 .. class:: CipherContext
 
@@ -438,8 +439,8 @@
     recommended padding is
     :class:`~cryptography.hazmat.primitives.padding.PKCS7`. If you are using a
     stream cipher mode (such as
-    :class:`~cryptography.hazmat.primitives.modes.CTR`) you don't have to worry
-    about this.
+    :class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`) you don't have
+    to worry about this.
 
     .. method:: update(data)
 
diff --git a/docs/x509.rst b/docs/x509.rst
index 6067ca5..0298d94 100644
--- a/docs/x509.rst
+++ b/docs/x509.rst
@@ -103,7 +103,7 @@
     .. method:: fingerprint(algorithm)
 
         :param algorithm: The
-            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             that will be used to generate the fingerprint.
 
         :return bytes: The fingerprint using the supplied hash algorithm as
@@ -130,8 +130,8 @@
 
         :type:
             :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.interfaces.EllipticCurvePublicKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
 
         The public key associated with the certificate.
 
diff --git a/src/cryptography/hazmat/backends/commoncrypto/hashes.py b/src/cryptography/hazmat/backends/commoncrypto/hashes.py
index 8ce20f6..a54e983 100644
--- a/src/cryptography/hazmat/backends/commoncrypto/hashes.py
+++ b/src/cryptography/hazmat/backends/commoncrypto/hashes.py
@@ -6,10 +6,10 @@
 
 from cryptography import utils
 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives import hashes
 
 
-@utils.register_interface(interfaces.HashContext)
+@utils.register_interface(hashes.HashContext)
 class _HashContext(object):
     def __init__(self, backend, algorithm, ctx=None):
         self._algorithm = algorithm
diff --git a/src/cryptography/hazmat/backends/commoncrypto/hmac.py b/src/cryptography/hazmat/backends/commoncrypto/hmac.py
index 942688e..ae623d8 100644
--- a/src/cryptography/hazmat/backends/commoncrypto/hmac.py
+++ b/src/cryptography/hazmat/backends/commoncrypto/hmac.py
@@ -8,11 +8,11 @@
 from cryptography.exceptions import (
     InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import constant_time, hashes, interfaces
 
 
 @utils.register_interface(interfaces.MACContext)
-@utils.register_interface(interfaces.HashContext)
+@utils.register_interface(hashes.HashContext)
 class _HMACContext(object):
     def __init__(self, backend, key, algorithm, ctx=None):
         self._algorithm = algorithm
diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py
index 8dc3c01..2c1702f 100644
--- a/src/cryptography/hazmat/backends/openssl/hashes.py
+++ b/src/cryptography/hazmat/backends/openssl/hashes.py
@@ -7,10 +7,10 @@
 
 from cryptography import utils
 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives import hashes
 
 
-@utils.register_interface(interfaces.HashContext)
+@utils.register_interface(hashes.HashContext)
 class _HashContext(object):
     def __init__(self, backend, algorithm, ctx=None):
         self._algorithm = algorithm
diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py
index 356d2aa..dfe9d93 100644
--- a/src/cryptography/hazmat/backends/openssl/hmac.py
+++ b/src/cryptography/hazmat/backends/openssl/hmac.py
@@ -9,11 +9,11 @@
 from cryptography.exceptions import (
     InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import constant_time, hashes, interfaces
 
 
 @utils.register_interface(interfaces.MACContext)
-@utils.register_interface(interfaces.HashContext)
+@utils.register_interface(hashes.HashContext)
 class _HMACContext(object):
     def __init__(self, backend, key, algorithm, ctx=None):
         self._algorithm = algorithm
diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py
index f51b201..d0c3ead 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -7,7 +7,7 @@
 import six
 
 from cryptography import utils
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives import hashes, interfaces
 
 
 @utils.register_interface(interfaces.AsymmetricPadding)
@@ -38,8 +38,8 @@
     name = "EME-OAEP"
 
     def __init__(self, mgf, algorithm, label):
-        if not isinstance(algorithm, interfaces.HashAlgorithm):
-            raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+        if not isinstance(algorithm, hashes.HashAlgorithm):
+            raise TypeError("Expected instance of hashes.HashAlgorithm.")
 
         self._mgf = mgf
         self._algorithm = algorithm
@@ -50,7 +50,7 @@
     MAX_LENGTH = object()
 
     def __init__(self, algorithm):
-        if not isinstance(algorithm, interfaces.HashAlgorithm):
-            raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+        if not isinstance(algorithm, hashes.HashAlgorithm):
+            raise TypeError("Expected instance of hashes.HashAlgorithm.")
 
         self._algorithm = algorithm
diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py
index f00c074..6bc8500 100644
--- a/src/cryptography/hazmat/primitives/hashes.py
+++ b/src/cryptography/hazmat/primitives/hashes.py
@@ -4,15 +4,66 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
+import six
+
 from cryptography import utils
 from cryptography.exceptions import (
     AlreadyFinalized, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HashBackend
-from cryptography.hazmat.primitives import interfaces
 
 
-@utils.register_interface(interfaces.HashContext)
+@six.add_metaclass(abc.ABCMeta)
+class HashAlgorithm(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this algorithm (e.g. "sha256", "md5").
+        """
+
+    @abc.abstractproperty
+    def digest_size(self):
+        """
+        The size of the resulting digest in bytes.
+        """
+
+    @abc.abstractproperty
+    def block_size(self):
+        """
+        The internal block size of the hash algorithm in bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class HashContext(object):
+    @abc.abstractproperty
+    def algorithm(self):
+        """
+        A HashAlgorithm that will be used by this context.
+        """
+
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Processes the provided bytes through the hash.
+        """
+
+    @abc.abstractmethod
+    def finalize(self):
+        """
+        Finalizes the hash context and returns the hash digest as bytes.
+        """
+
+    @abc.abstractmethod
+    def copy(self):
+        """
+        Return a HashContext that is a copy of the current context.
+        """
+
+
+@utils.register_interface(HashContext)
 class Hash(object):
     def __init__(self, algorithm, backend, ctx=None):
         if not isinstance(backend, HashBackend):
@@ -21,8 +72,8 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.HashAlgorithm):
-            raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+        if not isinstance(algorithm, HashAlgorithm):
+            raise TypeError("Expected instance of hashes.HashAlgorithm.")
         self._algorithm = algorithm
 
         self._backend = backend
@@ -56,56 +107,56 @@
         return digest
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class SHA1(object):
     name = "sha1"
     digest_size = 20
     block_size = 64
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class SHA224(object):
     name = "sha224"
     digest_size = 28
     block_size = 64
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class SHA256(object):
     name = "sha256"
     digest_size = 32
     block_size = 64
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class SHA384(object):
     name = "sha384"
     digest_size = 48
     block_size = 128
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class SHA512(object):
     name = "sha512"
     digest_size = 64
     block_size = 128
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class RIPEMD160(object):
     name = "ripemd160"
     digest_size = 20
     block_size = 64
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class Whirlpool(object):
     name = "whirlpool"
     digest_size = 64
     block_size = 64
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(HashAlgorithm)
 class MD5(object):
     name = "md5"
     digest_size = 16
diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py
index 17f1084..15b9ee6 100644
--- a/src/cryptography/hazmat/primitives/hmac.py
+++ b/src/cryptography/hazmat/primitives/hmac.py
@@ -9,11 +9,11 @@
     AlreadyFinalized, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives import hashes, interfaces
 
 
 @utils.register_interface(interfaces.MACContext)
-@utils.register_interface(interfaces.HashContext)
+@utils.register_interface(hashes.HashContext)
 class HMAC(object):
     def __init__(self, key, algorithm, backend, ctx=None):
         if not isinstance(backend, HMACBackend):
@@ -22,8 +22,8 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.HashAlgorithm):
-            raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+        if not isinstance(algorithm, hashes.HashAlgorithm):
+            raise TypeError("Expected instance of hashes.HashAlgorithm.")
         self._algorithm = algorithm
 
         self._backend = backend
diff --git a/src/cryptography/hazmat/primitives/interfaces/__init__.py b/src/cryptography/hazmat/primitives/interfaces/__init__.py
index a2154df..17bac1e 100644
--- a/src/cryptography/hazmat/primitives/interfaces/__init__.py
+++ b/src/cryptography/hazmat/primitives/interfaces/__init__.py
@@ -9,6 +9,7 @@
 import six
 
 from cryptography import utils
+from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
 from cryptography.hazmat.primitives.interfaces.ciphers import (
     BlockCipherAlgorithm, CipherAlgorithm, Mode,
@@ -202,52 +203,26 @@
         """
 
 
-@six.add_metaclass(abc.ABCMeta)
-class HashAlgorithm(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this algorithm (e.g. "sha256", "md5").
-        """
-
-    @abc.abstractproperty
-    def digest_size(self):
-        """
-        The size of the resulting digest in bytes.
-        """
-
-    @abc.abstractproperty
-    def block_size(self):
-        """
-        The internal block size of the hash algorithm in bytes.
-        """
+HashContext = utils.deprecated(
+    hashes.HashContext,
+    __name__,
+    (
+        "The HashContext interface has moved to the "
+        "cryptography.hazmat.primitives.hashes module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
-@six.add_metaclass(abc.ABCMeta)
-class HashContext(object):
-    @abc.abstractproperty
-    def algorithm(self):
-        """
-        A HashAlgorithm that will be used by this context.
-        """
-
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes through the hash.
-        """
-
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Finalizes the hash context and returns the hash digest as bytes.
-        """
-
-    @abc.abstractmethod
-    def copy(self):
-        """
-        Return a HashContext that is a copy of the current context.
-        """
+HashAlgorithm = utils.deprecated(
+    hashes.HashAlgorithm,
+    __name__,
+    (
+        "The HashAlgorithm interface has moved to the "
+        "cryptography.hazmat.primitives.hashes module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
 RSAPrivateKey = utils.deprecated(
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 5b5c7bd..97d5808 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -49,7 +49,7 @@
     name = "dummy-cipher"
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(hashes.HashAlgorithm)
 class DummyHash(object):
     name = "dummy-hash"
     block_size = None
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index d4bf622..d6fd727 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -13,14 +13,14 @@
 from cryptography import utils
 from cryptography.exceptions import AlreadyFinalized, _Reasons
 from cryptography.hazmat.backends.interfaces import HashBackend
-from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives import hashes
 
 from .utils import generate_base_hash_test
 from ..backends.test_multibackend import DummyHashBackend
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(hashes.HashAlgorithm)
 class UnsupportedDummyHash(object):
     name = "unsupported-dummy-hash"
     block_size = None
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index e31ddc8..acd0332 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -15,14 +15,14 @@
     AlreadyFinalized, InvalidSignature, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
-from cryptography.hazmat.primitives import hashes, hmac, interfaces
+from cryptography.hazmat.primitives import hashes, hmac
 
 from .utils import generate_base_hmac_test
 from ..backends.test_multibackend import DummyHMACBackend
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(hashes.HashAlgorithm)
 class UnsupportedDummyHash(object):
     name = "unsupported-dummy-hash"
     block_size = None
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
index caa6a85..df49d23 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -13,13 +13,13 @@
     AlreadyFinalized, InvalidKey, _Reasons
 )
 from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
 
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.HashAlgorithm)
+@utils.register_interface(hashes.HashAlgorithm)
 class DummyHash(object):
     name = "dummy-hash"
     block_size = None
diff --git a/tox.ini b/tox.ini
index 4e1304d..dc8811a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -21,6 +21,7 @@
 deps =
     doc8
     pyenchant
+    readme>=0.5.1
     sphinx
     sphinx_rtd_theme
     sphinxcontrib-spelling
@@ -31,6 +32,7 @@
     sphinx-build -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
     sphinx-build -W -b spelling docs docs/_build/html
     doc8 --allow-long-titles README.rst CHANGELOG.rst docs/ --ignore-path docs/_build/
+    python setup.py check --restructuredtext --strict
 
 [testenv:docs-linkcheck]
 deps =