move cipher and mode interfaces
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 15d8b98..2f4cdd3 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -30,10 +30,10 @@
         this backend.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns: ``True`` if the specified ``cipher`` and ``mode`` combination
             is supported by this backend, otherwise ``False``
@@ -42,18 +42,18 @@
     .. method:: create_symmetric_encryption_ctx(cipher, mode)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` that
+        :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext` that
         can be used for encrypting data with the symmetric ``cipher`` using
         the given ``mode``.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext`
 
         :raises ValueError: When tag is not None in an AEAD mode
 
@@ -61,18 +61,18 @@
     .. method:: create_symmetric_decryption_ctx(cipher, mode)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` that
+        :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext` that
         can be used for decrypting data with the symmetric ``cipher`` using
         the given ``mode``.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext`
 
         :raises ValueError: When tag is None in an AEAD mode
 
@@ -157,7 +157,7 @@
     .. method:: cmac_algorithm_supported(algorithm)
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm`
             provider.
         :return: Returns True if the block cipher is supported for CMAC by this backend
 
@@ -168,7 +168,7 @@
         uses the specified ``algorithm`` to calculate a message authentication code.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm`
             provider.
 
         :returns:
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 86a3a7e..67c6b3d 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -14,95 +14,6 @@
 .. _`Abstract Base Classes`: https://docs.python.org/3/library/abc.html
 
 
-Symmetric ciphers
------------------
-
-.. class:: CipherAlgorithm
-
-    A named symmetric encryption algorithm.
-
-    .. attribute:: name
-
-        :type: str
-
-        The standard name for the mode, for example, "AES", "Camellia", or
-        "Blowfish".
-
-    .. attribute:: key_size
-
-        :type: int
-
-        The number of bits in the key being used.
-
-
-.. class:: BlockCipherAlgorithm
-
-    A block cipher algorithm.
-
-    .. attribute:: block_size
-
-        :type: int
-
-        The number of bits in a block.
-
-
-Cipher modes
-~~~~~~~~~~~~
-
-Interfaces used by the symmetric cipher modes described in
-:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
-
-.. class:: Mode
-
-    A named cipher mode.
-
-    .. attribute:: name
-
-        :type: str
-
-        This should be the standard shorthand name for the mode, for example
-        Cipher-Block Chaining mode is "CBC".
-
-        The name may be used by a backend to influence the operation of a
-        cipher in conjunction with the algorithm's name.
-
-    .. method:: validate_for_algorithm(algorithm)
-
-        :param CipherAlgorithm algorithm:
-
-        Checks that the combination of this mode with the provided algorithm
-        meets any necessary invariants. This should raise an exception if they
-        are not met.
-
-        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
-
-    A cipher mode with an initialization vector.
-
-    .. attribute:: initialization_vector
-
-        :type: bytes
-
-        Exact requirements of the initialization are described by the
-        documentation of individual modes.
-
-
-.. class:: ModeWithNonce
-
-    A cipher mode with a nonce.
-
-    .. attribute:: nonce
-
-        :type: bytes
-
-        Exact requirements of the nonce are described by the documentation of
-        individual modes.
-
 Asymmetric interfaces
 ---------------------
 
diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst
index 1ba1b3f..14e1842 100644
--- a/docs/hazmat/primitives/mac/cmac.rst
+++ b/docs/hazmat/primitives/mac/cmac.rst
@@ -22,7 +22,7 @@
     .. versionadded:: 0.4
 
     CMAC objects take a
-    :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm` provider.
+    :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm` provider.
 
     .. doctest::
 
@@ -39,7 +39,7 @@
     raised.
 
     If ``algorithm`` isn't a
-    :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+    :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm`
     provider then ``TypeError`` will be raised.
 
     To check that a given signature is correct use the :meth:`verify` method.
@@ -55,13 +55,13 @@
         cryptography.exceptions.InvalidSignature: Signature did not match digest.
 
     :param algorithm: An
-        :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm`
         provider.
     :param backend: An
         :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
         provider.
     :raises TypeError: This is raised if the provided ``algorithm`` is not an instance of
