aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/primitives/asymmetric/dsa.py45
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst17
-rw-r--r--tests/hazmat/primitives/test_dsa.py292
3 files changed, 351 insertions, 3 deletions
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index a0631ce8..974db0a6 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -74,6 +74,49 @@ class DSAParameters(object):
return self.generator
+@utils.register_interface(interfaces.DSAPrivateKey)
+class DSAPrivateKey(object):
+ def __init__(self, modulus, subgroup_order, generator, x, y):
+ _check_dsa_parameters(modulus, subgroup_order, generator)
+ if (
+ not isinstance(x, six.integer_types) or
+ not isinstance(y, six.integer_types)
+ ):
+ raise TypeError("DSAPrivateKey arguments must be integers")
+
+ if x <= 0 or x >= subgroup_order:
+ raise ValueError("x must be > 0 and < subgroup_order")
+
+ if y != pow(generator, x, modulus):
+ raise ValueError("y must be equal to (generator ** x % modulus)")
+
+ self._modulus = modulus
+ self._subgroup_order = subgroup_order
+ self._generator = generator
+ self._x = x
+ self._y = y
+
+ @property
+ def key_size(self):
+ return utils.bit_length(self._modulus)
+
+ def public_key(self):
+ return DSAPublicKey(self._modulus, self._subgroup_order,
+ self._generator, self.y)
+
+ @property
+ def x(self):
+ return self._x
+
+ @property
+ def y(self):
+ return self._y
+
+ def parameters(self):
+ return DSAParameters(self._modulus, self._subgroup_order,
+ self._generator)
+
+
@utils.register_interface(interfaces.DSAPublicKey)
class DSAPublicKey(object):
def __init__(self, modulus, subgroup_order, generator, y):
@@ -96,4 +139,4 @@ class DSAPublicKey(object):
def parameters(self):
return DSAParameters(self._modulus, self._subgroup_order,
- self._generator) \ No newline at end of file
+ self._generator)
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index e93bd447..69e8d58e 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -24,6 +24,23 @@ DSA
not match the bounds specified in `FIPS 186-4`_.
+.. class:: DSAPrivateKey(modulus, subgroup_order, generator, x, y)
+
+ .. versionadded:: 0.4
+
+ A DSA private key is required for signing messages.
+
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+ 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``, or ``generator`` do
+ not match the bounds specified in `FIPS 186-4`_.
+
+
.. class:: DSAPublicKey(modulus, subgroup_order, generator, y)
.. versionadded:: 0.4
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index fe610ef3..2a2b9bda 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -19,6 +19,40 @@ import pytest
from cryptography.hazmat.primitives.asymmetric import dsa
+def _check_dsa_private_key(skey):
+ assert skey
+ assert skey.x
+ assert skey.y
+ assert skey.key_size
+
+ skey_parameters = skey.parameters()
+ assert skey_parameters
+ assert skey_parameters.modulus
+ assert skey_parameters.subgroup_order
+ assert skey_parameters.generator
+ assert skey_parameters.modulus == skey_parameters.p
+ assert skey_parameters.subgroup_order == skey_parameters.q
+ assert skey_parameters.generator == skey_parameters.g
+
+ pkey = skey.public_key()
+ assert pkey
+ assert skey.y == pkey.y
+ assert skey.key_size == pkey.key_size
+
+ pkey_parameters = pkey.parameters()
+ assert pkey_parameters
+ assert pkey_parameters.modulus
+ assert pkey_parameters.subgroup_order
+ assert pkey_parameters.generator
+ assert pkey_parameters.modulus == pkey_parameters.p
+ assert pkey_parameters.subgroup_order == pkey_parameters.q
+ assert pkey_parameters.generator == pkey_parameters.g
+
+ assert skey_parameters.modulus == pkey_parameters.modulus
+ assert skey_parameters.subgroup_order == pkey_parameters.subgroup_order
+ assert skey_parameters.generator == pkey_parameters.generator
+
+
class TestDSA(object):
_parameters_1024 = {
'p': 'd38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341eabb47'
@@ -127,6 +161,10 @@ class TestDSA(object):
with pytest.raises(TypeError):
dsa.DSAParameters(None, None, None)
+ def test_invalid_private_key_argument_types(self):
+ with pytest.raises(TypeError):
+ dsa.DSAPrivateKey(None, None, None, None, None)
+
def test_invalid_public_key_argument_types(self):
with pytest.raises(TypeError):
dsa.DSAPublicKey(None, None, None, None)
@@ -145,6 +183,36 @@ class TestDSA(object):
assert parameters.subgroup_order == parameters.q
assert parameters.generator == parameters.g
+ pub_key = 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 pub_key
+ assert pub_key.key_size
+ assert pub_key.y
+ pub_key_parameters = pub_key.parameters()
+ assert pub_key_parameters
+ assert pub_key_parameters.modulus
+ assert pub_key_parameters.subgroup_order
+ assert pub_key_parameters.generator
+
+ skey = dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024["p"], 16),
+ subgroup_order=int(self._parameters_1024["q"], 16),
+ generator=int(self._parameters_1024["g"], 16),
+ x=int(self._parameters_1024["x"], 16),
+ y=int(self._parameters_1024["y"], 16)
+ )
+ assert skey
+ _check_dsa_private_key(skey)
+ skey_parameters = skey.parameters()
+ assert skey_parameters
+ assert skey_parameters.modulus
+ assert skey_parameters.subgroup_order
+ assert skey_parameters.generator
+
pkey = dsa.DSAPublicKey(
modulus=int(self._parameters_1024["p"], 16),
subgroup_order=int(self._parameters_1024["q"], 16),
@@ -152,14 +220,33 @@ class TestDSA(object):
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
+ pkey2 = skey.public_key()
+ assert pkey2
+ pkey2_parameters = pkey.parameters()
+ assert pkey2_parameters
+ assert pkey2_parameters.modulus
+ assert pkey2_parameters.subgroup_order
+ assert pkey2_parameters.generator
+
+ assert skey_parameters.modulus == pkey_parameters.modulus
+ assert skey_parameters.subgroup_order == pkey_parameters.subgroup_order
+ assert skey_parameters.generator == pkey_parameters.generator
+ assert skey.y == pkey.y
+ assert skey.key_size == pkey.key_size
+
+ assert pkey_parameters.modulus == pkey2_parameters.modulus
+ assert pkey_parameters.subgroup_order == \
+ pkey2_parameters.subgroup_order
+ assert pkey_parameters.generator == pkey2_parameters.generator
+ assert pkey.y == pkey2.y
+ assert pkey.key_size == pkey2.key_size
+
def test_invalid_parameters_values(self):
# Test a modulus < 1024 bits in length
with pytest.raises(ValueError):
@@ -265,6 +352,207 @@ class TestDSA(object):
generator=2 ** 1200
)
+ def test_invalid_dsa_private_key_arguments(self):
+ # Test a modulus < 1024 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=2 ** 1000,
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test a modulus < 2048 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=2 ** 2000,
+ subgroup_order=int(self._parameters_2048['q'], 16),
+ generator=int(self._parameters_2048['g'], 16),
+ x=int(self._parameters_2048['x'], 16),
+ y=int(self._parameters_2048['y'], 16)
+ )
+
+ # Test a modulus < 3072 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=2 ** 3000,
+ subgroup_order=int(self._parameters_3072['q'], 16),
+ generator=int(self._parameters_3072['g'], 16),
+ x=int(self._parameters_3072['x'], 16),
+ y=int(self._parameters_3072['y'], 16)
+ )
+
+ # Test a modulus > 3072 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=2 ** 3100,
+ subgroup_order=int(self._parameters_3072['q'], 16),
+ generator=int(self._parameters_3072['g'], 16),
+ x=int(self._parameters_3072['x'], 16),
+ y=int(self._parameters_3072['y'], 16)
+ )
+
+ # Test a subgroup_order < 160 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=2 ** 150,
+ generator=int(self._parameters_1024['g'], 16),
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test a subgroup_order < 256 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_2048['p'], 16),
+ subgroup_order=2 ** 250,
+ generator=int(self._parameters_2048['g'], 16),
+ x=int(self._parameters_2048['x'], 16),
+ y=int(self._parameters_2048['y'], 16)
+ )
+
+ # Test a subgroup_order > 256 bits in length
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_3072['p'], 16),
+ subgroup_order=2 ** 260,
+ generator=int(self._parameters_3072['g'], 16),
+ x=int(self._parameters_3072['x'], 16),
+ y=int(self._parameters_3072['y'], 16)
+ )
+
+ # Test a modulus, subgroup_order pair of (1024, 256) bit lengths
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_2048['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test a modulus, subgroup_order pair of (2048, 160) bit lengths
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_2048['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_2048['g'], 16),
+ x=int(self._parameters_2048['x'], 16),
+ y=int(self._parameters_2048['y'], 16)
+ )
+
+ # Test a modulus, subgroup_order pair of (3072, 160) bit lengths
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_3072['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_3072['g'], 16),
+ x=int(self._parameters_3072['x'], 16),
+ y=int(self._parameters_3072['y'], 16)
+ )
+
+ # Test a generator < 1
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=0,
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test a generator = 1
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=1,
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test a generator > modulus
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=2 ** 1200,
+ x=int(self._parameters_1024['x'], 16),
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test x = 0
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=0,
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test x < 0
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=-2,
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test x = subgroup_order
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=2 ** 159,
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test x > subgroup_order
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=2 ** 200,
+ y=int(self._parameters_1024['y'], 16)
+ )
+
+ # Test y != (generator ** x) % modulus
+ with pytest.raises(ValueError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=int(self._parameters_1024['x'], 16),
+ y=2 ** 100
+ )
+
+ # Test a non-integer y value
+ with pytest.raises(TypeError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=int(self._parameters_1024['x'], 16),
+ y=None
+ )
+
+ # Test a non-integer x value
+ with pytest.raises(TypeError):
+ dsa.DSAPrivateKey(
+ modulus=int(self._parameters_1024['p'], 16),
+ subgroup_order=int(self._parameters_1024['q'], 16),
+ generator=int(self._parameters_1024['g'], 16),
+ x=None,
+ y=int(self._parameters_1024['x'], 16)
+ )
+
def test_invalid_dsa_public_key_arguments(self):
# Test a modulus < 1024 bits in length
with pytest.raises(ValueError):