DH serialization (#3297)

* DH keys support serialization

* Add DH serialization documentation

* Add tests for DH keys serialization in DER encoding

* update version to 1.8

* Allow only SubjectPublicKeyInfo serialization

* Remove support in TraditionalOpenSSL format

* Fix pep8

* Refactor dh serialization tests
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index fb72240..9747998 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -98,6 +98,19 @@
   Diffie-Hellman vector pairs that were generated using OpenSSL
   DH_generate_parameters_ex and DH_generate_key.
 
+* ``vectors/cryptography_vectors/asymmetric/DH/dhp.pem``,
+  ``vectors/cryptography_vectors/asymmetric/DH/dhkey.pem`` and
+  ``vectors/cryptography_vectors/asymmetric/DH/dhpub.pem`` contains
+  Diffie-Hellman parameters and key respectively. The keys were
+  generated using OpenSSL following `DHKE`_ guide.
+  ``vectors/cryptography_vectors/asymmetric/DH/dhkey.txt`` contains
+  all parameter in text.
+  ``vectors/cryptography_vectors/asymmetric/DH/dhp.der``,
+  ``vectors/cryptography_vectors/asymmetric/DH/dhkey.der`` and
+  ``vectors/cryptography_vectors/asymmetric/DH/dhpub.der`` contains
+  are the above parameters and keys in DER format.
+
+
 X.509
 ~~~~~
 
@@ -471,3 +484,4 @@
 .. _`test/evptests.txt`: https://github.com/openssl/openssl/blob/2d0b44126763f989a4cbffbffe9d0c7518158bb7/test/evptests.txt
 .. _`unknown signature OID`: https://bugzilla.mozilla.org/show_bug.cgi?id=405966
 .. _`botan`: https://github.com/randombit/botan/blob/57789bdfc55061002b2727d0b32587612829a37c/src/tests/data/pubkey/dh.vec
+.. _`DHKE`: https://sandilands.info/sgordon/diffie-hellman-secret-key-exchange-with-openssl
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index 463df90..4cb5ccd 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -145,6 +145,33 @@
 
         :return bytes: The agreed key. The bytes are ordered in 'big' endian.
 
+    .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+        .. versionadded:: 1.8
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
+        and encryption algorithm (such as
+        :class:`~cryptography.hazmat.primitives.serialization.BestAvailableEncryption`
+        or :class:`~cryptography.hazmat.primitives.serialization.NoEncryption`)
+        are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+            enum.
+
+        :param encryption_algorithm: An instance of an object conforming to the
+            :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+            interface.
+
+        :return bytes: Serialized key.
+
 
 .. class:: DHPublicKey
 
@@ -173,6 +200,25 @@
 
         :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`.
 
+    .. method:: public_bytes(encoding, format)
+
+        .. versionadded:: 1.8
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
+        are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
+
+        :return bytes: Serialized key.
+
 
 Numbers
 ~~~~~~~
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 3f44d7f..e460ab5 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -522,6 +522,11 @@
             self.openssl_assert(ec_cdata != self._ffi.NULL)
             ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
             return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey)
+        elif key_type == self._lib.EVP_PKEY_DH:
+            dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey)
+            self.openssl_assert(dh_cdata != self._ffi.NULL)
+            dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
+            return _DHPrivateKey(self, dh_cdata, evp_pkey)
         else:
             raise UnsupportedAlgorithm("Unsupported key type.")
 
@@ -549,6 +554,11 @@
             self.openssl_assert(ec_cdata != self._ffi.NULL)
             ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
             return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
+        elif key_type == self._lib.EVP_PKEY_DH:
+            dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey)
+            self.openssl_assert(dh_cdata != self._ffi.NULL)
+            dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
+            return _DHPublicKey(self, dh_cdata, evp_pkey)
         else:
             raise UnsupportedAlgorithm("Unsupported key type.")
 
@@ -1730,6 +1740,12 @@
 
         return _DHParameters(self, dh_param_cdata)
 
+    def _dh_cdata_to_evp_pkey(self, dh_cdata):
+        evp_pkey = self._create_evp_pkey_gc()
+        res = self._lib.EVP_PKEY_set1_DH(evp_pkey, dh_cdata)
+        self.openssl_assert(res == 1)
+        return evp_pkey
+
     def generate_dh_private_key(self, parameters):
         dh_key_cdata = self._lib.DHparams_dup(parameters._dh_cdata)
         self.openssl_assert(dh_key_cdata != self._ffi.NULL)
@@ -1738,7 +1754,9 @@
         res = self._lib.DH_generate_key(dh_key_cdata)
         self.openssl_assert(res == 1)
 
-        return _DHPrivateKey(self, dh_key_cdata)
+        evp_pkey = self._dh_cdata_to_evp_pkey(dh_key_cdata)
+
+        return _DHPrivateKey(self, dh_key_cdata, evp_pkey)
 
     def generate_dh_private_key_and_parameters(self, generator, key_size):
         return self.generate_dh_private_key(
@@ -1769,7 +1787,9 @@
         if codes[0] != 0:
             raise ValueError("DH private numbers did not pass safety checks.")
 
-        return _DHPrivateKey(self, dh_cdata)
+        evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata)
+
+        return _DHPrivateKey(self, dh_cdata, evp_pkey)
 
     def load_dh_public_numbers(self, numbers):
         dh_cdata = self._lib.DH_new()
@@ -1788,7 +1808,9 @@
         res = self._lib.DH_set0_key(dh_cdata, pub_key, self._ffi.NULL)
         self.openssl_assert(res == 1)
 
-        return _DHPublicKey(self, dh_cdata)
+        evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata)
+
+        return _DHPublicKey(self, dh_cdata, evp_pkey)
 
     def load_dh_parameter_numbers(self, numbers):
         dh_cdata = self._lib.DH_new()
diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py
index 666429f..b594d41 100644
--- a/src/cryptography/hazmat/backends/openssl/dh.py
+++ b/src/cryptography/hazmat/backends/openssl/dh.py
@@ -5,6 +5,7 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography import utils
+from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric import dh
 
 
@@ -64,9 +65,10 @@
 
 @utils.register_interface(dh.DHPrivateKeyWithSerialization)
 class _DHPrivateKey(object):
-    def __init__(self, backend, dh_cdata):
+    def __init__(self, backend, dh_cdata, evp_pkey):
         self._backend = backend
         self._dh_cdata = dh_cdata
+        self._evp_pkey = evp_pkey
         self._key_size_bytes = self._backend._lib.DH_size(dh_cdata)
 
     @property
@@ -141,18 +143,32 @@
                                              pub_key_dup,
                                              self._backend._ffi.NULL)
         self._backend.openssl_assert(res == 1)
-
-        return _DHPublicKey(self._backend, dh_cdata)
+        evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata)
+        return _DHPublicKey(self._backend, dh_cdata, evp_pkey)
 
     def parameters(self):
         return _dh_cdata_to_parameters(self._dh_cdata, self._backend)
 
+    def private_bytes(self, encoding, format, encryption_algorithm):
+        if format is not serialization.PrivateFormat.PKCS8:
+            raise ValueError(
+                "DH private keys support only PKCS8 serialization"
+            )
+        return self._backend._private_key_bytes(
+            encoding,
+            format,
+            encryption_algorithm,
+            self._evp_pkey,
+            self._dh_cdata
+        )
+
 
 @utils.register_interface(dh.DHPublicKeyWithSerialization)
 class _DHPublicKey(object):
-    def __init__(self, backend, dh_cdata):
+    def __init__(self, backend, dh_cdata, evp_pkey):
         self._backend = backend
         self._dh_cdata = dh_cdata
+        self._evp_pkey = evp_pkey
         self._key_size_bits = _get_dh_num_bits(self._backend, self._dh_cdata)
 
     @property
@@ -180,3 +196,18 @@
 
     def parameters(self):
         return _dh_cdata_to_parameters(self._dh_cdata, self._backend)
+
+    def public_bytes(self, encoding, format):
+        if format is not serialization.PublicFormat.SubjectPublicKeyInfo:
+            raise ValueError(
+                "DH public keys support only "
+                "SubjectPublicKeyInfo serialization"
+            )
+
+        return self._backend._public_key_bytes(
+            encoding,
+            format,
+            self,
+            self._evp_pkey,
+            None
+        )
diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py
index ba724bf..1086630 100644
--- a/tests/hazmat/primitives/test_dh.py
+++ b/tests/hazmat/primitives/test_dh.py
@@ -8,9 +8,13 @@
 
 import pytest
 
-from cryptography.hazmat.backends.interfaces import DHBackend
+from cryptography.hazmat.backends.interfaces import (
+    DHBackend, PEMSerializationBackend)
+from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric import dh
 from cryptography.utils import bit_length, int_from_bytes
+
+from ...doubles import DummyKeySerializationEncryption
 from ...utils import load_nist_vectors, load_vectors_from_file
 
 
@@ -285,3 +289,242 @@
         symkey = key.exchange(public.public_key(backend))
 
         assert int_from_bytes(symkey, 'big') == int(vector["k"], 16)
+
+
+@pytest.mark.requires_backend_interface(interface=DHBackend)
+@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
+class TestDHPrivateKeySerialization(object):
+
+    @pytest.mark.parametrize(
+        ("encoding", "loader_func"),
+        [
+            [
+                serialization.Encoding.PEM,
+                serialization.load_pem_private_key
+            ],
+            [
+                serialization.Encoding.DER,
+                serialization.load_der_private_key
+            ],
+        ]
+    )
+    def test_private_bytes_unencrypted(self, backend, encoding,
+                                       loader_func):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        serialized = key.private_bytes(
+            encoding, serialization.PrivateFormat.PKCS8,
+            serialization.NoEncryption()
+        )
+        loaded_key = loader_func(serialized, None, backend)
+        loaded_priv_num = loaded_key.private_numbers()
+        priv_num = key.private_numbers()
+        assert loaded_priv_num == priv_num
+
+    @pytest.mark.parametrize(
+        ("key_path", "loader_func", "encoding"),
+        [
+            (
+                os.path.join("asymmetric", "DH", "dhkey.pem"),
+                serialization.load_pem_private_key,
+                serialization.Encoding.PEM,
+            ), (
+                os.path.join("asymmetric", "DH", "dhkey.der"),
+                serialization.load_der_private_key,
+                serialization.Encoding.DER,
+            )
+        ]
+    )
+    def test_private_bytes_match(self, key_path, loader_func,
+                                 encoding, backend):
+        key_bytes = load_vectors_from_file(
+            key_path,
+            lambda pemfile: pemfile.read(), mode="rb"
+        )
+        key = loader_func(key_bytes, None, backend)
+        serialized = key.private_bytes(
+            encoding, serialization.PrivateFormat.PKCS8,
+            serialization.NoEncryption()
+        )
+        assert serialized == key_bytes
+
+    @pytest.mark.parametrize(
+        ("key_path", "loader_func"),
+        [
+            (
+                os.path.join("asymmetric", "DH", "dhkey.pem"),
+                serialization.load_pem_private_key,
+            ), (
+                os.path.join("asymmetric", "DH", "dhkey.der"),
+                serialization.load_der_private_key,
+            )
+        ]
+    )
+    def test_private_bytes_values(self, key_path, loader_func,
+                                  backend):
+        key_bytes = load_vectors_from_file(
+            key_path,
+            lambda pemfile: pemfile.read(), mode="rb"
+        )
+        vec = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "dhkey.txt"),
+            load_nist_vectors)[0]
+        key = loader_func(key_bytes, None, backend)
+        private_numbers = key.private_numbers()
+        assert private_numbers.x == int(vec["x"], 16)
+        assert private_numbers.public_numbers.y == int(vec["y"], 16)
+        assert private_numbers.public_numbers.parameter_numbers.g == int(
+            vec["g"])
+        assert private_numbers.public_numbers.parameter_numbers.p == int(
+            vec["p"], 16)
+
+    def test_private_bytes_traditional_openssl_invalid(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.TraditionalOpenSSL,
+                serialization.NoEncryption()
+            )
+
+    def test_private_bytes_invalid_encoding(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        with pytest.raises(TypeError):
+            key.private_bytes(
+                "notencoding",
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption()
+            )
+
+    def test_private_bytes_invalid_format(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                "invalidformat",
+                serialization.NoEncryption()
+            )
+
+    def test_private_bytes_invalid_encryption_algorithm(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        with pytest.raises(TypeError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                "notanencalg"
+            )
+
+    def test_private_bytes_unsupported_encryption_type(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                DummyKeySerializationEncryption()
+            )
+
+
+@pytest.mark.requires_backend_interface(interface=DHBackend)
+@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
+class TestDHPublicKeySerialization(object):
+
+    @pytest.mark.parametrize(
+        ("encoding", "loader_func"),
+        [
+            [
+                serialization.Encoding.PEM,
+                serialization.load_pem_public_key
+            ],
+            [
+                serialization.Encoding.DER,
+                serialization.load_der_public_key
+            ],
+        ]
+    )
+    def test_public_bytes(self, backend, encoding,
+                          loader_func):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key().public_key()
+        serialized = key.public_bytes(
+            encoding, serialization.PublicFormat.SubjectPublicKeyInfo
+        )
+        loaded_key = loader_func(serialized, backend)
+        loaded_pub_num = loaded_key.public_numbers()
+        pub_num = key.public_numbers()
+        assert loaded_pub_num == pub_num
+
+    @pytest.mark.parametrize(
+        ("key_path", "loader_func", "encoding"),
+        [
+            (
+                os.path.join("asymmetric", "DH", "dhpub.pem"),
+                serialization.load_pem_public_key,
+                serialization.Encoding.PEM,
+            ), (
+                os.path.join("asymmetric", "DH", "dhpub.der"),
+                serialization.load_der_public_key,
+                serialization.Encoding.DER,
+            )
+        ]
+    )
+    def test_public_bytes_match(self, key_path, loader_func,
+                                encoding, backend):
+        key_bytes = load_vectors_from_file(
+            key_path,
+            lambda pemfile: pemfile.read(), mode="rb"
+        )
+        pub_key = loader_func(key_bytes, backend)
+        serialized = pub_key.public_bytes(
+            encoding,
+            serialization.PublicFormat.SubjectPublicKeyInfo,
+        )
+        assert serialized == key_bytes
+
+    @pytest.mark.parametrize(
+        ("key_path", "loader_func"),
+        [
+            (
+                os.path.join("asymmetric", "DH", "dhpub.pem"),
+                serialization.load_pem_public_key,
+            ), (
+                os.path.join("asymmetric", "DH", "dhpub.der"),
+                serialization.load_der_public_key,
+            )
+        ]
+    )
+    def test_public_bytes_values(self, key_path, loader_func,
+                                 backend):
+        key_bytes = load_vectors_from_file(
+            key_path,
+            lambda pemfile: pemfile.read(), mode="rb"
+        )
+        vec = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "dhkey.txt"),
+            load_nist_vectors)[0]
+        pub_key = loader_func(key_bytes, backend)
+        public_numbers = pub_key.public_numbers()
+        assert public_numbers.y == int(vec["y"], 16)
+        assert public_numbers.parameter_numbers.g == int(vec["g"])
+        assert public_numbers.parameter_numbers.p == int(vec["p"], 16)
+
+    def test_public_bytes_invalid_encoding(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key().public_key()
+        with pytest.raises(TypeError):
+            key.public_bytes(
+                "notencoding",
+                serialization.PublicFormat.SubjectPublicKeyInfo
+            )
+
+    def test_public_bytes_pkcs1_unsupported(self, backend):
+        parameters = dh.generate_parameters(2, 512, backend)
+        key = parameters.generate_private_key().public_key()
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+            )
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey.der b/vectors/cryptography_vectors/asymmetric/DH/dhkey.der
new file mode 100644
index 0000000..07edb8c
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhkey.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey.pem b/vectors/cryptography_vectors/asymmetric/DH/dhkey.pem
new file mode 100644
index 0000000..45ac9e9
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhkey.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBIQIBADCBlQYJKoZIhvcNAQMBMIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51
+V6Vtarjm2+5BslQK/RtlndHde3gx+ccNs+InANszcuJFI8AHt4743kGRzy5XSlul
+4q4dDJENOHoyqYxueFuFVJELEwLQXrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQ
+eQded8Bum8jqzP3rAgECBIGDAoGAcglrcequR+67Nl+FbEjLQb/1toPK5XpMRvsi
+V7BCZLqhSUmQBBZGyJFqTm6JXuZSCi/5zVFAfepoe0jmZj7p2I5TlEu+VsKuAK0q
+yYhIfOXJouVV21Bv1WVcCfRE8o0w4nsAg3uVt7O7R7c1YqHmfE/pUpP5Na/hdGYi
+aWFD94g=
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey.txt b/vectors/cryptography_vectors/asymmetric/DH/dhkey.txt
new file mode 100644
index 0000000..adfcec7
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhkey.txt
@@ -0,0 +1,6 @@
+
+COUNT = 0
+P = 00bb2b5ade38535a23a93cbcf28d307e3cac044e7557a56d6ab8e6dbee41b2540afd1b659dd1dd7b7831f9c70db3e22700db3372e24523c007b78ef8de4191cf2e574a5ba5e2ae1d0c910d387a32a98c6e785b8554910b1302d05eb5ff31c2b0fa14ba18f5509f0ead661806a3d6a974d75881e2d079075e77c06e9bc8eaccfdeb
+G = 2
+Y = 00983d5e292c5457c78e3af022a1a9d6808be7a52f4c1e76b20eb235796ba5b8553a1aaffe6cb9b2d0de41db41f2a72f3a3a6284057b4acac31cfbb19bd1ed963facf24187622b33cb0be70829db67150daa8c7b1803cb8347eba451fb26777d6a1dcc53e2271ef4c1349e2f3e5e97a12c138e486bf14d315fdd86ad8b14e3fd3c
+X = 72096b71eaae47eebb365f856c48cb41bff5b683cae57a4c46fb2257b04264baa1494990041646c8916a4e6e895ee6520a2ff9cd51407dea687b48e6663ee9d88e53944bbe56c2ae00ad2ac988487ce5c9a2e555db506fd5655c09f444f28d30e27b00837b95b7b3bb47b73562a1e67c4fe95293f935afe1746622696143f788
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhp.der b/vectors/cryptography_vectors/asymmetric/DH/dhp.der
new file mode 100644
index 0000000..8c5edae
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhp.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhp.pem b/vectors/cryptography_vectors/asymmetric/DH/dhp.pem
new file mode 100644
index 0000000..1b3f399
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhp.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx
++ccNs+InANszcuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQ
+XrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQeQded8Bum8jqzP3rAgEC
+-----END DH PARAMETERS-----
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhpub.der b/vectors/cryptography_vectors/asymmetric/DH/dhpub.der
new file mode 100644
index 0000000..4560294
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhpub.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhpub.pem b/vectors/cryptography_vectors/asymmetric/DH/dhpub.pem
new file mode 100644
index 0000000..945180d
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dhpub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIDCBlQYJKoZIhvcNAQMBMIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vt
+arjm2+5BslQK/RtlndHde3gx+ccNs+InANszcuJFI8AHt4743kGRzy5XSlul4q4d
+DJENOHoyqYxueFuFVJELEwLQXrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQeQde
+d8Bum8jqzP3rAgECA4GFAAKBgQCYPV4pLFRXx4468CKhqdaAi+elL0wedrIOsjV5
+a6W4VToar/5subLQ3kHbQfKnLzo6YoQFe0rKwxz7sZvR7ZY/rPJBh2IrM8sL5wgp
+22cVDaqMexgDy4NH66RR+yZ3fWodzFPiJx70wTSeLz5el6EsE45Ia/FNMV/dhq2L
+FOP9PA==
+-----END PUBLIC KEY-----