Merge pull request #1727 from public/dh-key-iface-2015

DH key interfaces
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index fdf113f..dde18cf 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -6,6 +6,9 @@
 .. currentmodule:: cryptography.hazmat.primitives.asymmetric.dh
 
 
+Numbers
+~~~~~~~
+
 .. class:: DHPrivateNumbers(x, public_numbers)
 
     .. versionadded:: 0.8
@@ -62,3 +65,98 @@
         :type: int
 
         The generator value.
+
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: DHParameters
+
+    .. versionadded:: 0.9
+
+
+    .. method:: generate_private_key()
+
+        .. versionadded:: 0.9
+
+        Generate a DH private key. This method can be used to generate many
+        new private keys from a single set of parameters.
+
+        :return: A
+            :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`
+            provider.
+
+
+.. class:: DHParametersWithSerialization
+
+    .. versionadded:: 0.9
+
+    Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+
+    .. method:: parameter_numbers()
+
+        Return the numbers that make up this set of parameters.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`.
+
+
+.. class:: DHPrivateKey
+
+    .. versionadded:: 0.9
+
+    .. attribute:: key_size
+
+        The bit length of the prime modulus.
+
+    .. method:: public_key()
+
+        Return the public key associated with this private key.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
+
+    .. method:: parameters()
+
+        Return the parameters associated with this private key.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+
+
+.. class:: DHPrivateKeyWithSerialization
+
+    .. versionadded:: 0.9
+
+    Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
+
+    .. method:: private_numbers()
+
+        Return the numbers that make up this private key.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`.
+
+
+.. class:: DHPublicKey
+
+    .. versionadded:: 0.9
+
+    .. attribute:: key_size
+
+        The bit length of the prime modulus.
+
+    .. method:: parameters()
+
+        Return the parameters associated with this private key.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+
+
+.. class:: DHPublicKeyWithSerialization
+
+    .. versionadded:: 0.9
+
+    Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
+
+    .. method:: public_numbers()
+
+        Return the numbers that make up this public key.
+
+        :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`.
diff --git a/docs/hazmat/primitives/asymmetric/interfaces.rst b/docs/hazmat/primitives/asymmetric/interfaces.rst
index 4932faa..c4f176c 100644
--- a/docs/hazmat/primitives/asymmetric/interfaces.rst
+++ b/docs/hazmat/primitives/asymmetric/interfaces.rst
@@ -30,4 +30,3 @@
 
         :raises cryptography.exceptions.InvalidSignature: If the signature does
             not validate.
-
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index c029b5d..f7b73b3 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -20,6 +20,7 @@
 decrypting
 deserialize
 deserialized
+Diffie
 Docstrings
 Encodings
 fernet
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py
index 61556ef..12d53ee 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dh.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py
@@ -1,18 +1,11 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# 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
 
 from cryptography import utils
@@ -99,3 +92,75 @@
 
     p = utils.read_only_property("_p")
     g = utils.read_only_property("_g")
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHParameters(object):
+    @abc.abstractmethod
+    def generate_private_key(self):
+        """
+        Generates and returns a DHPrivateKey.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHParametersWithSerialization(DHParameters):
+    @abc.abstractmethod
+    def parameter_numbers(self):
+        """
+        Returns a DHParameterNumbers.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHPrivateKey(object):
+    @abc.abstractproperty
+    def key_size(self):
+        """
+        The bit length of the prime modulus.
+        """
+
+    @abc.abstractmethod
+    def public_key(self):
+        """
+        The DHPublicKey associated with this private key.
+        """
+
+    @abc.abstractmethod
+    def parameters(self):
+        """
+        The DHParameters object associated with this private key.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHPrivateKeyWithSerialization(DHPrivateKey):
+    @abc.abstractmethod
+    def private_numbers(self):
+        """
+        Returns a DHPrivateNumbers.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHPublicKey(object):
+    @abc.abstractproperty
+    def key_size(self):
+        """
+        The bit length of the prime modulus.
+        """
+
+    @abc.abstractmethod
+    def parameters(self):
+        """
+        The DHParameters object associated with this public key.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class DHPublicKeyWithSerialization(DHPublicKey):
+    @abc.abstractmethod
+    def public_numbers(self):
+        """
+        Returns a DHPublicNumbers.
+        """