diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-03-30 15:58:20 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-03-30 15:58:20 -0500 |
commit | 99b0b1f78d5ca9888f996d8d9b0392ca32b8210f (patch) | |
tree | 38ae8cd1d265e4e512d60983ec45796ee5c5dc16 | |
parent | 3b1e6e4b2ec5274b8e21c446e18fc993001e637e (diff) | |
parent | 5b50613aaa9ec06d4b9f350ddbe6427b6d85e424 (diff) | |
download | cryptography-99b0b1f78d5ca9888f996d8d9b0392ca32b8210f.tar.gz cryptography-99b0b1f78d5ca9888f996d8d9b0392ca32b8210f.tar.bz2 cryptography-99b0b1f78d5ca9888f996d8d9b0392ca32b8210f.zip |
Merge pull request #870 from skeuomorf/dsa-public-key
Add DSA public key api, docs and tests
-rw-r--r-- | cryptography/hazmat/primitives/asymmetric/dsa.py | 25 | ||||
-rw-r--r-- | docs/hazmat/primitives/asymmetric/dsa.rst | 22 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_dsa.py | 146 |
3 files changed, 193 insertions, 0 deletions
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py index c368e783..a0631ce8 100644 --- a/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -72,3 +72,28 @@ class DSAParameters(object): @property def g(self): return self.generator + + +@utils.register_interface(interfaces.DSAPublicKey) +class DSAPublicKey(object): + def __init__(self, modulus, subgroup_order, generator, y): + _check_dsa_parameters(modulus, subgroup_order, generator) + if not isinstance(y, six.integer_types): + raise TypeError("y must be an integer") + + self._modulus = modulus + self._subgroup_order = subgroup_order + self._generator = generator + self._y = y + + @property + def key_size(self): + return utils.bit_length(self._modulus) + + @property + def y(self): + return self._y + + def parameters(self): + return DSAParameters(self._modulus, self._subgroup_order, + self._generator)
\ No newline at end of file diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index c9fd2f55..e93bd447 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -24,6 +24,28 @@ DSA not match the bounds specified in `FIPS 186-4`_. +.. class:: DSAPublicKey(modulus, subgroup_order, generator, y) + + .. versionadded:: 0.4 + + A DSA public key is required for verifying messages. + + Normally you do not need to directly construct public keys because you'll + be loading them from a file, generating them automatically or receiving + them from a 3rd party. + + This class conforms to the + :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey` + interface. + + :raises TypeError: This is raised when the arguments are not all integers. + + :raises ValueError: This is raised when the values of ``modulus``, + ``subgroup_order``,``generator``, or ``y`` + do not match the bounds specified in `FIPS 186-4`_. + + .. _`DSA`: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm .. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography .. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index ea2d96f7..fe610ef3 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -127,6 +127,10 @@ class TestDSA(object): with pytest.raises(TypeError): dsa.DSAParameters(None, None, None) + def test_invalid_public_key_argument_types(self): + with pytest.raises(TypeError): + dsa.DSAPublicKey(None, None, None, None) + def test_load_dsa_example_keys(self): parameters = dsa.DSAParameters( modulus=int(self._parameters_1024['p'], 16), @@ -141,6 +145,21 @@ class TestDSA(object): assert parameters.subgroup_order == parameters.q assert parameters.generator == parameters.g + pkey = dsa.DSAPublicKey( + modulus=int(self._parameters_1024["p"], 16), + subgroup_order=int(self._parameters_1024["q"], 16), + generator=int(self._parameters_1024["g"], 16), + y=int(self._parameters_1024["y"], 16) + ) + assert pkey + assert pkey.key_size + assert pkey.y + pkey_parameters = pkey.parameters() + assert pkey_parameters + assert pkey_parameters.modulus + assert pkey_parameters.subgroup_order + assert pkey_parameters.generator + def test_invalid_parameters_values(self): # Test a modulus < 1024 bits in length with pytest.raises(ValueError): @@ -245,3 +264,130 @@ class TestDSA(object): subgroup_order=int(self._parameters_1024['q'], 16), generator=2 ** 1200 ) + + def test_invalid_dsa_public_key_arguments(self): + # Test a modulus < 1024 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=2 ** 1000, + subgroup_order=int(self._parameters_1024['q'], 16), + generator=int(self._parameters_1024['g'], 16), + y=int(self._parameters_1024['y'], 16) + ) + + # Test a modulus < 2048 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=2 ** 2000, + subgroup_order=int(self._parameters_2048['q'], 16), + generator=int(self._parameters_2048['g'], 16), + y=int(self._parameters_2048['y'], 16) + ) + + # Test a modulus < 3072 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=2 ** 3000, + subgroup_order=int(self._parameters_3072['q'], 16), + generator=int(self._parameters_3072['g'], 16), + y=int(self._parameters_3072['y'], 16) + ) + + # Test a modulus > 3072 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=2 ** 3100, + subgroup_order=int(self._parameters_3072['q'], 16), + generator=int(self._parameters_3072['g'], 16), + y=int(self._parameters_3072['y'], 16) + ) + + # Test a subgroup_order < 160 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=2 ** 150, + generator=int(self._parameters_1024['g'], 16), + y=int(self._parameters_1024['y'], 16) + ) + + # Test a subgroup_order < 256 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_2048['p'], 16), + subgroup_order=2 ** 250, + generator=int(self._parameters_2048['g'], 16), + y=int(self._parameters_2048['y'], 16) + ) + + # Test a subgroup_order > 256 bits in length + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_3072['p'], 16), + subgroup_order=2 ** 260, + generator=int(self._parameters_3072['g'], 16), + y=int(self._parameters_3072['y'], 16) + ) + + # Test a modulus, subgroup_order pair of (1024, 256) bit lengths + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=int(self._parameters_2048['q'], 16), + generator=int(self._parameters_1024['g'], 16), + y=int(self._parameters_1024['y'], 16) + ) + + # Test a modulus, subgroup_order pair of (2048, 160) bit lengths + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_2048['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=int(self._parameters_2048['g'], 16), + y=int(self._parameters_2048['y'], 16) + ) + + # Test a modulus, subgroup_order pair of (3072, 160) bit lengths + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_3072['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=int(self._parameters_3072['g'], 16), + y=int(self._parameters_3072['y'], 16) + ) + + # Test a generator < 1 + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=0, + y=int(self._parameters_1024['y'], 16) + ) + + # Test a generator = 1 + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=1, + y=int(self._parameters_1024['y'], 16) + ) + + # Test a generator > modulus + with pytest.raises(ValueError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=2 ** 1200, + y=int(self._parameters_1024['y'], 16) + ) + + # Test a non-integer y value + with pytest.raises(TypeError): + dsa.DSAPublicKey( + modulus=int(self._parameters_1024['p'], 16), + subgroup_order=int(self._parameters_1024['q'], 16), + generator=int(self._parameters_1024['g'], 16), + y=None + ) |