| # This file is dual licensed under the terms of the Apache License, Version |
| # 2.0, and the BSD License. See the LICENSE file in the root of this repository |
| # for complete details. |
| |
| from __future__ import absolute_import, division, print_function |
| |
| import itertools |
| import os |
| |
| import pytest |
| |
| from cryptography.exceptions import AlreadyFinalized, InvalidSignature |
| from cryptography.hazmat.backends.interfaces import ( |
| DSABackend, PEMSerializationBackend |
| ) |
| from cryptography.hazmat.primitives import hashes, serialization |
| from cryptography.hazmat.primitives.asymmetric import dsa |
| from cryptography.hazmat.primitives.asymmetric.utils import ( |
| Prehashed, encode_dss_signature |
| ) |
| from cryptography.utils import CryptographyDeprecationWarning |
| |
| from .fixtures_dsa import ( |
| DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072 |
| ) |
| from ...doubles import DummyHashAlgorithm, DummyKeySerializationEncryption |
| from ...utils import ( |
| load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors, |
| load_vectors_from_file, |
| ) |
| |
| |
| def _skip_if_dsa_not_supported(backend, algorithm, p, q, g): |
| if ( |
| not backend.dsa_parameters_supported(p, q, g) or |
| not backend.dsa_hash_supported(algorithm) |
| ): |
| pytest.skip( |
| "{0} does not support the provided parameters".format(backend) |
| ) |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| def test_skip_if_dsa_not_supported(backend): |
| with pytest.raises(pytest.skip.Exception): |
| _skip_if_dsa_not_supported(backend, DummyHashAlgorithm(), 1, 1, 1) |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| class TestDSA(object): |
| def test_generate_dsa_parameters(self, backend): |
| parameters = dsa.generate_parameters(1024, backend) |
| assert isinstance(parameters, dsa.DSAParameters) |
| |
| def test_generate_invalid_dsa_parameters(self, backend): |
| with pytest.raises(ValueError): |
| dsa.generate_parameters(1, backend) |
| |
| @pytest.mark.parametrize( |
| "vector", |
| load_vectors_from_file( |
| os.path.join( |
| "asymmetric", "DSA", "FIPS_186-3", "KeyPair.rsp"), |
| load_fips_dsa_key_pair_vectors |
| ) |
| ) |
| def test_generate_dsa_keys(self, vector, backend): |
| parameters = dsa.DSAParameterNumbers( |
| p=vector['p'], |
| q=vector['q'], |
| g=vector['g'] |
| ).parameters(backend) |
| skey = parameters.generate_private_key() |
| 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 == vector['p'].bit_length() |
| 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_generate_dsa_private_key_and_parameters(self, backend): |
| skey = dsa.generate_private_key(1024, backend) |
| assert skey |
| numbers = skey.private_numbers() |
| skey_parameters = numbers.public_numbers.parameter_numbers |
| assert numbers.public_numbers.y == pow( |
| skey_parameters.g, numbers.x, skey_parameters.p |
| ) |
| |
| @pytest.mark.parametrize( |
| ("p", "q", "g"), |
| [ |
| ( |
| 2 ** 1000, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| 2 ** 2000, |
| DSA_KEY_2048.public_numbers.parameter_numbers.q, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| 2 ** 3000, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| 2 ** 3100, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| 2 ** 150, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| DSA_KEY_2048.public_numbers.parameter_numbers.p, |
| 2 ** 250, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g |
| ), |
| ( |
| DSA_KEY_3072.public_numbers.parameter_numbers.p, |
| 2 ** 260, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 0 |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 1 |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 2 ** 1200 |
| ), |
| ] |
| ) |
| def test_invalid_parameters_values(self, p, q, g, backend): |
| with pytest.raises(ValueError): |
| dsa.DSAParameterNumbers(p, q, g).parameters(backend) |
| |
| @pytest.mark.parametrize( |
| ("p", "q", "g", "y", "x"), |
| [ |
| ( |
| 2 ** 1000, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| DSA_KEY_1024.x, |
| ), |
| ( |
| 2 ** 2000, |
| DSA_KEY_2048.public_numbers.parameter_numbers.q, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g, |
| DSA_KEY_2048.public_numbers.y, |
| DSA_KEY_2048.x, |
| ), |
| ( |
| 2 ** 3000, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| DSA_KEY_3072.x, |
| ), |
| ( |
| 2 ** 3100, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| DSA_KEY_3072.x, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| 2 ** 150, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| DSA_KEY_1024.x, |
| ), |
| ( |
| DSA_KEY_2048.public_numbers.parameter_numbers.p, |
| 2 ** 250, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g, |
| DSA_KEY_2048.public_numbers.y, |
| DSA_KEY_2048.x, |
| ), |
| ( |
| DSA_KEY_3072.public_numbers.parameter_numbers.p, |
| 2 ** 260, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| DSA_KEY_3072.x, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 0, |
| DSA_KEY_1024.public_numbers.y, |
| DSA_KEY_1024.x, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 1, |
| DSA_KEY_1024.public_numbers.y, |
| DSA_KEY_1024.x, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 2 ** 1200, |
| DSA_KEY_1024.public_numbers.y, |
| DSA_KEY_1024.x, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| 0, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| -2, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| 2 ** 159, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| 2 ** 200, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| 2 ** 100, |
| DSA_KEY_1024.x |
| ), |
| ] |
| ) |
| def test_invalid_dsa_private_key_arguments(self, p, q, g, y, x, backend): |
| with pytest.raises(ValueError): |
| dsa.DSAPrivateNumbers( |
| public_numbers=dsa.DSAPublicNumbers( |
| parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g), |
| y=y |
| ), x=x |
| ).private_key(backend) |
| |
| @pytest.mark.parametrize( |
| ("p", "q", "g", "y"), |
| [ |
| ( |
| 2 ** 1000, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| ), |
| ( |
| 2 ** 2000, |
| DSA_KEY_2048.public_numbers.parameter_numbers.q, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g, |
| DSA_KEY_2048.public_numbers.y, |
| ), |
| ( |
| 2 ** 3000, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| ), |
| ( |
| 2 ** 3100, |
| DSA_KEY_3072.public_numbers.parameter_numbers.q, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| 2 ** 150, |
| DSA_KEY_1024.public_numbers.parameter_numbers.g, |
| DSA_KEY_1024.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_2048.public_numbers.parameter_numbers.p, |
| 2 ** 250, |
| DSA_KEY_2048.public_numbers.parameter_numbers.g, |
| DSA_KEY_2048.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_3072.public_numbers.parameter_numbers.p, |
| 2 ** 260, |
| DSA_KEY_3072.public_numbers.parameter_numbers.g, |
| DSA_KEY_3072.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 0, |
| DSA_KEY_1024.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 1, |
| DSA_KEY_1024.public_numbers.y, |
| ), |
| ( |
| DSA_KEY_1024.public_numbers.parameter_numbers.p, |
| DSA_KEY_1024.public_numbers.parameter_numbers.q, |
| 2 ** 1200, |
| DSA_KEY_1024.public_numbers.y, |
| ), |
| ] |
| ) |
| def test_invalid_dsa_public_key_arguments(self, p, q, g, y, backend): |
| with pytest.raises(ValueError): |
| dsa.DSAPublicNumbers( |
| parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g), |
| y=y |
| ).public_key(backend) |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| class TestDSAVerification(object): |
| _algorithms_dict = { |
| 'SHA1': hashes.SHA1, |
| 'SHA224': hashes.SHA224, |
| 'SHA256': hashes.SHA256, |
| 'SHA384': hashes.SHA384, |
| 'SHA512': hashes.SHA512 |
| } |
| |
| @pytest.mark.parametrize( |
| "vector", |
| load_vectors_from_file( |
| os.path.join( |
| "asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"), |
| load_fips_dsa_sig_vectors |
| ) |
| ) |
| def test_dsa_verification(self, vector, backend): |
| digest_algorithm = vector['digest_algorithm'].replace("-", "") |
| algorithm = self._algorithms_dict[digest_algorithm] |
| |
| _skip_if_dsa_not_supported( |
| backend, algorithm, vector['p'], vector['q'], vector['g'] |
| ) |
| |
| public_key = dsa.DSAPublicNumbers( |
| parameter_numbers=dsa.DSAParameterNumbers( |
| vector['p'], vector['q'], vector['g'] |
| ), |
| y=vector['y'] |
| ).public_key(backend) |
| sig = encode_dss_signature(vector['r'], vector['s']) |
| |
| if vector['result'] == "F": |
| with pytest.raises(InvalidSignature): |
| public_key.verify(sig, vector['msg'], algorithm()) |
| else: |
| public_key.verify(sig, vector['msg'], algorithm()) |
| |
| def test_dsa_verify_invalid_asn1(self, backend): |
| public_key = DSA_KEY_1024.public_numbers.public_key(backend) |
| with pytest.raises(InvalidSignature): |
| public_key.verify(b'fakesig', b'fakemsg', hashes.SHA1()) |
| |
| def test_signature_not_bytes(self, backend): |
| public_key = DSA_KEY_1024.public_numbers.public_key(backend) |
| with pytest.raises(TypeError), \ |
| pytest.warns(CryptographyDeprecationWarning): |
| public_key.verifier(1234, hashes.SHA1()) |
| |
| def test_use_after_finalize(self, backend): |
| public_key = DSA_KEY_1024.public_numbers.public_key(backend) |
| with pytest.warns(CryptographyDeprecationWarning): |
| verifier = public_key.verifier(b'fakesig', hashes.SHA1()) |
| verifier.update(b'irrelevant') |
| with pytest.raises(InvalidSignature): |
| verifier.verify() |
| with pytest.raises(AlreadyFinalized): |
| verifier.verify() |
| with pytest.raises(AlreadyFinalized): |
| verifier.update(b"more data") |
| |
| def test_verify(self, backend): |
| message = b"one little message" |
| algorithm = hashes.SHA1() |
| private_key = DSA_KEY_1024.private_key(backend) |
| signature = private_key.sign(message, algorithm) |
| public_key = private_key.public_key() |
| public_key.verify(signature, message, algorithm) |
| |
| def test_prehashed_verify(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| message = b"one little message" |
| h = hashes.Hash(hashes.SHA1(), backend) |
| h.update(message) |
| digest = h.finalize() |
| prehashed_alg = Prehashed(hashes.SHA1()) |
| signature = private_key.sign(message, hashes.SHA1()) |
| public_key = private_key.public_key() |
| public_key.verify(signature, digest, prehashed_alg) |
| |
| def test_prehashed_digest_mismatch(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| public_key = private_key.public_key() |
| message = b"one little message" |
| h = hashes.Hash(hashes.SHA1(), backend) |
| h.update(message) |
| digest = h.finalize() |
| prehashed_alg = Prehashed(hashes.SHA224()) |
| with pytest.raises(ValueError): |
| public_key.verify(b"\x00" * 128, digest, prehashed_alg) |
| |
| def test_prehashed_unsupported_in_signer_ctx(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| with pytest.raises(TypeError), \ |
| pytest.warns(CryptographyDeprecationWarning): |
| private_key.signer(Prehashed(hashes.SHA1())) |
| |
| def test_prehashed_unsupported_in_verifier_ctx(self, backend): |
| public_key = DSA_KEY_1024.private_key(backend).public_key() |
| with pytest.raises(TypeError), \ |
| pytest.warns(CryptographyDeprecationWarning): |
| public_key.verifier( |
| b"0" * 64, Prehashed(hashes.SHA1()) |
| ) |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| class TestDSASignature(object): |
| _algorithms_dict = { |
| 'SHA1': hashes.SHA1, |
| 'SHA224': hashes.SHA224, |
| 'SHA256': hashes.SHA256, |
| 'SHA384': hashes.SHA384, |
| 'SHA512': hashes.SHA512} |
| |
| @pytest.mark.parametrize( |
| "vector", |
| load_vectors_from_file( |
| os.path.join( |
| "asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"), |
| load_fips_dsa_sig_vectors |
| ) |
| ) |
| def test_dsa_signing(self, vector, backend): |
| digest_algorithm = vector['digest_algorithm'].replace("-", "") |
| algorithm = self._algorithms_dict[digest_algorithm] |
| |
| _skip_if_dsa_not_supported( |
| backend, algorithm, vector['p'], vector['q'], vector['g'] |
| ) |
| |
| 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) |
| signature = private_key.sign(vector['msg'], algorithm()) |
| assert signature |
| |
| private_key.public_key().verify(signature, vector['msg'], algorithm()) |
| |
| def test_use_after_finalize(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| with pytest.warns(CryptographyDeprecationWarning): |
| signer = private_key.signer(hashes.SHA1()) |
| signer.update(b"data") |
| signer.finalize() |
| with pytest.raises(AlreadyFinalized): |
| signer.finalize() |
| with pytest.raises(AlreadyFinalized): |
| signer.update(b"more data") |
| |
| def test_sign(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| message = b"one little message" |
| algorithm = hashes.SHA1() |
| signature = private_key.sign(message, algorithm) |
| public_key = private_key.public_key() |
| public_key.verify(signature, message, algorithm) |
| |
| def test_prehashed_sign(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| message = b"one little message" |
| h = hashes.Hash(hashes.SHA1(), backend) |
| h.update(message) |
| digest = h.finalize() |
| prehashed_alg = Prehashed(hashes.SHA1()) |
| signature = private_key.sign(digest, prehashed_alg) |
| public_key = private_key.public_key() |
| public_key.verify(signature, message, hashes.SHA1()) |
| |
| def test_prehashed_digest_mismatch(self, backend): |
| private_key = DSA_KEY_1024.private_key(backend) |
| message = b"one little message" |
| h = hashes.Hash(hashes.SHA1(), backend) |
| h.update(message) |
| digest = h.finalize() |
| prehashed_alg = Prehashed(hashes.SHA224()) |
| with pytest.raises(ValueError): |
| private_key.sign(digest, prehashed_alg) |
| |
| |
| class TestDSANumbers(object): |
| def test_dsa_parameter_numbers(self): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| assert parameter_numbers.p == 1 |
| assert parameter_numbers.q == 2 |
| assert parameter_numbers.g == 3 |
| |
| def test_dsa_parameter_numbers_invalid_types(self): |
| with pytest.raises(TypeError): |
| dsa.DSAParameterNumbers(p=None, q=2, g=3) |
| |
| with pytest.raises(TypeError): |
| dsa.DSAParameterNumbers(p=1, q=None, g=3) |
| |
| with pytest.raises(TypeError): |
| dsa.DSAParameterNumbers(p=1, q=2, g=None) |
| |
| def test_dsa_public_numbers(self): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| public_numbers = dsa.DSAPublicNumbers( |
| y=4, |
| parameter_numbers=parameter_numbers |
| ) |
| assert public_numbers.y == 4 |
| assert public_numbers.parameter_numbers == parameter_numbers |
| |
| def test_dsa_public_numbers_invalid_types(self): |
| with pytest.raises(TypeError): |
| dsa.DSAPublicNumbers(y=4, parameter_numbers=None) |
| |
| with pytest.raises(TypeError): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| dsa.DSAPublicNumbers(y=None, parameter_numbers=parameter_numbers) |
| |
| def test_dsa_private_numbers(self): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| public_numbers = dsa.DSAPublicNumbers( |
| y=4, |
| parameter_numbers=parameter_numbers |
| ) |
| private_numbers = dsa.DSAPrivateNumbers( |
| x=5, |
| public_numbers=public_numbers |
| ) |
| assert private_numbers.x == 5 |
| assert private_numbers.public_numbers == public_numbers |
| |
| def test_dsa_private_numbers_invalid_types(self): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| public_numbers = dsa.DSAPublicNumbers( |
| y=4, |
| parameter_numbers=parameter_numbers |
| ) |
| with pytest.raises(TypeError): |
| dsa.DSAPrivateNumbers(x=4, public_numbers=None) |
| |
| with pytest.raises(TypeError): |
| dsa.DSAPrivateNumbers(x=None, public_numbers=public_numbers) |
| |
| def test_repr(self): |
| parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) |
| assert ( |
| repr(parameter_numbers) == "<DSAParameterNumbers(p=1, q=2, g=3)>" |
| ) |
| |
| public_numbers = dsa.DSAPublicNumbers( |
| y=4, |
| parameter_numbers=parameter_numbers |
| ) |
| assert repr(public_numbers) == ( |
| "<DSAPublicNumbers(y=4, parameter_numbers=<DSAParameterNumbers(p=1" |
| ", q=2, g=3)>)>" |
| ) |
| |
| |
| class TestDSANumberEquality(object): |
| def test_parameter_numbers_eq(self): |
| param = dsa.DSAParameterNumbers(1, 2, 3) |
| assert param == dsa.DSAParameterNumbers(1, 2, 3) |
| |
| def test_parameter_numbers_ne(self): |
| param = dsa.DSAParameterNumbers(1, 2, 3) |
| assert param != dsa.DSAParameterNumbers(1, 2, 4) |
| assert param != dsa.DSAParameterNumbers(1, 1, 3) |
| assert param != dsa.DSAParameterNumbers(2, 2, 3) |
| assert param != object() |
| |
| def test_public_numbers_eq(self): |
| pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) |
| assert pub == dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) |
| |
| def test_public_numbers_ne(self): |
| pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) |
| assert pub != dsa.DSAPublicNumbers(2, dsa.DSAParameterNumbers(1, 2, 3)) |
| assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(2, 2, 3)) |
| assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 3, 3)) |
| assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 4)) |
| assert pub != object() |
| |
| def test_private_numbers_eq(self): |
| pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) |
| priv = dsa.DSAPrivateNumbers(1, pub) |
| assert priv == dsa.DSAPrivateNumbers( |
| 1, dsa.DSAPublicNumbers( |
| 1, dsa.DSAParameterNumbers(1, 2, 3) |
| ) |
| ) |
| |
| def test_private_numbers_ne(self): |
| pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) |
| priv = dsa.DSAPrivateNumbers(1, pub) |
| assert priv != dsa.DSAPrivateNumbers( |
| 2, dsa.DSAPublicNumbers( |
| 1, dsa.DSAParameterNumbers(1, 2, 3) |
| ) |
| ) |
| assert priv != dsa.DSAPrivateNumbers( |
| 1, dsa.DSAPublicNumbers( |
| 2, dsa.DSAParameterNumbers(1, 2, 3) |
| ) |
| ) |
| assert priv != dsa.DSAPrivateNumbers( |
| 1, dsa.DSAPublicNumbers( |
| 1, dsa.DSAParameterNumbers(2, 2, 3) |
| ) |
| ) |
| assert priv != dsa.DSAPrivateNumbers( |
| 1, dsa.DSAPublicNumbers( |
| 1, dsa.DSAParameterNumbers(1, 3, 3) |
| ) |
| ) |
| assert priv != dsa.DSAPrivateNumbers( |
| 1, dsa.DSAPublicNumbers( |
| 1, dsa.DSAParameterNumbers(1, 2, 4) |
| ) |
| ) |
| assert priv != object() |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) |
| class TestDSASerialization(object): |
| @pytest.mark.parametrize( |
| ("fmt", "password"), |
| itertools.product( |
| [ |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| serialization.PrivateFormat.PKCS8 |
| ], |
| [ |
| b"s", |
| b"longerpassword", |
| b"!*$&(@#$*&($T@%_somesymbols", |
| b"\x01" * 1000, |
| ] |
| ) |
| ) |
| def test_private_bytes_encrypted_pem(self, backend, fmt, password): |
| key_bytes = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: pemfile.read().encode() |
| ) |
| key = serialization.load_pem_private_key(key_bytes, None, backend) |
| serialized = key.private_bytes( |
| serialization.Encoding.PEM, |
| fmt, |
| serialization.BestAvailableEncryption(password) |
| ) |
| loaded_key = serialization.load_pem_private_key( |
| serialized, password, backend |
| ) |
| loaded_priv_num = loaded_key.private_numbers() |
| priv_num = key.private_numbers() |
| assert loaded_priv_num == priv_num |
| |
| @pytest.mark.parametrize( |
| ("encoding", "fmt"), |
| [ |
| (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), |
| (serialization.Encoding.DER, serialization.PrivateFormat.Raw), |
| (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), |
| (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8), |
| ] |
| ) |
| def test_private_bytes_rejects_invalid(self, encoding, fmt, backend): |
| key = DSA_KEY_1024.private_key(backend) |
| with pytest.raises(ValueError): |
| key.private_bytes(encoding, fmt, serialization.NoEncryption()) |
| |
| @pytest.mark.parametrize( |
| ("fmt", "password"), |
| [ |
| [serialization.PrivateFormat.PKCS8, b"s"], |
| [serialization.PrivateFormat.PKCS8, b"longerpassword"], |
| [serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"], |
| [serialization.PrivateFormat.PKCS8, b"\x01" * 1000] |
| ] |
| ) |
| def test_private_bytes_encrypted_der(self, backend, fmt, password): |
| key_bytes = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: pemfile.read().encode() |
| ) |
| key = serialization.load_pem_private_key(key_bytes, None, backend) |
| serialized = key.private_bytes( |
| serialization.Encoding.DER, |
| fmt, |
| serialization.BestAvailableEncryption(password) |
| ) |
| loaded_key = serialization.load_der_private_key( |
| serialized, password, backend |
| ) |
| loaded_priv_num = loaded_key.private_numbers() |
| priv_num = key.private_numbers() |
| assert loaded_priv_num == priv_num |
| |
| @pytest.mark.parametrize( |
| ("encoding", "fmt", "loader_func"), |
| [ |
| [ |
| serialization.Encoding.PEM, |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| serialization.load_pem_private_key |
| ], |
| [ |
| serialization.Encoding.DER, |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| serialization.load_der_private_key |
| ], |
| [ |
| serialization.Encoding.PEM, |
| serialization.PrivateFormat.PKCS8, |
| serialization.load_pem_private_key |
| ], |
| [ |
| serialization.Encoding.DER, |
| serialization.PrivateFormat.PKCS8, |
| serialization.load_der_private_key |
| ], |
| ] |
| ) |
| def test_private_bytes_unencrypted(self, backend, encoding, fmt, |
| loader_func): |
| key = DSA_KEY_1024.private_key(backend) |
| serialized = key.private_bytes( |
| encoding, fmt, 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", "encoding", "loader_func"), |
| [ |
| [ |
| os.path.join( |
| "asymmetric", |
| "Traditional_OpenSSL_Serialization", |
| "dsa.1024.pem" |
| ), |
| serialization.Encoding.PEM, |
| serialization.load_pem_private_key |
| ], |
| [ |
| os.path.join( |
| "asymmetric", "DER_Serialization", "dsa.1024.der" |
| ), |
| serialization.Encoding.DER, |
| serialization.load_der_private_key |
| ], |
| ] |
| ) |
| def test_private_bytes_traditional_openssl_unencrypted( |
| self, backend, key_path, encoding, loader_func |
| ): |
| 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.TraditionalOpenSSL, |
| serialization.NoEncryption() |
| ) |
| assert serialized == key_bytes |
| |
| def test_private_bytes_traditional_der_encrypted_invalid(self, backend): |
| key = DSA_KEY_1024.private_key(backend) |
| with pytest.raises(ValueError): |
| key.private_bytes( |
| serialization.Encoding.DER, |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| serialization.BestAvailableEncryption(b"password") |
| ) |
| |
| def test_private_bytes_invalid_encoding(self, backend): |
| key = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: serialization.load_pem_private_key( |
| pemfile.read().encode(), None, backend |
| ) |
| ) |
| with pytest.raises(TypeError): |
| key.private_bytes( |
| "notencoding", |
| serialization.PrivateFormat.PKCS8, |
| serialization.NoEncryption() |
| ) |
| |
| def test_private_bytes_invalid_format(self, backend): |
| key = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: serialization.load_pem_private_key( |
| pemfile.read().encode(), None, backend |
| ) |
| ) |
| with pytest.raises(TypeError): |
| key.private_bytes( |
| serialization.Encoding.PEM, |
| "invalidformat", |
| serialization.NoEncryption() |
| ) |
| |
| def test_private_bytes_invalid_encryption_algorithm(self, backend): |
| key = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: serialization.load_pem_private_key( |
| pemfile.read().encode(), None, backend |
| ) |
| ) |
| with pytest.raises(TypeError): |
| key.private_bytes( |
| serialization.Encoding.PEM, |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| "notanencalg" |
| ) |
| |
| def test_private_bytes_unsupported_encryption_type(self, backend): |
| key = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), |
| lambda pemfile: serialization.load_pem_private_key( |
| pemfile.read().encode(), None, backend |
| ) |
| ) |
| with pytest.raises(ValueError): |
| key.private_bytes( |
| serialization.Encoding.PEM, |
| serialization.PrivateFormat.TraditionalOpenSSL, |
| DummyKeySerializationEncryption() |
| ) |
| |
| |
| @pytest.mark.requires_backend_interface(interface=DSABackend) |
| @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) |
| class TestDSAPEMPublicKeySerialization(object): |
| @pytest.mark.parametrize( |
| ("key_path", "loader_func", "encoding"), |
| [ |
| ( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"), |
| serialization.load_pem_public_key, |
| serialization.Encoding.PEM, |
| ), ( |
| os.path.join( |
| "asymmetric", |
| "DER_Serialization", |
| "unenc-dsa-pkcs8.pub.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" |
| ) |
| key = loader_func(key_bytes, backend) |
| serialized = key.public_bytes( |
| encoding, serialization.PublicFormat.SubjectPublicKeyInfo, |
| ) |
| assert serialized == key_bytes |
| |
| def test_public_bytes_openssh(self, backend): |
| key_bytes = load_vectors_from_file( |
| os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"), |
| lambda pemfile: pemfile.read(), mode="rb" |
| ) |
| key = serialization.load_pem_public_key(key_bytes, backend) |
| |
| ssh_bytes = key.public_bytes( |
| serialization.Encoding.OpenSSH, serialization.PublicFormat.OpenSSH |
| ) |
| assert ssh_bytes == ( |
| b"ssh-dss AAAAB3NzaC1kc3MAAACBAKoJMMwUWCUiHK/6KKwolBlqJ4M95ewhJweR" |
| b"aJQgd3Si57I4sNNvGySZosJYUIPrAUMpJEGNhn+qIS3RBx1NzrJ4J5StOTzAik1K" |
| b"2n9o1ug5pfzTS05ALYLLioy0D+wxkRv5vTYLA0yqy0xelHmSVzyekAmcGw8FlAyr" |
| b"5dLeSaFnAAAAFQCtwOhps28KwBOmgf301ImdaYIEUQAAAIEAjGtFia+lOk0QSL/D" |
| b"RtHzhsp1UhzPct2qJRKGiA7hMgH/SIkLv8M9ebrK7HHnp3hQe9XxpmQi45QVvgPn" |
| b"EUG6Mk9bkxMZKRgsiKn6QGKDYGbOvnS1xmkMfRARBsJAq369VOTjMB/Qhs5q2ski" |
| b"+ycTorCIfLoTubxozlz/8kHNMkYAAACAKyYOqX3GoSrpMsZA5989j/BKigWgMk+N" |
| b"Xxsj8V+hcP8/QgYRJO/yWGyxG0moLc3BuQ/GqE+xAQnLZ9tdLalxrq8Xvl43KEVj" |
| b"5MZNnl/ISAJYsxnw3inVTYNQcNnih5FNd9+BSR9EI7YtqYTrP0XrKin86l2uUlrG" |
| b"q2vM4Ev99bY=" |
| ) |
| |
| def test_public_bytes_invalid_encoding(self, backend): |
| key = DSA_KEY_2048.private_key(backend).public_key() |
| with pytest.raises(TypeError): |
| key.public_bytes( |
| "notencoding", |
| serialization.PublicFormat.SubjectPublicKeyInfo |
| ) |
| |
| def test_public_bytes_invalid_format(self, backend): |
| key = DSA_KEY_2048.private_key(backend).public_key() |
| with pytest.raises(TypeError): |
| key.public_bytes(serialization.Encoding.PEM, "invalidformat") |
| |
| def test_public_bytes_pkcs1_unsupported(self, backend): |
| key = DSA_KEY_2048.private_key(backend).public_key() |
| with pytest.raises(ValueError): |
| key.public_bytes( |
| serialization.Encoding.PEM, serialization.PublicFormat.PKCS1 |
| ) |
| |
| @pytest.mark.parametrize( |
| ("encoding", "fmt"), |
| [ |
| ( |
| serialization.Encoding.Raw, |
| serialization.PublicFormat.SubjectPublicKeyInfo |
| ), |
| (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1), |
| ] + list(itertools.product( |
| [ |
| serialization.Encoding.Raw, |
| serialization.Encoding.X962, |
| serialization.Encoding.PEM, |
| serialization.Encoding.DER |
| ], |
| [ |
| serialization.PublicFormat.Raw, |
| serialization.PublicFormat.UncompressedPoint, |
| serialization.PublicFormat.CompressedPoint |
| ] |
| )) |
| ) |
| def test_public_bytes_rejects_invalid(self, encoding, fmt, backend): |
| key = DSA_KEY_2048.private_key(backend).public_key() |
| with pytest.raises(ValueError): |
| key.public_bytes(encoding, fmt) |