-        :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.base.BlockCipherAlgorithm`
     :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
         provided ``backend`` does not implement
         :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index b2ce376..5302301 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -43,10 +43,10 @@
         'a secret message'
 
     :param algorithms: A
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.base.CipherAlgorithm`
         provider such as those described
         :ref:`below <symmetric-encryption-algorithms>`.
-    :param mode: A :class:`~cryptography.hazmat.primitives.interfaces.Mode`
+    :param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
         provider such as those described
         :ref:`below <symmetric-encryption-modes>`.
     :param backend: A
@@ -60,7 +60,7 @@
     .. method:: encryptor()
 
         :return: An encrypting
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext`
             provider.
 
         If the backend doesn't support the requested combination of ``cipher``
@@ -70,7 +70,7 @@
     .. method:: decryptor()
 
         :return: A decrypting
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.base.CipherContext`
             provider.
 
         If the backend doesn't support the requested combination of ``cipher``
@@ -293,7 +293,7 @@
     .. danger::
 
         When using this mode you **must** not use the decrypted data until
-        :meth:`~cryptography.hazmat.primitives.interfaces.CipherContext.finalize`
+        :meth:`~cryptography.hazmat.primitives.ciphers.base.CipherContext.finalize`
         has been called. GCM provides **no** guarantees of ciphertext integrity
         until decryption is complete.
 
@@ -422,7 +422,8 @@
 
 Interfaces
 ----------
-.. currentmodule:: cryptography.hazmat.primitives.interfaces
+
+.. currentmodule:: cryptography.hazmat.primitives.ciphers.base
 
 .. class:: CipherContext
 
@@ -505,6 +506,91 @@
         :raises: :class:`~cryptography.exceptions.NotYetFinalized` if called
             before the context is finalized.
 
