From e44efb634fb1db024fcd6e110eacbf59abbc4782 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Mon, 6 Mar 2017 04:24:55 +0200 Subject: DH subgroup order (q) (#3369) * Support DH q (subgroup order) * Change RFC5114.txt to NIST format * Add tests for DH q * Update docs for DH q * Fix pep8 * Improve test covergae for DH q * Create _dh_params_dup that copy q if DHparams_dup don't On OpenSSL < 1.0.2 DHparams_dup don't copy q. _dh_params_dup call DHparams_dup and if the version is smaller than 1.0.2 copy q manually * Copy q manually on libressl * Add to test vectors serialized RFC5114 2048 bit DH parameters with 224 bit subgroup * Support serialization of DH with q * Add tests for serialization of DH with q * Support DH serialization with q only if Cryptography_HAS_EVP_PKEY_DHX is true * Raise exception when trying to serialize DH X9.42 when not supported * raise unsupported key type when deserilizing DH X9.42 if not supported * pep8 fixes * Fix test_serialization * Add dhx_serialization_supported method to DHBacked * document q in dh_parameters_supported * Rename dhx_serialization_supported to dh_x942_serialization_supported --- docs/development/test-vectors.rst | 14 ++ docs/hazmat/backends/interfaces.rst | 15 +- docs/hazmat/primitives/asymmetric/dh.rst | 12 +- src/cryptography/hazmat/backends/interfaces.py | 9 +- src/cryptography/hazmat/backends/multibackend.py | 13 +- .../hazmat/backends/openssl/backend.py | 66 +++++++-- src/cryptography/hazmat/backends/openssl/dh.py | 77 ++++++++-- .../hazmat/primitives/asymmetric/dh.py | 11 +- tests/hazmat/backends/test_multibackend.py | 7 +- tests/hazmat/backends/test_openssl.py | 83 ++++++++++- tests/hazmat/primitives/test_dh.py | 165 ++++++++++++++++++--- tests/hazmat/primitives/test_serialization.py | 21 ++- .../cryptography_vectors/asymmetric/DH/RFC5114.txt | 3 + .../asymmetric/DH/dhkey_rfc5114_2.der | Bin 0 -> 609 bytes .../asymmetric/DH/dhkey_rfc5114_2.pem | 15 ++ .../asymmetric/DH/dhkey_rfc5114_2.txt | 7 + .../asymmetric/DH/dhp_rfc5114_2.der | Bin 0 -> 526 bytes .../asymmetric/DH/dhp_rfc5114_2.pem | 14 ++ .../asymmetric/DH/dhpub_rfc5114_2.der | Bin 0 -> 840 bytes .../asymmetric/DH/dhpub_rfc5114_2.pem | 20 +++ 20 files changed, 481 insertions(+), 71 deletions(-) create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 15fe2d2e..f9f865e8 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -110,6 +110,20 @@ Key exchange ``vectors/cryptography_vectors/asymmetric/DH/dhpub.der`` contains are the above parameters and keys in DER format. +* ``vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem``, + ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem`` and + ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem`` contains + Diffie-Hellman parameters and key respectively. The keys were + generated using OpenSSL following `DHKE`_ guide. When creating the + parameters we added the `-pkeyopt dh_rfc5114:2` option to use + RFC5114 2048 bit DH parameters with 224 bit subgroup. + ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt`` contains + all parameter in text. + ``vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der``, + ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der`` and + ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der`` contains + are the above parameters and keys in DER format. + X.509 ~~~~~ diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst index 87fc6ab7..4f15d5c6 100644 --- a/docs/hazmat/backends/interfaces.rst +++ b/docs/hazmat/backends/interfaces.rst @@ -666,14 +666,23 @@ A specific ``backend`` may provide one or more of these interfaces. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised when any backend specific criteria are not met. - .. method:: dh_parameters_supported(p, g) + .. method:: dh_parameters_supported(p, g, q=None) :param int p: The p value of the DH key. :param int g: The g value of the DH key. - :returns: ``True`` if the given values of ``p`` and ``g`` are supported - by this backend, otherwise ``False``. + :param int q: The q value of the DH key. + + :returns: ``True`` if the given values of ``p``, ``g`` and ``q`` + are supported by this backend, otherwise ``False``. + + .. versionadded:: 1.8 + + .. method:: dh_x942_serialization_supported() + + :returns: True if serialization of DH objects with + subgroup order (q) is supported by this backend. .. class:: ScryptBackend diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst index 73e534e2..759b265b 100644 --- a/docs/hazmat/primitives/asymmetric/dh.rst +++ b/docs/hazmat/primitives/asymmetric/dh.rst @@ -223,7 +223,7 @@ Key interfaces Numbers ~~~~~~~ -.. class:: DHParameterNumbers(p, g) +.. class:: DHParameterNumbers(p, g, q=None) .. versionadded:: 0.8 @@ -239,7 +239,15 @@ Numbers :type: int - The generator value. Must be 2 or 5. + The generator value. Must be 2 or 5 (Unless q is given). + + .. attribute:: q + + .. versionadded:: 1.8 + + :type: int + + p subgroup order value. .. class:: DHPrivateNumbers(x, public_numbers) diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index c5f2951c..9ed50cc4 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -361,11 +361,18 @@ class DHBackend(object): """ @abc.abstractmethod - def dh_parameters_supported(self, p, g): + def dh_parameters_supported(self, p, g, q=None): """ Returns whether the backend supports DH with these parameter values. """ + @abc.abstractmethod + def dh_x942_serialization_supported(self): + """ + Returns True if the backend supports the serialization of DH objects + with subgroup order (q). + """ + @six.add_metaclass(abc.ABCMeta) class ScryptBackend(object): diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py index 097b4908..bb30c661 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -481,9 +481,18 @@ class MultiBackend(object): _Reasons.UNSUPPORTED_DIFFIE_HELLMAN ) - def dh_parameters_supported(self, p, g): + def dh_parameters_supported(self, p, g, q=None): for b in self._filtered_backends(DHBackend): - return b.dh_parameters_supported(p, g) + return b.dh_parameters_supported(p, g, q) + + raise UnsupportedAlgorithm( + "This backend does not support Diffie-Hellman", + _Reasons.UNSUPPORTED_DIFFIE_HELLMAN + ) + + def dh_x942_serialization_supported(self): + for b in self._filtered_backends(DHBackend): + return b.dh_x942_serialization_supported() raise UnsupportedAlgorithm( "This backend does not support Diffie-Hellman", diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 77538162..446891d3 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -23,7 +23,8 @@ from cryptography.hazmat.backends.interfaces import ( from cryptography.hazmat.backends.openssl.ciphers import _CipherContext from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.dh import ( - _DHParameters, _DHPrivateKey, _DHPublicKey + _DHParameters, _DHPrivateKey, _DHPublicKey, + _dh_params_dup ) from cryptography.hazmat.backends.openssl.dsa import ( _DSAParameters, _DSAPrivateKey, _DSAPublicKey @@ -99,6 +100,9 @@ class Backend(object): self._cipher_registry = {} self._register_default_ciphers() self.activate_osrandom_engine() + self._dh_types = [self._lib.EVP_PKEY_DH] + if self._lib.Cryptography_HAS_EVP_PKEY_DHX: + self._dh_types.append(self._lib.EVP_PKEY_DHX) def openssl_assert(self, ok): return binding._openssl_assert(self._lib, ok) @@ -480,7 +484,7 @@ class Backend(object): 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: + elif key_type in self._dh_types: 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) @@ -512,7 +516,7 @@ class Backend(object): 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: + elif key_type in self._dh_types: 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) @@ -1205,6 +1209,23 @@ class Backend(object): _Reasons.UNSUPPORTED_CIPHER ) + elif errors[0][1:] in ( + ( + self._lib.ERR_LIB_ASN1, + self._lib.ASN1_F_ASN1_CHECK_TLEN, + self._lib.ASN1_R_WRONG_TAG + ), + ( + self._lib.ERR_LIB_PEM, + self._lib.PEM_F_PEM_READ_BIO, + self._lib.PEM_R_NO_START_LINE + ), + ): + raise UnsupportedAlgorithm( + "Unsupported public key algorithm.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM + ) + elif any( error[1:] == ( self._lib.ERR_LIB_EVP, @@ -1660,9 +1681,7 @@ class Backend(object): 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) - dh_key_cdata = self._ffi.gc(dh_key_cdata, self._lib.DH_free) + dh_key_cdata = _dh_params_dup(parameters._dh_cdata, self) res = self._lib.DH_generate_key(dh_key_cdata) self.openssl_assert(res == 1) @@ -1684,10 +1703,16 @@ class Backend(object): p = self._int_to_bn(parameter_numbers.p) g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + pub_key = self._int_to_bn(numbers.public_numbers.y) priv_key = self._int_to_bn(numbers.x) - res = self._lib.DH_set0_pqg(dh_cdata, p, self._ffi.NULL, g) + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) res = self._lib.DH_set0_key(dh_cdata, pub_key, priv_key) @@ -1713,9 +1738,15 @@ class Backend(object): p = self._int_to_bn(parameter_numbers.p) g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + pub_key = self._int_to_bn(numbers.y) - res = self._lib.DH_set0_pqg(dh_cdata, p, self._ffi.NULL, g) + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) res = self._lib.DH_set0_key(dh_cdata, pub_key, self._ffi.NULL) @@ -1733,12 +1764,17 @@ class Backend(object): p = self._int_to_bn(numbers.p) g = self._int_to_bn(numbers.g) - res = self._lib.DH_set0_pqg(dh_cdata, p, self._ffi.NULL, g) + if numbers.q is not None: + q = self._int_to_bn(numbers.q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) return _DHParameters(self, dh_cdata) - def dh_parameters_supported(self, p, g): + def dh_parameters_supported(self, p, g, q=None): dh_cdata = self._lib.DH_new() self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) @@ -1746,7 +1782,12 @@ class Backend(object): p = self._int_to_bn(p) g = self._int_to_bn(g) - res = self._lib.DH_set0_pqg(dh_cdata, p, self._ffi.NULL, g) + if q is not None: + q = self._int_to_bn(q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) codes = self._ffi.new("int[]", 1) @@ -1755,6 +1796,9 @@ class Backend(object): return codes[0] == 0 + def dh_x942_serialization_supported(self): + return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 + def x509_name_bytes(self, name): x509_name = _encode_name_gc(self, name) pp = self._ffi.new("unsigned char **") diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index b594d411..88c876fc 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -5,18 +5,31 @@ from __future__ import absolute_import, division, print_function from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh -def _dh_cdata_to_parameters(dh_cdata, backend): +def _dh_params_dup(dh_cdata, backend): lib = backend._lib ffi = backend._ffi param_cdata = lib.DHparams_dup(dh_cdata) backend.openssl_assert(param_cdata != ffi.NULL) param_cdata = ffi.gc(param_cdata, lib.DH_free) + if lib.OPENSSL_VERSION_NUMBER < 0x10002000 or lib.CRYPTOGRAPHY_IS_LIBRESSL: + # In OpenSSL versions < 1.0.2 or libressl DHparams_dup don't copy q + q = ffi.new("BIGNUM **") + lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL) + q_dup = lib.BN_dup(q[0]) + res = lib.DH_set0_pqg(param_cdata, ffi.NULL, q_dup, ffi.NULL) + backend.openssl_assert(res == 1) + + return param_cdata + +def _dh_cdata_to_parameters(dh_cdata, backend): + param_cdata = _dh_params_dup(dh_cdata, backend) return _DHParameters(backend, param_cdata) @@ -29,13 +42,18 @@ class _DHParameters(object): def parameter_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") - self._backend._lib.DH_get0_pqg(self._dh_cdata, - p, self._backend._ffi.NULL, g) + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) return dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), - g=self._backend._bn_to_int(g[0]) + g=self._backend._bn_to_int(g[0]), + q=q_val ) def generate_private_key(self): @@ -78,10 +96,14 @@ class _DHPrivateKey(object): def private_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") - self._backend._lib.DH_get0_pqg(self._dh_cdata, - p, self._backend._ffi.NULL, g) + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) pub_key = self._backend._ffi.new("BIGNUM **") priv_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, priv_key) @@ -91,7 +113,8 @@ class _DHPrivateKey(object): public_numbers=dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), - g=self._backend._bn_to_int(g[0]) + g=self._backend._bn_to_int(g[0]), + q=q_val ), y=self._backend._bn_to_int(pub_key[0]) ), @@ -126,12 +149,7 @@ class _DHPrivateKey(object): return key def public_key(self): - dh_cdata = self._backend._lib.DHparams_dup(self._dh_cdata) - self._backend.openssl_assert(dh_cdata != self._backend._ffi.NULL) - dh_cdata = self._backend._ffi.gc( - dh_cdata, self._backend._lib.DH_free - ) - + dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) @@ -154,6 +172,17 @@ class _DHPrivateKey(object): raise ValueError( "DH private keys support only PKCS8 serialization" ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + return self._backend._private_key_bytes( encoding, format, @@ -178,10 +207,14 @@ class _DHPublicKey(object): def public_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") - self._backend._lib.DH_get0_pqg(self._dh_cdata, - p, self._backend._ffi.NULL, g) + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) @@ -189,7 +222,8 @@ class _DHPublicKey(object): return dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), - g=self._backend._bn_to_int(g[0]) + g=self._backend._bn_to_int(g[0]), + q=q_val ), y=self._backend._bn_to_int(pub_key[0]) ) @@ -204,6 +238,17 @@ class _DHPublicKey(object): "SubjectPublicKeyInfo serialization" ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + return self._backend._public_key_bytes( encoding, format, diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index ec044ddd..aa60a2d8 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -78,18 +78,21 @@ class DHPublicNumbers(object): class DHParameterNumbers(object): - def __init__(self, p, g): + def __init__(self, p, g, q=None): if ( not isinstance(p, six.integer_types) or not isinstance(g, six.integer_types) ): raise TypeError("p and g must be integers") + if q is not None and not isinstance(q, six.integer_types): + raise TypeError("q must be integer or None") - if g not in (2, 5): + if q is None and g not in (2, 5): raise ValueError("DH generator must be 2 or 5") self._p = p self._g = g + self._q = q def __eq__(self, other): if not isinstance(other, DHParameterNumbers): @@ -97,7 +100,8 @@ class DHParameterNumbers(object): return ( self._p == other._p and - self._g == other._g + self._g == other._g and + self._q == other._q ) def __ne__(self, other): @@ -108,6 +112,7 @@ class DHParameterNumbers(object): p = utils.read_only_property("_p") g = utils.read_only_property("_g") + q = utils.read_only_property("_q") @six.add_metaclass(abc.ABCMeta) diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index bd806731..9370387c 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -265,7 +265,10 @@ class DummyDHBackend(object): def generate_dh_private_key_and_parameters(self, generator, key_size): pass - def dh_parameters_supported(self, p, g): + def dh_parameters_supported(self, p, g, q=None): + pass + + def dh_x942_serialization_supported(self): pass @@ -638,6 +641,8 @@ class TestMultiBackend(object): backend.generate_dh_private_key_and_parameters(2, 512) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_DIFFIE_HELLMAN): backend.dh_parameters_supported(2, 3) + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_DIFFIE_HELLMAN): + backend.dh_x942_serialization_supported() def test_scrypt(self): backend = MultiBackend([DummyScryptBackend()]) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index ff8a42ef..f561c793 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -16,13 +16,13 @@ import pytest from cryptography import utils, x509 from cryptography.exceptions import InternalError, _Reasons -from cryptography.hazmat.backends.interfaces import RSABackend +from cryptography.hazmat.backends.interfaces import DHBackend, RSABackend from cryptography.hazmat.backends.openssl.backend import ( Backend, backend ) from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import dsa, ec, padding +from cryptography.hazmat.primitives.asymmetric import dh, dsa, ec, padding from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import CBC @@ -32,7 +32,9 @@ from ...doubles import ( DummyAsymmetricPadding, DummyCipherAlgorithm, DummyHashAlgorithm, DummyMode ) from ...test_x509 import _load_cert -from ...utils import load_vectors_from_file, raises_unsupported_algorithm +from ...utils import ( + load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm +) def skip_if_libre_ssl(openssl_version): @@ -611,3 +613,78 @@ class TestGOSTCertificate(object): assert cert.subject.get_attributes_for_oid( x509.ObjectIdentifier("1.2.643.3.131.1.1") )[0].value == "007710474375" + + +@pytest.mark.skipif( + backend._lib.Cryptography_HAS_EVP_PKEY_DHX == 1, + reason="Requires OpenSSL without EVP_PKEY_DHX (1.0.2-)") +@pytest.mark.requires_backend_interface(interface=DHBackend) +class TestOpenSSLDHSerialization(object): + + @pytest.mark.parametrize( + "vector", + load_vectors_from_file( + os.path.join("asymmetric", "DH", "RFC5114.txt"), + load_nist_vectors)) + def test_dh_serialization_with_q_unsupported(self, backend, vector): + parameters = dh.DHParameterNumbers(int(vector["p"], 16), + int(vector["g"], 16), + int(vector["q"], 16)) + public = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters) + private = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public) + private_key = private.private_key(backend) + public_key = private_key.public_key() + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): + private_key.private_bytes(serialization.Encoding.PEM, + serialization.PrivateFormat.PKCS8, + serialization.NoEncryption()) + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): + public_key.public_bytes( + serialization.Encoding.PEM, + serialization.PublicFormat.SubjectPublicKeyInfo) + + @pytest.mark.parametrize( + ("key_path", "loader_func"), + [ + ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"), + serialization.load_pem_private_key, + ), + ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"), + serialization.load_der_private_key, + ) + ] + ) + def test_private_load_dhx_unsupported(self, key_path, loader_func, + backend): + key_bytes = load_vectors_from_file( + key_path, + lambda pemfile: pemfile.read(), mode="rb" + ) + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): + loader_func(key_bytes, None, backend) + + @pytest.mark.parametrize( + ("key_path", "loader_func"), + [ + ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"), + serialization.load_pem_public_key, + ), + ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"), + serialization.load_der_public_key, + ) + ] + ) + def test_public_load_dhx_unsupported(self, key_path, loader_func, + backend): + key_bytes = load_vectors_from_file( + key_path, + lambda pemfile: pemfile.read(), mode="rb" + ) + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): + loader_func(key_bytes, backend) diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 1086630d..5b35fe51 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -18,6 +18,13 @@ from ...doubles import DummyKeySerializationEncryption from ...utils import load_nist_vectors, load_vectors_from_file +def _skip_dhx_unsupported(backend): + if not backend.dh_x942_serialization_supported(): + pytest.skip( + "DH x9.42 serialization is not supported" + ) + + def test_dh_parameternumbers(): params = dh.DHParameterNumbers( 65537, 2 @@ -46,6 +53,19 @@ def test_dh_parameternumbers(): 65537, 7 ) + params = dh.DHParameterNumbers( + 65537, 7, 1245 + ) + + assert params.p == 65537 + assert params.g == 7 + assert params.q == 1245 + + with pytest.raises(TypeError): + dh.DHParameterNumbers( + 65537, 2, "hello" + ) + def test_dh_numbers(): params = dh.DHParameterNumbers( @@ -89,7 +109,11 @@ def test_dh_numbers(): def test_dh_parameter_numbers_equality(): assert dh.DHParameterNumbers(65537, 2) == dh.DHParameterNumbers(65537, 2) + assert dh.DHParameterNumbers(65537, 7, 12345) == dh.DHParameterNumbers( + 65537, 7, 12345) assert dh.DHParameterNumbers(6, 2) != dh.DHParameterNumbers(65537, 2) + assert dh.DHParameterNumbers(65537, 2, 123) != dh.DHParameterNumbers( + 65537, 2, 456) assert dh.DHParameterNumbers(65537, 5) != dh.DHParameterNumbers(65537, 2) assert dh.DHParameterNumbers(65537, 2) != object() @@ -132,15 +156,35 @@ class TestDH(object): assert backend.dh_parameters_supported(23, 5) assert not backend.dh_parameters_supported(23, 18) - def test_convert_to_numbers(self, backend): - parameters = backend.generate_dh_private_key_and_parameters(2, 512) + @pytest.mark.parametrize( + "vector", + load_vectors_from_file( + os.path.join("asymmetric", "DH", "RFC5114.txt"), + load_nist_vectors)) + def test_dh_parameters_supported_with_q(self, backend, vector): + assert backend.dh_parameters_supported(int(vector["p"], 16), + int(vector["g"], 16), + int(vector["q"], 16)) + + @pytest.mark.parametrize("with_q", [False, True]) + def test_convert_to_numbers(self, backend, with_q): + if with_q: + vector = load_vectors_from_file( + os.path.join("asymmetric", "DH", "RFC5114.txt"), + load_nist_vectors)[0] + p = int(vector["p"], 16) + g = int(vector["g"], 16) + q = int(vector["q"], 16) + else: + parameters = backend.generate_dh_private_key_and_parameters(2, 512) - private = parameters.private_numbers() + private = parameters.private_numbers() - p = private.public_numbers.parameter_numbers.p - g = private.public_numbers.parameter_numbers.g + p = private.public_numbers.parameter_numbers.p + g = private.public_numbers.parameter_numbers.g + q = None - params = dh.DHParameterNumbers(p, g) + params = dh.DHParameterNumbers(p, g, q) public = dh.DHPublicNumbers(1, params) private = dh.DHPrivateNumbers(2, public) @@ -163,11 +207,22 @@ class TestDH(object): with pytest.raises(ValueError): private.private_key(backend) - def test_generate_dh(self, backend): - generator = 2 - key_size = 512 + @pytest.mark.parametrize("with_q", [False, True]) + def test_generate_dh(self, backend, with_q): + if with_q: + vector = load_vectors_from_file( + os.path.join("asymmetric", "DH", "RFC5114.txt"), + load_nist_vectors)[0] + p = int(vector["p"], 16) + g = int(vector["g"], 16) + q = int(vector["q"], 16) + parameters = dh.DHParameterNumbers(p, g, q).parameters(backend) + key_size = 1024 + else: + generator = 2 + key_size = 512 - parameters = dh.generate_parameters(generator, key_size, backend) + parameters = dh.generate_parameters(generator, key_size, backend) assert isinstance(parameters, dh.DHParameters) key = parameters.generate_private_key() @@ -290,6 +345,27 @@ class TestDH(object): assert int_from_bytes(symkey, 'big') == int(vector["k"], 16) + @pytest.mark.parametrize( + "vector", + load_vectors_from_file( + os.path.join("asymmetric", "DH", "RFC5114.txt"), + load_nist_vectors)) + def test_dh_vectors_with_q(self, backend, vector): + parameters = dh.DHParameterNumbers(int(vector["p"], 16), + int(vector["g"], 16), + int(vector["q"], 16)) + public1 = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters) + private1 = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public1) + public2 = dh.DHPublicNumbers(int(vector["ystatiut"], 16), parameters) + private2 = dh.DHPrivateNumbers(int(vector["xstatiut"], 16), public2) + key1 = private1.private_key(backend) + key2 = private2.private_key(backend) + symkey1 = key1.exchange(public2.public_key(backend)) + symkey2 = key2.exchange(public1.public_key(backend)) + + assert int_from_bytes(symkey1, 'big') == int(vector["z"], 16) + assert int_from_bytes(symkey2, 'big') == int(vector["z"], 16) + @pytest.mark.requires_backend_interface(interface=DHBackend) @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) @@ -332,11 +408,20 @@ class TestDHPrivateKeySerialization(object): os.path.join("asymmetric", "DH", "dhkey.der"), serialization.load_der_private_key, serialization.Encoding.DER, + ), ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"), + serialization.load_pem_private_key, + serialization.Encoding.PEM, + ), ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"), + serialization.load_der_private_key, + serialization.Encoding.DER, ) ] ) def test_private_bytes_match(self, key_path, loader_func, encoding, backend): + _skip_dhx_unsupported(backend) key_bytes = load_vectors_from_file( key_path, lambda pemfile: pemfile.read(), mode="rb" @@ -349,34 +434,48 @@ class TestDHPrivateKeySerialization(object): assert serialized == key_bytes @pytest.mark.parametrize( - ("key_path", "loader_func"), + ("key_path", "loader_func", "vec_path"), [ ( os.path.join("asymmetric", "DH", "dhkey.pem"), serialization.load_pem_private_key, + os.path.join("asymmetric", "DH", "dhkey.txt") ), ( os.path.join("asymmetric", "DH", "dhkey.der"), serialization.load_der_private_key, + os.path.join("asymmetric", "DH", "dhkey.txt") + ), ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"), + serialization.load_pem_private_key, + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt") + ), ( + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"), + serialization.load_der_private_key, + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt") ) ] ) def test_private_bytes_values(self, key_path, loader_func, - backend): + vec_path, backend): + _skip_dhx_unsupported(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] + vec = load_vectors_from_file(vec_path, 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"]) + vec["g"], 16) assert private_numbers.public_numbers.parameter_numbers.p == int( vec["p"], 16) + if "q" in vec: + assert private_numbers.public_numbers.parameter_numbers.q == int( + vec["q"], 16) + else: + assert private_numbers.public_numbers.parameter_numbers.q is None def test_private_bytes_traditional_openssl_invalid(self, backend): parameters = dh.generate_parameters(2, 512, backend) @@ -469,11 +568,20 @@ class TestDHPublicKeySerialization(object): os.path.join("asymmetric", "DH", "dhpub.der"), serialization.load_der_public_key, serialization.Encoding.DER, + ), ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"), + serialization.load_pem_public_key, + serialization.Encoding.PEM, + ), ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"), + serialization.load_der_public_key, + serialization.Encoding.DER, ) ] ) def test_public_bytes_match(self, key_path, loader_func, encoding, backend): + _skip_dhx_unsupported(backend) key_bytes = load_vectors_from_file( key_path, lambda pemfile: pemfile.read(), mode="rb" @@ -486,31 +594,44 @@ class TestDHPublicKeySerialization(object): assert serialized == key_bytes @pytest.mark.parametrize( - ("key_path", "loader_func"), + ("key_path", "loader_func", "vec_path"), [ ( os.path.join("asymmetric", "DH", "dhpub.pem"), serialization.load_pem_public_key, + os.path.join("asymmetric", "DH", "dhkey.txt"), ), ( os.path.join("asymmetric", "DH", "dhpub.der"), serialization.load_der_public_key, + os.path.join("asymmetric", "DH", "dhkey.txt"), + ), ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"), + serialization.load_pem_public_key, + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"), + ), ( + os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"), + serialization.load_der_public_key, + os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"), ) ] ) def test_public_bytes_values(self, key_path, loader_func, - backend): + vec_path, backend): + _skip_dhx_unsupported(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] + vec = load_vectors_from_file(vec_path, 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.g == int(vec["g"], 16) assert public_numbers.parameter_numbers.p == int(vec["p"], 16) + if "q" in vec: + assert public_numbers.parameter_numbers.q == int(vec["q"], 16) + else: + assert public_numbers.parameter_numbers.q is None def test_public_bytes_invalid_encoding(self, backend): parameters = dh.generate_parameters(2, 512, backend) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index dad056c6..bc16b5f8 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -236,10 +236,12 @@ class TestDERSerialization(object): """).encode() bad_der = base64.b64decode(b"".join(key_data.splitlines())) - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key(bad_der, None, backend) - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key( bad_der, b"this password will not be used", backend ) @@ -575,12 +577,14 @@ class TestPEMSerialization(object): def test_wrong_private_format(self, backend): key_data = b"---- NOT A KEY ----\n" - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key( key_data, None, backend ) - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key( key_data, b"this password will not be used", backend ) @@ -588,7 +592,8 @@ class TestPEMSerialization(object): def test_wrong_public_format(self, backend): key_data = b"---- NOT A KEY ----\n" - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_public_key(key_data, backend) def test_corrupt_traditional_format(self, backend): @@ -720,12 +725,14 @@ class TestPEMSerialization(object): password = b"this password is wrong" - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key( key_data, None, backend ) - with pytest.raises(ValueError): + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): load_pem_private_key( key_data, password, backend ) diff --git a/vectors/cryptography_vectors/asymmetric/DH/RFC5114.txt b/vectors/cryptography_vectors/asymmetric/DH/RFC5114.txt index bb8e238f..08e9c129 100644 --- a/vectors/cryptography_vectors/asymmetric/DH/RFC5114.txt +++ b/vectors/cryptography_vectors/asymmetric/DH/RFC5114.txt @@ -1,4 +1,5 @@ [A.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup] +COUNT=0 P = B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371 Q = F518AA8781A8DF278ABA4E7D64B7CB9D49462353 G = A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5 @@ -14,6 +15,7 @@ Z = 5C804F454D30D9C4DF85271F93528C91DF6B48AB5F80B3B59CAAC1B28F8ACBA9CD3E39F3CB61 Result = P (0 - Correct) [A.2.2048-bitMODPGroupwith224-bitPrimeOrderSubgroup] +COUNT=1 P = AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F Q = 801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB G = AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D027275AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA @@ -29,6 +31,7 @@ Z = 34D9BDDC1B42176C313FEA034C21034D074A6313BB4ECDB3703FFF424567A46BDF75530EDE0A Result = P (0 - Correct) [A.3. 2048-bit MODP Group with 256-bit Prime Order Subgroup] +COUNT=2 P = 87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597 Q = 8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3 G = 3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659 diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der new file mode 100644 index 00000000..4db7c957 Binary files /dev/null and b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der differ diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem new file mode 100644 index 00000000..3356432b --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICXQIBADCCAjYGByqGSM4+AgEwggIpAoIBAQCtEH4ekSOp0NZg+qeVWcUfog1k +5Wg7n9G1SxWXth0Kdeb6FB35Wlbbr5o8QHuh3xXrPWiKMJwYDh3muFoSdKCmbT+B +Uq1qwhKQN8nt79pN+Nkej+9VtzlLetW30LbBIgfJ+Y0R7TTb9sa6CyyLvCe+agDg +oLnElwizv4oxcJGINoEoYTC8iYXbFgLnFEFdkzAngnPH3jHv3HMQ9xIf1aB0FZh9 +mtwKSG3N+TrMRDKDhzFddeGYxkGkgM2Gobnlh+i+YOacySiyucUhcuQTBC6bI/EL +Dhbnl2PJtT3PS6gKKeP7c8FrjnW5fvNj4v+jH3HPneU4TnG4HArE3/4MEOZPAoIB +AQCsQDLvTy2a453zC1yP/axQbN6+e4mZjK90hmoIz+T/46aCSk4Quabw3ZIfAacM +Svqrc513AMKfUsV9sXxiCoZSvl6QAajWatfBdmkQGZkCSvTQJydawTSLuKdi0FIb +yYriRxUEIuoe1AmTnVTadGDNtfbGslBxfL7xgOs0EY6Y0RlSmkXW+DRWbjAl4xaj +MO+7d6hvDBqxWwUa49QoyPistwqBNxULjusQ4YPt0Zlj3dniY+R3BYnvaqIef18v +84G1OczjQJ0TzVZq+7SNbAGRgeG8/pSzAmnt/nL+m2qkvXtaDxxxz/9MGcQY4fbs +AXmBvAh/KnBls4S4kNMZHyv6Ah0AgBwNNMWNk/6ZcXcQH4BTWkc4zry/OJqZs2Nx +6wQeAhxEYPzCd3Q1ssq2dHEOtoeo6KO1ZVs6WS2LFf3x +-----END PRIVATE KEY----- diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt new file mode 100644 index 00000000..e1999899 --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt @@ -0,0 +1,7 @@ + +COUNT = 0 +P = AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F +G = AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D027275AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA +Q = 801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB +Y = 0082c165bb576243ecf46d58c3d1501616955fca0320fa95ea11d2e6c1b9cf217676720dc1c08c85bf20c4d232b60a29a1e51c7b773bc645014587c525c86151b30d75486ec7b6c98efb5f74955b83116d01d0af1232af89213c2de574369d701aba9357300b920d3d8b98252d46c46952c16a5f33554b38317809c7b9add4701f5c158c1b7035e9fe39366ececb90d2896b78c523c4a577287ef5ba7a2663ed58aa20b5ec66e30f316610dfaa38583e495ab6af771c284387e660edbef4edb872e2e80e1d244ee95622e76d028e61c1e887c2aa792717362139f4dd26eafd49b2366eeb2350b01fe1b56022a2809e379559c37b375ba01c4eaacc14fd1b247837 +X = 4460fcc2777435b2cab674710eb687a8e8a3b5655b3a592d8b15fdf1 diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der b/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der new file mode 100644 index 00000000..666eb9a0 Binary files /dev/null and b/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der differ diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem b/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem new file mode 100644 index 00000000..8887cb17 --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem @@ -0,0 +1,14 @@ +-----BEGIN X9.42 DH PARAMETERS----- +MIICKQKCAQEArRB+HpEjqdDWYPqnlVnFH6INZOVoO5/RtUsVl7YdCnXm+hQd+VpW +26+aPEB7od8V6z1oijCcGA4d5rhaEnSgpm0/gVKtasISkDfJ7e/aTfjZHo/vVbc5 +S3rVt9C2wSIHyfmNEe002/bGugssi7wnvmoA4KC5xJcIs7+KMXCRiDaBKGEwvImF +2xYC5xRBXZMwJ4Jzx94x79xzEPcSH9WgdBWYfZrcCkhtzfk6zEQyg4cxXXXhmMZB +pIDNhqG55YfovmDmnMkosrnFIXLkEwQumyPxCw4W55djybU9z0uoCinj+3PBa451 +uX7zY+L/ox9xz53lOE5xuBwKxN/+DBDmTwKCAQEArEAy708tmuOd8wtcj/2sUGze +vnuJmYyvdIZqCM/k/+OmgkpOELmm8N2SHwGnDEr6q3OddwDCn1LFfbF8YgqGUr5e +kAGo1mrXwXZpEBmZAkr00CcnWsE0i7inYtBSG8mK4kcVBCLqHtQJk51U2nRgzbX2 +xrJQcXy+8YDrNBGOmNEZUppF1vg0Vm4wJeMWozDvu3eobwwasVsFGuPUKMj4rLcK +gTcVC47rEOGD7dGZY93Z4mPkdwWJ72qiHn9fL/OBtTnM40CdE81Wavu0jWwBkYHh +vP6UswJp7f5y/ptqpL17Wg8ccc//TBnEGOH27AF5gbwIfypwZbOEuJDTGR8r+gId +AIAcDTTFjZP+mXF3EB+AU1pHOM68vziambNjces= +-----END X9.42 DH PARAMETERS----- diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der b/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der new file mode 100644 index 00000000..ba8aec90 Binary files /dev/null and b/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der differ diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem b/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem new file mode 100644 index 00000000..94a7170a --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem @@ -0,0 +1,20 @@ +-----BEGIN PUBLIC KEY----- +MIIDRDCCAjYGByqGSM4+AgEwggIpAoIBAQCtEH4ekSOp0NZg+qeVWcUfog1k5Wg7 +n9G1SxWXth0Kdeb6FB35Wlbbr5o8QHuh3xXrPWiKMJwYDh3muFoSdKCmbT+BUq1q +whKQN8nt79pN+Nkej+9VtzlLetW30LbBIgfJ+Y0R7TTb9sa6CyyLvCe+agDgoLnE +lwizv4oxcJGINoEoYTC8iYXbFgLnFEFdkzAngnPH3jHv3HMQ9xIf1aB0FZh9mtwK +SG3N+TrMRDKDhzFddeGYxkGkgM2Gobnlh+i+YOacySiyucUhcuQTBC6bI/ELDhbn +l2PJtT3PS6gKKeP7c8FrjnW5fvNj4v+jH3HPneU4TnG4HArE3/4MEOZPAoIBAQCs +QDLvTy2a453zC1yP/axQbN6+e4mZjK90hmoIz+T/46aCSk4Quabw3ZIfAacMSvqr +c513AMKfUsV9sXxiCoZSvl6QAajWatfBdmkQGZkCSvTQJydawTSLuKdi0FIbyYri +RxUEIuoe1AmTnVTadGDNtfbGslBxfL7xgOs0EY6Y0RlSmkXW+DRWbjAl4xajMO+7 +d6hvDBqxWwUa49QoyPistwqBNxULjusQ4YPt0Zlj3dniY+R3BYnvaqIef18v84G1 +OczjQJ0TzVZq+7SNbAGRgeG8/pSzAmnt/nL+m2qkvXtaDxxxz/9MGcQY4fbsAXmB +vAh/KnBls4S4kNMZHyv6Ah0AgBwNNMWNk/6ZcXcQH4BTWkc4zry/OJqZs2Nx6wOC +AQYAAoIBAQCCwWW7V2JD7PRtWMPRUBYWlV/KAyD6leoR0ubBuc8hdnZyDcHAjIW/ +IMTSMrYKKaHlHHt3O8ZFAUWHxSXIYVGzDXVIbse2yY77X3SVW4MRbQHQrxIyr4kh +PC3ldDadcBq6k1cwC5INPYuYJS1GxGlSwWpfM1VLODF4Cce5rdRwH1wVjBtwNen+ +OTZuzsuQ0olreMUjxKV3KH71unomY+1YqiC17GbjDzFmEN+qOFg+SVq2r3ccKEOH +5mDtvvTtuHLi6A4dJE7pViLnbQKOYcHoh8KqeScXNiE59N0m6v1JsjZu6yNQsB/h +tWAiooCeN5VZw3s3W6AcTqrMFP0bJHg3 +-----END PUBLIC KEY----- -- cgit v1.2.3