diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-06-22 18:06:28 -0600 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-06-25 08:25:52 -0600 |
commit | 0197ed8dedcd24d3b690d1b76eb6866df14f56dd (patch) | |
tree | c773e0eb29ba4d16b5ce8dd1422dbff000711175 | |
parent | 42ee73b26e18fc9a03badd885a8a3847f3907cad (diff) | |
download | cryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.tar.gz cryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.tar.bz2 cryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.zip |
DSA opaque OpenSSL
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 90 | ||||
-rw-r--r-- | cryptography/hazmat/backends/openssl/dsa.py | 121 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/asymmetric/dsa.py | 78 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_dsa.py | 72 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_serialization.py | 68 |
5 files changed, 319 insertions, 110 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index d08cd3e4..e895da83 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -32,6 +32,7 @@ from cryptography.hazmat.backends.openssl.ciphers import ( _AESCTRCipherContext, _CipherContext ) from cryptography.hazmat.backends.openssl.dsa import ( + _DSAParameters, _DSAPrivateKey, _DSAPublicKey, _DSASignatureContext, _DSAVerificationContext ) from cryptography.hazmat.backends.openssl.ec import ( @@ -467,19 +468,10 @@ class Backend(object): dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) assert dsa_cdata != self._ffi.NULL dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) - return self._dsa_cdata_to_private_key(dsa_cdata) + return _DSAPrivateKey(self, dsa_cdata) else: raise UnsupportedAlgorithm("Unsupported key type.") - def _dsa_cdata_to_private_key(self, cdata): - return dsa.DSAPrivateKey( - modulus=self._bn_to_int(cdata.p), - subgroup_order=self._bn_to_int(cdata.q), - generator=self._bn_to_int(cdata.g), - x=self._bn_to_int(cdata.priv_key), - y=self._bn_to_int(cdata.pub_key) - ) - def _pem_password_cb(self, password): """ Generate a pem_password_cb function pointer that copied the password to @@ -615,37 +607,79 @@ class Backend(object): assert res == 1 - return dsa.DSAParameters( - modulus=self._bn_to_int(ctx.p), - subgroup_order=self._bn_to_int(ctx.q), - generator=self._bn_to_int(ctx.g) - ) + return _DSAParameters(self, ctx) def generate_dsa_private_key(self, parameters): ctx = self._lib.DSA_new() assert ctx != self._ffi.NULL ctx = self._ffi.gc(ctx, self._lib.DSA_free) - ctx.p = self._int_to_bn(parameters.p) - ctx.q = self._int_to_bn(parameters.q) - ctx.g = self._int_to_bn(parameters.g) + if isinstance(parameters, dsa.DSAParameters): + ctx.p = self._int_to_bn(parameters.p) + ctx.q = self._int_to_bn(parameters.q) + ctx.g = self._int_to_bn(parameters.g) + else: + ctx.p = self._lib.BN_dup(parameters._dsa_cdata.p) + ctx.q = self._lib.BN_dup(parameters._dsa_cdata.q) + ctx.g = self._lib.BN_dup(parameters._dsa_cdata.g) self._lib.DSA_generate_key(ctx) - return dsa.DSAPrivateKey( - modulus=self._bn_to_int(ctx.p), - subgroup_order=self._bn_to_int(ctx.q), - generator=self._bn_to_int(ctx.g), - x=self._bn_to_int(ctx.priv_key), - y=self._bn_to_int(ctx.pub_key) - ) + return _DSAPrivateKey(self, ctx) def create_dsa_signature_ctx(self, private_key, algorithm): - return _DSASignatureContext(self, private_key, algorithm) + dsa_cdata = self._dsa_cdata_from_private_key(private_key) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + key = _DSAPrivateKey(self, dsa_cdata) + return _DSASignatureContext(self, key, algorithm) def create_dsa_verification_ctx(self, public_key, signature, algorithm): - return _DSAVerificationContext(self, public_key, signature, - algorithm) + dsa_cdata = self._dsa_cdata_from_public_key(public_key) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + key = _DSAPublicKey(self, dsa_cdata) + return _DSAVerificationContext(self, key, signature, algorithm) + + def load_dsa_private_numbers(self, numbers): + parameter_numbers = numbers.public_numbers.parameter_numbers + dsa._check_dsa_parameters(parameter_numbers) + dsa_cdata = self._lib.DSA_new() + assert dsa_cdata != self._ffi.NULL + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + dsa_cdata.p = self._int_to_bn(parameter_numbers.p) + dsa_cdata.q = self._int_to_bn(parameter_numbers.q) + dsa_cdata.g = self._int_to_bn(parameter_numbers.g) + dsa_cdata.pub_key = self._int_to_bn(numbers.public_numbers.y) + dsa_cdata.priv_key = self._int_to_bn(numbers.x) + + return _DSAPrivateKey(self, dsa_cdata) + + def load_dsa_public_numbers(self, numbers): + dsa._check_dsa_parameters(numbers.parameter_numbers) + # TODO check more + dsa_cdata = self._lib.DSA_new() + assert dsa_cdata != self._ffi.NULL + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + dsa_cdata.p = self._int_to_bn(numbers.parameter_numbers.p) + dsa_cdata.q = self._int_to_bn(numbers.parameter_numbers.q) + dsa_cdata.g = self._int_to_bn(numbers.parameter_numbers.g) + dsa_cdata.pub_key = self._int_to_bn(numbers.y) + + return _DSAPublicKey(self, dsa_cdata) + + def load_dsa_parameter_numbers(self, numbers): + dsa._check_dsa_parameters(numbers) + # TODO check more + dsa_cdata = self._lib.DSA_new() + assert dsa_cdata != self._ffi.NULL + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + dsa_cdata.p = self._int_to_bn(numbers.p) + dsa_cdata.q = self._int_to_bn(numbers.q) + dsa_cdata.g = self._int_to_bn(numbers.g) + + return _DSAParameters(self, dsa_cdata) def _dsa_cdata_from_public_key(self, public_key): # Does not GC the DSA cdata. You *must* make sure it's freed diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py index ec05c3aa..d492372f 100644 --- a/cryptography/hazmat/backends/openssl/dsa.py +++ b/cryptography/hazmat/backends/openssl/dsa.py @@ -16,6 +16,10 @@ from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes, interfaces +from cryptography.hazmat.primitives.asymmetric import dsa +from cryptography.hazmat.primitives.interfaces import ( + DSAParametersWithNumbers, DSAPrivateKeyWithNumbers, DSAPublicKeyWithNumbers +) @utils.register_interface(interfaces.AsymmetricVerificationContext) @@ -32,9 +36,7 @@ class _DSAVerificationContext(object): self._hash_ctx.update(data) def verify(self): - self._dsa_cdata = self._backend._dsa_cdata_from_public_key( - self._public_key) - self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata, + self._dsa_cdata = self._backend._ffi.gc(self._public_key._dsa_cdata, self._backend._lib.DSA_free) data_to_verify = self._hash_ctx.finalize() @@ -43,7 +45,7 @@ class _DSAVerificationContext(object): # must be an integer. res = self._backend._lib.DSA_verify( 0, data_to_verify, len(data_to_verify), self._signature, - len(self._signature), self._dsa_cdata) + len(self._signature), self._public_key._dsa_cdata) if res != 1: errors = self._backend._consume_errors() @@ -61,17 +63,13 @@ class _DSASignatureContext(object): self._private_key = private_key self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) - self._dsa_cdata = self._backend._dsa_cdata_from_private_key( - self._private_key) - self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata, - self._backend._lib.DSA_free) def update(self, data): self._hash_ctx.update(data) def finalize(self): data_to_sign = self._hash_ctx.finalize() - sig_buf_len = self._backend._lib.DSA_size(self._dsa_cdata) + sig_buf_len = self._backend._lib.DSA_size(self._private_key._dsa_cdata) sig_buf = self._backend._ffi.new("unsigned char[]", sig_buf_len) buflen = self._backend._ffi.new("unsigned int *") @@ -79,8 +77,111 @@ class _DSASignatureContext(object): # must be an integer. res = self._backend._lib.DSA_sign( 0, data_to_sign, len(data_to_sign), sig_buf, - buflen, self._dsa_cdata) + buflen, self._private_key._dsa_cdata) assert res == 1 assert buflen[0] return self._backend._ffi.buffer(sig_buf)[:buflen[0]] + + +@utils.register_interface(DSAParametersWithNumbers) +class _DSAParameters(object): + def __init__(self, backend, dsa_cdata): + self._backend = backend + self._dsa_cdata = dsa_cdata + + def parameter_numbers(self): + return dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(self._dsa_cdata.p), + q=self._backend._bn_to_int(self._dsa_cdata.q), + g=self._backend._bn_to_int(self._dsa_cdata.g) + ) + + +@utils.register_interface(DSAPrivateKeyWithNumbers) +class _DSAPrivateKey(object): + def __init__(self, backend, dsa_cdata): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p) + + @property + def key_size(self): + return self._key_size + + def signer(self, algorithm): + return _DSASignatureContext(self._backend, self, algorithm) + + def private_numbers(self): + return dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(self._dsa_cdata.p), + q=self._backend._bn_to_int(self._dsa_cdata.q), + g=self._backend._bn_to_int(self._dsa_cdata.g) + ), + y=self._backend._bn_to_int(self._dsa_cdata.pub_key) + ), + x=self._backend._bn_to_int(self._dsa_cdata.priv_key) + ) + + def public_key(self): + dsa_cdata = self._backend._lib.DSA_new() + assert dsa_cdata != self._backend._ffi.NULL + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p) + dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q) + dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g) + dsa_cdata.pub_key = self._backend._lib.BN_dup(self._dsa_cdata.pub_key) + return _DSAPublicKey(self._backend, dsa_cdata) + + def parameters(self): + dsa_cdata = self._backend._lib.DSA_new() + assert dsa_cdata != self._backend._ffi.NULL + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p) + dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q) + dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g) + return _DSAParameters(self._backend, dsa_cdata) + + +@utils.register_interface(DSAPublicKeyWithNumbers) +class _DSAPublicKey(object): + def __init__(self, backend, dsa_cdata): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p) + + @property + def key_size(self): + return self._key_size + + def verifier(self, signature, algorithm): + return _DSAVerificationContext( + self._backend, self, signature, algorithm + ) + + def public_numbers(self): + return dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(self._dsa_cdata.p), + q=self._backend._bn_to_int(self._dsa_cdata.q), + g=self._backend._bn_to_int(self._dsa_cdata.g) + ), + y=self._backend._bn_to_int(self._dsa_cdata.pub_key) + ) + + def parameters(self): + dsa_cdata = self._backend._lib.DSA_new() + assert dsa_cdata != self._backend._ffi.NULL + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p) + dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q) + dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g) + return _DSAParameters(self._backend, dsa_cdata) diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py index 4d78679e..4675bd0a 100644 --- a/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -21,31 +21,38 @@ from cryptography.hazmat.backends.interfaces import DSABackend from cryptography.hazmat.primitives import interfaces -def _check_dsa_parameters(modulus, subgroup_order, generator): - if ( - not isinstance(modulus, six.integer_types) or - not isinstance(subgroup_order, six.integer_types) or - not isinstance(generator, six.integer_types) - ): - raise TypeError("DSA parameters must be integers.") - - if (utils.bit_length(modulus), - utils.bit_length(subgroup_order)) not in ( +def generate_parameters(key_size, backend): + return backend.generate_dsa_parameters(key_size) + + +def generate_private_key(parameters): + return parameters._backend.generate_dsa_private_key(parameters) + + +def _check_dsa_parameters(parameters): + if (utils.bit_length(parameters.p), + utils.bit_length(parameters.q)) not in ( (1024, 160), (2048, 256), (3072, 256)): - raise ValueError("modulus and subgroup_order lengths must be " + raise ValueError("p and q lengths must be " "one of these pairs (1024, 160) or (2048, 256) " "or (3072, 256).") - if generator <= 1 or generator >= modulus: - raise ValueError("generator must be > 1 and < modulus.") + if parameters.g <= 1 or parameters.g >= parameters.p: + raise ValueError("g must be > 1 and < p.") @utils.register_interface(interfaces.DSAParameters) class DSAParameters(object): def __init__(self, modulus, subgroup_order, generator): - _check_dsa_parameters(modulus, subgroup_order, generator) + _check_dsa_parameters( + DSAParameterNumbers( + p=modulus, + q=subgroup_order, + g=generator + ) + ) self._modulus = modulus self._subgroup_order = subgroup_order @@ -59,7 +66,13 @@ class DSAParameters(object): _Reasons.BACKEND_MISSING_INTERFACE ) - return backend.generate_dsa_parameters(key_size) + parameters = backend.generate_dsa_parameters(key_size) + numbers = parameters.parameter_numbers() + return cls( + modulus=numbers.p, + subgroup_order=numbers.q, + generator=numbers.g + ) @property def modulus(self): @@ -89,7 +102,13 @@ class DSAParameters(object): @utils.register_interface(interfaces.DSAPrivateKey) class DSAPrivateKey(object): def __init__(self, modulus, subgroup_order, generator, x, y): - _check_dsa_parameters(modulus, subgroup_order, generator) + _check_dsa_parameters( + DSAParameterNumbers( + p=modulus, + q=subgroup_order, + g=generator + ) + ) if ( not isinstance(x, six.integer_types) or not isinstance(y, six.integer_types) @@ -116,7 +135,15 @@ class DSAPrivateKey(object): _Reasons.BACKEND_MISSING_INTERFACE ) - return backend.generate_dsa_private_key(parameters) + key = backend.generate_dsa_private_key(parameters) + private_numbers = key.private_numbers() + return cls( + modulus=private_numbers.public_numbers.parameter_numbers.p, + subgroup_order=private_numbers.public_numbers.parameter_numbers.q, + generator=private_numbers.public_numbers.parameter_numbers.g, + x=private_numbers.x, + y=private_numbers.public_numbers.y + ) def signer(self, algorithm, backend): if not isinstance(backend, DSABackend): @@ -151,7 +178,13 @@ class DSAPrivateKey(object): @utils.register_interface(interfaces.DSAPublicKey) class DSAPublicKey(object): def __init__(self, modulus, subgroup_order, generator, y): - _check_dsa_parameters(modulus, subgroup_order, generator) + _check_dsa_parameters( + DSAParameterNumbers( + p=modulus, + q=subgroup_order, + g=generator + ) + ) if not isinstance(y, six.integer_types): raise TypeError("y must be an integer.") @@ -210,6 +243,9 @@ class DSAParameterNumbers(object): def g(self): return self._g + def parameters(self, backend): + return backend.load_dsa_parameter_numbers(self) + class DSAPublicNumbers(object): def __init__(self, y, parameter_numbers): @@ -232,6 +268,9 @@ class DSAPublicNumbers(object): def parameter_numbers(self): return self._parameter_numbers + def public_key(self, backend): + return backend.load_dsa_public_numbers(self) + class DSAPrivateNumbers(object): def __init__(self, x, public_numbers): @@ -252,3 +291,6 @@ class DSAPrivateNumbers(object): @property def public_numbers(self): return self._public_numbers + + def private_key(self, backend): + return backend.load_dsa_private_numbers(self) diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 1c266baa..76436f79 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -20,7 +20,7 @@ import pytest from cryptography.exceptions import ( AlreadyFinalized, InvalidSignature, _Reasons) -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, interfaces from cryptography.hazmat.primitives.asymmetric import dsa from cryptography.utils import bit_length @@ -70,10 +70,15 @@ def _check_dsa_private_key(skey): @pytest.mark.dsa class TestDSA(object): - def test_generate_dsa_parameters(self, backend): + def test_generate_dsa_parameters_class_method(self, backend): parameters = dsa.DSAParameters.generate(1024, backend) assert bit_length(parameters.p) == 1024 + def test_generate_dsa_parameters(self, backend): + parameters = dsa.generate_parameters(1024, backend) + assert isinstance(parameters, interfaces.DSAParameters) + # TODO: withnumbers check like RSA + def test_generate_invalid_dsa_parameters(self, backend): with pytest.raises(ValueError): dsa.DSAParameters.generate(1, backend) @@ -87,17 +92,31 @@ class TestDSA(object): ) ) def test_generate_dsa_keys(self, vector, backend): - parameters = dsa.DSAParameters(modulus=vector['p'], - subgroup_order=vector['q'], - generator=vector['g']) - skey = dsa.DSAPrivateKey.generate(parameters, backend) - - skey_parameters = skey.parameters() - assert skey_parameters.p == vector['p'] - assert skey_parameters.q == vector['q'] - assert skey_parameters.g == vector['g'] - assert skey.key_size == bit_length(vector['p']) - assert skey.y == pow(skey_parameters.g, skey.x, skey_parameters.p) + parameters = dsa.DSAParameterNumbers( + p=vector['p'], + q=vector['q'], + g=vector['g'] + ).parameters(backend) + skey = dsa.generate_private_key(parameters) + if isinstance(skey, interfaces.DSAPrivateKeyWithNumbers): + numbers = skey.private_numbers() + skey_parameters = numbers.public_numbers.parameter_numbers + pkey = skey.public_key() + parameters = pkey.parameters() + parameter_numbers = parameters.parameter_numbers() + assert parameter_numbers.p == skey_parameters.p + assert parameter_numbers.q == skey_parameters.q + assert parameter_numbers.g == skey_parameters.g + assert skey_parameters.p == vector['p'] + assert skey_parameters.q == vector['q'] + assert skey_parameters.g == vector['g'] + assert skey.key_size == bit_length(vector['p']) + assert pkey.key_size == skey.key_size + public_numbers = pkey.public_numbers() + assert numbers.public_numbers.y == public_numbers.y + assert numbers.public_numbers.y == pow( + skey_parameters.g, numbers.x, skey_parameters.p + ) def test_invalid_parameters_argument_types(self): with pytest.raises(TypeError): @@ -654,11 +673,14 @@ class TestDSAVerification(object): "{0} does not support the provided parameters".format(backend) ) - public_key = dsa.DSAPublicKey( - vector['p'], vector['q'], vector['g'], vector['y'] - ) + public_key = dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + vector['p'], vector['q'], vector['g'] + ), + y=vector['y'] + ).public_key(backend) sig = der_encode_dsa_signature(vector['r'], vector['s']) - verifier = public_key.verifier(sig, algorithm(), backend) + verifier = public_key.verifier(sig, algorithm()) verifier.update(vector['msg']) if vector['result'] == "F": with pytest.raises(InvalidSignature): @@ -728,16 +750,22 @@ class TestDSASignature(object): "{0} does not support the provided parameters".format(backend) ) - private_key = dsa.DSAPrivateKey( - vector['p'], vector['q'], vector['g'], vector['x'], vector['y'] - ) - signer = private_key.signer(algorithm(), backend) + private_key = dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + vector['p'], vector['q'], vector['g'] + ), + y=vector['y'] + ), + x=vector['x'] + ).private_key(backend) + signer = private_key.signer(algorithm()) signer.update(vector['msg']) signature = signer.finalize() assert signature public_key = private_key.public_key() - verifier = public_key.verifier(signature, algorithm(), backend) + verifier = public_key.verifier(signature, algorithm()) verifier.update(vector['msg']) verifier.verify() diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 8a90b30e..30ac4f3d 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -21,7 +21,6 @@ import pytest from cryptography.exceptions import _Reasons from cryptography.hazmat.primitives import interfaces -from cryptography.hazmat.primitives.asymmetric import dsa from cryptography.hazmat.primitives.serialization import ( load_pem_pkcs8_private_key, load_pem_traditional_openssl_private_key ) @@ -73,7 +72,7 @@ class TestTraditionalOpenSSLSerialisation(object): ) assert key - assert isinstance(key, dsa.DSAPrivateKey) + assert isinstance(key, interfaces.DSAPrivateKey) def test_key1_pem_encrypted_values(self, backend): pkey = load_vectors_from_file( @@ -480,41 +479,46 @@ class TestPKCS8Serialisation(object): ) ) assert key - assert isinstance(key, dsa.DSAPrivateKey) + assert isinstance(key, interfaces.DSAPrivateKey) params = key.parameters() - assert isinstance(params, dsa.DSAParameters) - - assert key.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", 16) - assert key.y == int( - "2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1" - "70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d" - "2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350" - "70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6" - "ab6bcce04bfdf5b6", - 16 - ) + assert isinstance(params, interfaces.DSAParameters) + + if isinstance(params, interfaces.DSAParametersWithNumbers): + num = key.private_numbers() + pub = num.public_numbers + parameter_numbers = pub.parameter_numbers + assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", + 16) + assert pub.y == int( + "2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1" + "70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d" + "2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350" + "70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6" + "ab6bcce04bfdf5b6", + 16 + ) - assert params.p == int( - "00aa0930cc145825221caffa28ac2894196a27833de5ec21270791689420" - "7774a2e7b238b0d36f1b2499a2c2585083eb01432924418d867faa212dd1" - "071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb" - "8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05" - "940cabe5d2de49a167", - 16 - ) + assert parameter_numbers.p == int( + "00aa0930cc145825221caffa28ac2894196a27833de5ec21270791689420" + "7774a2e7b238b0d36f1b2499a2c2585083eb01432924418d867faa212dd1" + "071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb" + "8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05" + "940cabe5d2de49a167", + 16 + ) - assert params.q == int("00adc0e869b36f0ac013a681fdf4d4899d69820451", - 16) + assert parameter_numbers.q == int( + "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16) - assert params.g == int( - "008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e" - "e13201ff48890bbfc33d79bacaec71e7a778507bd5f1a66422e39415be03" - "e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10" - "1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc" - "68ce5cfff241cd3246", - 16 - ) + assert parameter_numbers.g == int( + "008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e" + "e13201ff48890bbfc33d79bacaec71e7a778507bd5f1a66422e39415be03" + "e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10" + "1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc" + "68ce5cfff241cd3246", + 16 + ) @pytest.mark.parametrize( ("key_file", "password"), |