+.. class:: CipherAlgorithm
+
+    A named symmetric encryption algorithm.
+
+    .. attribute:: name
+
+        :type: str
+
+        The standard name for the mode, for example, "AES", "Camellia", or
+        "Blowfish".
+
+    .. attribute:: key_size
+
+        :type: int
+
+        The number of bits in the key being used.
+
+
+.. class:: BlockCipherAlgorithm
+
+    A block cipher algorithm.
+
+    .. attribute:: block_size
+
+        :type: int
+
+        The number of bits in a block.
+
+Interfaces used by the symmetric cipher modes described in
+:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
+
+.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes
+
+.. class:: Mode
+
+    A named cipher mode.
+
+    .. attribute:: name
+
+        :type: str
+
+        This should be the standard shorthand name for the mode, for example
+        Cipher-Block Chaining mode is "CBC".
+
+        The name may be used by a backend to influence the operation of a
+        cipher in conjunction with the algorithm's name.
+
+    .. method:: validate_for_algorithm(algorithm)
+
+        :param CipherAlgorithm algorithm:
+
+        Checks that the combination of this mode with the provided algorithm
+        meets any necessary invariants. This should raise an exception if they
+        are not met.
+
+        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
+
+    A cipher mode with an initialization vector.
+
+    .. attribute:: initialization_vector
+
+        :type: bytes
+
+        Exact requirements of the initialization are described by the
+        documentation of individual modes.
+
+
+.. class:: ModeWithNonce
+
+    A cipher mode with a nonce.
+
+    .. attribute:: nonce
+
+        :type: bytes
+
+        Exact requirements of the nonce are described by the documentation of
+        individual modes.
+
+
 
 .. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
 .. _`recommends a 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
diff --git a/src/cryptography/hazmat/backends/commoncrypto/ciphers.py b/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
index 7e537db..54715d8 100644
--- a/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
+++ b/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
@@ -8,13 +8,14 @@
 from cryptography.exceptions import (
     InvalidTag, UnsupportedAlgorithm, _Reasons
 )
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import constant_time
+from cryptography.hazmat.primitives.ciphers import base, modes
 from cryptography.hazmat.primitives.ciphers.modes import (
     CFB, CFB8, CTR, OFB
 )
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(base.CipherContext)
 class _CipherContext(object):
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
@@ -31,7 +32,7 @@
         # treat RC4 and other stream cipher block sizes).
         # This bug has been filed as rdar://15589470
         self._bytes_processed = 0
-        if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not
+        if (isinstance(cipher, base.BlockCipherAlgorithm) and not
                 isinstance(mode, (OFB, CFB, CFB8, CTR))):
             self._byte_block_size = cipher.block_size // 8
         else:
@@ -51,9 +52,9 @@
         ctx = self._backend._ffi.new("CCCryptorRef *")
         ctx = self._backend._ffi.gc(ctx, self._backend._release_cipher_ctx)
 
-        if isinstance(mode, interfaces.ModeWithInitializationVector):
+        if isinstance(mode, modes.ModeWithInitializationVector):
             iv_nonce = mode.initialization_vector
-        elif isinstance(mode, interfaces.ModeWithNonce):
+        elif isinstance(mode, modes.ModeWithNonce):
             iv_nonce = mode.nonce
         else:
             iv_nonce = self._backend._ffi.NULL
@@ -101,8 +102,8 @@
         return self._backend._ffi.buffer(buf)[:outlen[0]]
 
 
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(base.AEADCipherContext)
+@utils.register_interface(base.AEADEncryptionContext)
 class _GCMCipherContext(object):
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py
index d665f36..e836175 100644
--- a/src/cryptography/hazmat/backends/openssl/ciphers.py
+++ b/src/cryptography/hazmat/backends/openssl/ciphers.py
@@ -6,13 +6,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
-from cryptography.hazmat.primitives import interfaces
-from cryptography.hazmat.primitives.ciphers.modes import GCM
+from cryptography.hazmat.primitives.ciphers import base, modes
 
 
-@utils.register_interface(interfaces.CipherContext)
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(base.CipherContext)
+@utils.register_interface(base.AEADCipherContext)
+@utils.register_interface(base.AEADEncryptionContext)
 class _CipherContext(object):
     _ENCRYPT = 1
     _DECRYPT = 0
@@ -24,7 +23,7 @@
         self._operation = operation
         self._tag = None
 
-        if isinstance(self._cipher, interfaces.BlockCipherAlgorithm):
+        if isinstance(self._cipher, base.BlockCipherAlgorithm):
             self._block_size = self._cipher.block_size
         else:
             self._block_size = 1
@@ -54,9 +53,9 @@
                 _Reasons.UNSUPPORTED_CIPHER
             )
 
-        if isinstance(mode, interfaces.ModeWithInitializationVector):
+        if isinstance(mode, modes.ModeWithInitializationVector):
             iv_nonce = mode.initialization_vector
-        elif isinstance(mode, interfaces.ModeWithNonce):
+        elif isinstance(mode, modes.ModeWithNonce):
             iv_nonce = mode.nonce
         else:
             iv_nonce = self._backend._ffi.NULL
@@ -72,7 +71,7 @@
             ctx, len(cipher.key)
         )
         assert res != 0
-        if isinstance(mode, GCM):
+        if isinstance(mode, modes.GCM):
             res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
                 ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
                 len(iv_nonce), self._backend._ffi.NULL
@@ -107,7 +106,7 @@
         # should be taken only when length is zero and mode is not GCM because
         # AES GCM can return improper tag values if you don't call update
         # with empty plaintext when authenticating AAD for ...reasons.
-        if len(data) == 0 and not isinstance(self._mode, GCM):
+        if len(data) == 0 and not isinstance(self._mode, modes.GCM):
             return b""
 
         buf = self._backend._ffi.new("unsigned char[]",
@@ -124,7 +123,7 @@
         # even if you are only using authenticate_additional_data or the
         # GCM tag will be wrong. An (empty) call to update resolves this
         # and is harmless for all other versions of OpenSSL.
-        if isinstance(self._mode, GCM):
+        if isinstance(self._mode, modes.GCM):
             self.update(b"")
 
         buf = self._backend._ffi.new("unsigned char[]", self._block_size)
@@ -133,7 +132,7 @@
         if res == 0:
             errors = self._backend._consume_errors()
 
-            if not errors and isinstance(self._mode, GCM):
+            if not errors and isinstance(self._mode, modes.GCM):
                 raise InvalidTag
 
             assert errors
@@ -154,7 +153,7 @@
             else:
                 raise self._backend._unknown_error(errors[0])
 
-        if (isinstance(self._mode, GCM) and
+        if (isinstance(self._mode, modes.GCM) and
            self._operation == self._ENCRYPT):
             block_byte_size = self._block_size // 8
             tag_buf = self._backend._ffi.new(
@@ -181,7 +180,7 @@
     tag = utils.read_only_property("_tag")
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(base.CipherContext)
 class _AESCTRCipherContext(object):
     """
     This is needed to provide support for AES CTR mode in OpenSSL 0.9.8. It can
diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
index 677d702..0e219be 100644
--- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -5,7 +5,9 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography import utils
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers.base import (
+    BlockCipherAlgorithm, CipherAlgorithm
+)
 
 
 def _verify_key_size(algorithm, key):
@@ -17,8 +19,8 @@
     return key
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class AES(object):
     name = "AES"
     block_size = 128
@@ -32,8 +34,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class Camellia(object):
     name = "camellia"
     block_size = 128
@@ -47,8 +49,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class TripleDES(object):
     name = "3DES"
     block_size = 64
@@ -66,8 +68,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class Blowfish(object):
     name = "Blowfish"
     block_size = 64
@@ -81,8 +83,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class CAST5(object):
     name = "CAST5"
     block_size = 64
@@ -96,7 +98,7 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class ARC4(object):
     name = "RC4"
     key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256])
@@ -109,7 +111,7 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class IDEA(object):
     name = "IDEA"
     block_size = 64
@@ -123,8 +125,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class SEED(object):
     name = "SEED"
     block_size = 128
diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py
index 81b8d77..8f3028f 100644
--- a/src/cryptography/hazmat/primitives/ciphers/base.py
+++ b/src/cryptography/hazmat/primitives/ciphers/base.py
@@ -4,13 +4,76 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
+import six
+
 from cryptography import utils
 from cryptography.exceptions import (
     AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm,
     _Reasons
 )
 from cryptography.hazmat.backends.interfaces import CipherBackend
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers import modes
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CipherAlgorithm(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this mode (e.g. "AES", "Camellia").
+        """
+
+    @abc.abstractproperty
+    def key_size(self):
+        """
+        The size of the key being used as an integer in bits (e.g. 128, 256).
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BlockCipherAlgorithm(object):
+    @abc.abstractproperty
+    def block_size(self):
+        """
+        The size of a block as an integer in bits (e.g. 64, 128).
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CipherContext(object):
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Processes the provided bytes through the cipher and returns the results
+        as bytes.
+        """
+
+    @abc.abstractmethod
+    def finalize(self):
+        """
+        Returns the results of processing the final block as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AEADCipherContext(object):
+    @abc.abstractmethod
+    def authenticate_additional_data(self, data):
+        """
+        Authenticates the provided bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AEADEncryptionContext(object):
+    @abc.abstractproperty
+    def tag(self):
+        """
+        Returns tag bytes. This is only available after encryption is
+        finalized.
+        """
 
 
 class Cipher(object):
@@ -21,10 +84,8 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.CipherAlgorithm):
-            raise TypeError(
-                "Expected interface of interfaces.CipherAlgorithm."
-            )
+        if not isinstance(algorithm, CipherAlgorithm):
+            raise TypeError("Expected interface of CipherAlgorithm.")
 
         if mode is not None:
             mode.validate_for_algorithm(algorithm)
@@ -34,7 +95,7 @@
         self._backend = backend
 
     def encryptor(self):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if self.mode.tag is not None:
                 raise ValueError(
                     "Authentication tag must be None when encrypting."
@@ -45,7 +106,7 @@
         return self._wrap_ctx(ctx, encrypt=True)
 
     def decryptor(self):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if self.mode.tag is None:
                 raise ValueError(
                     "Authentication tag must be provided when decrypting."
@@ -56,7 +117,7 @@
         return self._wrap_ctx(ctx, encrypt=False)
 
     def _wrap_ctx(self, ctx, encrypt):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if encrypt:
                 return _AEADEncryptionContext(ctx)
             else:
@@ -65,7 +126,7 @@
             return _CipherContext(ctx)
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(CipherContext)
 class _CipherContext(object):
     def __init__(self, ctx):
         self._ctx = ctx
@@ -83,8 +144,8 @@
         return data
 
 
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(AEADCipherContext)
+@utils.register_interface(CipherContext)
 class _AEADCipherContext(object):
     def __init__(self, ctx):
         self._ctx = ctx
@@ -113,7 +174,7 @@
         self._ctx.authenticate_additional_data(data)
 
 
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(AEADEncryptionContext)
 class _AEADEncryptionContext(_AEADCipherContext):
     @property
     def tag(self):
diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py
index fc269de..e31c906 100644
--- a/src/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/src/cryptography/hazmat/primitives/ciphers/modes.py
@@ -4,8 +4,54 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
+import six
+
 from cryptography import utils
-from cryptography.hazmat.primitives import interfaces
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Mode(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this mode (e.g. "ECB", "CBC").
+        """
+
+    @abc.abstractmethod
+    def validate_for_algorithm(self, algorithm):
+        """
+        Checks that all the necessary invariants of this (mode, algorithm)
+        combination are met.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithInitializationVector(object):
+    @abc.abstractproperty
+    def initialization_vector(self):
+        """
+        The value of the initialization vector for this mode as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithNonce(object):
+    @abc.abstractproperty
+    def nonce(self):
+        """
+        The value of the nonce for this mode as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithAuthenticationTag(object):
+    @abc.abstractproperty
+    def tag(self):
+        """
+        The value of the tag supplied to the constructor of this mode.
+        """
 
 
 def _check_iv_length(self, algorithm):
@@ -15,8 +61,8 @@
         ))
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CBC(object):
     name = "CBC"
 
@@ -27,7 +73,7 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(Mode)
 class ECB(object):
     name = "ECB"
 
@@ -35,8 +81,8 @@
         pass
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class OFB(object):
     name = "OFB"
 
@@ -47,8 +93,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CFB(object):
     name = "CFB"
 
@@ -59,8 +105,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CFB8(object):
     name = "CFB8"
 
@@ -71,8 +117,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithNonce)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithNonce)
 class CTR(object):
     name = "CTR"
 
@@ -88,9 +134,9 @@
             ))
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
-@utils.register_interface(interfaces.ModeWithAuthenticationTag)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
+@utils.register_interface(ModeWithAuthenticationTag)
 class GCM(object):
     name = "GCM"
 
diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py
index ccbe07e..d746147 100644
--- a/src/cryptography/hazmat/primitives/cmac.py
+++ b/src/cryptography/hazmat/primitives/cmac.py
@@ -10,6 +10,7 @@
 )
 from cryptography.hazmat.backends.interfaces import CMACBackend
 from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers import base
 
 
 @utils.register_interface(interfaces.MACContext)
@@ -21,9 +22,9 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.BlockCipherAlgorithm):
+        if not isinstance(algorithm, base.BlockCipherAlgorithm):
             raise TypeError(
-                "Expected instance of interfaces.BlockCipherAlgorithm."
+                "Expected instance of BlockCipherAlgorithm."
             )
         self._algorithm = algorithm
 
diff --git a/src/cryptography/hazmat/primitives/interfaces/__init__.py b/src/cryptography/hazmat/primitives/interfaces/__init__.py
index 17bac1e..e9ba780 100644
--- a/src/cryptography/hazmat/primitives/interfaces/__init__.py
+++ b/src/cryptography/hazmat/primitives/interfaces/__init__.py
@@ -11,19 +11,106 @@
 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,
-    ModeWithAuthenticationTag, ModeWithInitializationVector, ModeWithNonce
+from cryptography.hazmat.primitives.ciphers import base, modes
+
+
+BlockCipherAlgorithm = utils.deprecated(
+    base.BlockCipherAlgorithm,
+    __name__,
+    (
+        "The BlockCipherAlgorithm interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.base module"
+    ),
+    utils.DeprecatedIn08
 )
 
-__all__ = [
-    "BlockCipherAlgorithm",
-    "CipherAlgorithm",
-    "Mode",
-    "ModeWithAuthenticationTag",
-    "ModeWithInitializationVector",
-    "ModeWithNonce"
-]
+
+CipherAlgorithm = utils.deprecated(
+    base.CipherAlgorithm,
+    __name__,
+    (
+        "The CipherAlgorithm interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.base module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+Mode = utils.deprecated(
+    modes.Mode,
+    __name__,
+    (
+        "The Mode interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithAuthenticationTag = utils.deprecated(
+    modes.ModeWithAuthenticationTag,
+    __name__,
+    (
+        "The ModeWithAuthenticationTag interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithInitializationVector = utils.deprecated(
+    modes.ModeWithInitializationVector,
+    __name__,
+    (
+        "The ModeWithInitializationVector interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithNonce = utils.deprecated(
+    modes.ModeWithNonce,
+    __name__,
+    (
+        "The ModeWithNonce interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+CipherContext = utils.deprecated(
+    base.CipherContext,
+    __name__,
+    (
+        "The CipherContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.base module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+AEADCipherContext = utils.deprecated(
+    base.AEADCipherContext,
+    __name__,
+    (
+        "The AEADCipherContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.base module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+AEADEncryptionContext = utils.deprecated(
+    base.AEADEncryptionContext,
+    __name__,
+    (
+        "The AEADEncryptionContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.base module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
 EllipticCurve = utils.deprecated(
@@ -154,41 +241,6 @@
 
 
 @six.add_metaclass(abc.ABCMeta)
-class CipherContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes through the cipher and returns the results
-        as bytes.
-        """
-
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Returns the results of processing the final block as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AEADCipherContext(object):
-    @abc.abstractmethod
-    def authenticate_additional_data(self, data):
-        """
-        Authenticates the provided bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AEADEncryptionContext(object):
-    @abc.abstractproperty
-    def tag(self):
-        """
-        Returns tag bytes. This is only available after encryption is
-        finalized.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
 class PaddingContext(object):
     @abc.abstractmethod
     def update(self, data):
diff --git a/src/cryptography/hazmat/primitives/interfaces/ciphers.py b/src/cryptography/hazmat/primitives/interfaces/ciphers.py
deleted file mode 100644
index 075a9c2..0000000
--- a/src/cryptography/hazmat/primitives/interfaces/ciphers.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import abc
-
-import six
-
-
-@six.add_metaclass(abc.ABCMeta)
-class CipherAlgorithm(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this mode (e.g. "AES", "Camellia").
-        """
-
-    @abc.abstractproperty
-    def key_size(self):
-        """
-        The size of the key being used as an integer in bits (e.g. 128, 256).
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class BlockCipherAlgorithm(object):
-    @abc.abstractproperty
-    def block_size(self):
-        """
-        The size of a block as an integer in bits (e.g. 64, 128).
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class Mode(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this mode (e.g. "ECB", "CBC").
-        """
-
-    @abc.abstractmethod
-    def validate_for_algorithm(self, algorithm):
-        """
-        Checks that all the necessary invariants of this (mode, algorithm)
-        combination are met.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithInitializationVector(object):
-    @abc.abstractproperty
-    def initialization_vector(self):
-        """
-        The value of the initialization vector for this mode as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithNonce(object):
-    @abc.abstractproperty
-    def nonce(self):
-        """
-        The value of the nonce for this mode as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithAuthenticationTag(object):
-    @abc.abstractproperty
-    def tag(self):
-        """
-        The value of the tag supplied to the constructor of this mode.
-        """
diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py
index 7ccc1af..c867804 100644
--- a/tests/hazmat/backends/test_commoncrypto.py
+++ b/tests/hazmat/backends/test_commoncrypto.py
@@ -9,15 +9,14 @@
 from cryptography import utils
 from cryptography.exceptions import InternalError, _Reasons
 from cryptography.hazmat.backends import _available_backends
-from cryptography.hazmat.primitives import interfaces
 from cryptography.hazmat.primitives.ciphers.algorithms import AES
-from cryptography.hazmat.primitives.ciphers.base import Cipher
+from cryptography.hazmat.primitives.ciphers.base import Cipher, CipherAlgorithm
 from cryptography.hazmat.primitives.ciphers.modes import CBC, GCM
 
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     block_size = None
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 97d5808..878d71b 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -23,14 +23,16 @@
 from cryptography.hazmat.primitives.asymmetric import dsa, padding
 from cryptography.hazmat.primitives.ciphers import Cipher
 from cryptography.hazmat.primitives.ciphers.algorithms import AES
-from cryptography.hazmat.primitives.ciphers.modes import CBC, CTR
-from cryptography.hazmat.primitives.interfaces import BlockCipherAlgorithm
+from cryptography.hazmat.primitives.ciphers.base import (
+    BlockCipherAlgorithm, CipherAlgorithm
+)
+from cryptography.hazmat.primitives.ciphers.modes import CBC, CTR, Mode
 
 from ..primitives.fixtures_rsa import RSA_KEY_512
 from ...utils import load_vectors_from_file, raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(Mode)
 class DummyMode(object):
     name = "dummy-mode"
 
@@ -38,7 +40,7 @@
         pass
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     key_size = None
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 22e6d0e..1b3fc1c 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -13,9 +13,8 @@
     AlreadyFinalized, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import CipherBackend
-from cryptography.hazmat.primitives import interfaces
 from cryptography.hazmat.primitives.ciphers import (
-    Cipher, algorithms, modes
+    Cipher, algorithms, base, modes
 )
 
 from .utils import (
@@ -24,7 +23,7 @@
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(modes.Mode)
 class DummyMode(object):
     name = "dummy-mode"
 
@@ -32,7 +31,7 @@
         pass
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(base.CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     key_size = None
@@ -46,7 +45,7 @@
             modes.CBC(binascii.unhexlify(b"0" * 32)),
             backend
         )
-        assert isinstance(cipher.encryptor(), interfaces.CipherContext)
+        assert isinstance(cipher.encryptor(), base.CipherContext)
 
     def test_creates_decryptor(self, backend):
         cipher = Cipher(
@@ -54,7 +53,7 @@
             modes.CBC(binascii.unhexlify(b"0" * 32)),
             backend
         )
-        assert isinstance(cipher.decryptor(), interfaces.CipherContext)
+        assert isinstance(cipher.decryptor(), base.CipherContext)
 
     def test_instantiate_with_non_algorithm(self, backend):
         algorithm = object()