mirror of
https://github.com/saymrwulf/cryptography.git
synced 2026-05-14 20:37:55 +00:00
Add DSABackend
This commit is contained in:
parent
9ac7c1d903
commit
97c27c698d
9 changed files with 121 additions and 19 deletions
|
|
@ -113,6 +113,21 @@ class RSABackend(six.with_metaclass(abc.ABCMeta)):
|
|||
"""
|
||||
|
||||
|
||||
class DSABackend(six.with_metaclass(abc.ABCMeta)):
|
||||
@abc.abstractmethod
|
||||
def generate_dsa_parameters(self, key_size):
|
||||
"""
|
||||
Generate a DSAParameters instance with a modulus of key_size bits.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def generate_dsa_private_key(self, parameters):
|
||||
"""
|
||||
Generate an DSAPrivateKey instance with parameters as
|
||||
a DSAParameters object.
|
||||
"""
|
||||
|
||||
|
||||
class OpenSSLSerializationBackend(six.with_metaclass(abc.ABCMeta)):
|
||||
@abc.abstractmethod
|
||||
def load_openssl_pem_private_key(self, data, password):
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ from __future__ import absolute_import, division, print_function
|
|||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.backends.interfaces import (
|
||||
CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
|
||||
CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
|
||||
RSABackend
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ from cryptography.hazmat.backends.interfaces import (
|
|||
@utils.register_interface(HMACBackend)
|
||||
@utils.register_interface(PBKDF2HMACBackend)
|
||||
@utils.register_interface(RSABackend)
|
||||
@utils.register_interface(DSABackend)
|
||||
class MultiBackend(object):
|
||||
name = "multibackend"
|
||||
|
||||
|
|
@ -142,3 +144,15 @@ class MultiBackend(object):
|
|||
padding, algorithm)
|
||||
raise UnsupportedAlgorithm("RSA is not supported by the backend",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||
|
||||
def generate_dsa_parameters(self, key_size):
|
||||
for b in self._filtered_backends(DSABackend):
|
||||
return b.generate_dsa_parameters(key_size)
|
||||
raise UnsupportedAlgorithm("DSA is not supported by the backend",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||
|
||||
def generate_dsa_private_key(self, parameters):
|
||||
for b in self._filtered_backends(DSABackend):
|
||||
return b.generate_dsa_private_key(parameters)
|
||||
raise UnsupportedAlgorithm("DSA is not supported by the backend",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ from cryptography.exceptions import (
|
|||
UnsupportedAlgorithm, _Reasons
|
||||
)
|
||||
from cryptography.hazmat.backends.interfaces import (
|
||||
CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
|
||||
CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
|
||||
RSABackend
|
||||
)
|
||||
from cryptography.hazmat.bindings.openssl.binding import Binding
|
||||
from cryptography.hazmat.primitives import hashes, interfaces
|
||||
|
|
@ -46,6 +47,7 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError",
|
|||
|
||||
|
||||
@utils.register_interface(CipherBackend)
|
||||
@utils.register_interface(DSABackend)
|
||||
@utils.register_interface(HashBackend)
|
||||
@utils.register_interface(HMACBackend)
|
||||
@utils.register_interface(PBKDF2HMACBackend)
|
||||
|
|
@ -420,8 +422,8 @@ class Backend(object):
|
|||
raise ValueError(
|
||||
"Key size must be 1024 or 2048 or 3072 bits")
|
||||
|
||||
if backend._lib.OPENSSL_VERSION_NUMBER < 0x1000000f \
|
||||
and key_size > 1024:
|
||||
if (self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f and
|
||||
key_size > 1024):
|
||||
raise ValueError(
|
||||
"Key size must be 1024 because OpenSSL < 1.0.0 doesn't "
|
||||
"support larger key sizes")
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ from __future__ import absolute_import, division, print_function
|
|||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.backends.interfaces import DSABackend
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
|
||||
|
||||
|
|
@ -51,6 +53,12 @@ class DSAParameters(object):
|
|||
|
||||
@classmethod
|
||||
def generate(cls, key_size, backend):
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
return backend.generate_dsa_parameters(key_size)
|
||||
|
||||
@property
|
||||
|
|
@ -102,6 +110,12 @@ class DSAPrivateKey(object):
|
|||
|
||||
@classmethod
|
||||
def generate(cls, parameters, backend):
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
return backend.generate_dsa_private_key(parameters)
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
addopts = -r s
|
||||
markers =
|
||||
cipher: this test requires a backend providing CipherBackend
|
||||
dsa: this test requires a backend providing DSABackend
|
||||
hash: this test requires a backend providing HashBackend
|
||||
hmac: this test requires a backend providing HMACBackend
|
||||
pbkdf2hmac: this test requires a backend providing PBKDF2HMACBackend
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ import pytest
|
|||
|
||||
from cryptography.hazmat.backends import _available_backends
|
||||
from cryptography.hazmat.backends.interfaces import (
|
||||
CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
|
||||
CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
|
||||
RSABackend
|
||||
)
|
||||
|
||||
from .utils import check_backend_support, check_for_iface, select_backends
|
||||
|
|
@ -37,6 +38,7 @@ def pytest_runtest_setup(item):
|
|||
check_for_iface("cipher", CipherBackend, item)
|
||||
check_for_iface("hash", HashBackend, item)
|
||||
check_for_iface("pbkdf2hmac", PBKDF2HMACBackend, item)
|
||||
check_for_iface("dsa", DSABackend, item)
|
||||
check_for_iface("rsa", RSABackend, item)
|
||||
check_backend_support(item)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ from cryptography.exceptions import (
|
|||
UnsupportedAlgorithm, _Reasons
|
||||
)
|
||||
from cryptography.hazmat.backends.interfaces import (
|
||||
CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
|
||||
CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend,
|
||||
DSABackend
|
||||
)
|
||||
from cryptography.hazmat.backends.multibackend import MultiBackend
|
||||
from cryptography.hazmat.primitives import hashes, hmac
|
||||
|
|
@ -27,6 +28,8 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|||
|
||||
from ...utils import raises_unsupported_algorithm
|
||||
|
||||
from pretend import stub
|
||||
|
||||
|
||||
@utils.register_interface(CipherBackend)
|
||||
class DummyCipherBackend(object):
|
||||
|
|
@ -98,6 +101,15 @@ class DummyRSABackend(object):
|
|||
pass
|
||||
|
||||
|
||||
@utils.register_interface(DSABackend)
|
||||
class DummyDSABackend(object):
|
||||
def generate_dsa_parameters(self, key_size):
|
||||
pass
|
||||
|
||||
def generate_dsa_private_key(self, parameters):
|
||||
pass
|
||||
|
||||
|
||||
class TestMultiBackend(object):
|
||||
def test_ciphers(self):
|
||||
backend = MultiBackend([
|
||||
|
|
@ -193,3 +205,24 @@ class TestMultiBackend(object):
|
|||
):
|
||||
backend.create_rsa_verification_ctx(
|
||||
"public_key", "sig", padding.PKCS1v15(), hashes.MD5())
|
||||
|
||||
def test_dsa(self):
|
||||
backend = MultiBackend([
|
||||
DummyDSABackend()
|
||||
])
|
||||
|
||||
backend.generate_dsa_parameters(key_size=1024)
|
||||
|
||||
parameters = stub()
|
||||
backend.generate_dsa_private_key(parameters)
|
||||
|
||||
backend = MultiBackend([])
|
||||
with raises_unsupported_algorithm(
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
|
||||
):
|
||||
backend.generate_dsa_parameters(key_size=1024)
|
||||
|
||||
with raises_unsupported_algorithm(
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
|
||||
):
|
||||
backend.generate_dsa_private_key(parameters)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ from cryptography.hazmat.primitives.ciphers.modes import CBC
|
|||
|
||||
from ...utils import raises_unsupported_algorithm
|
||||
|
||||
from cryptography.utils import bit_length
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
class DummyMode(object):
|
||||
|
|
@ -203,6 +205,16 @@ class TestOpenSSL(object):
|
|||
with pytest.raises(ValueError):
|
||||
dsa.DSAParameters.generate(3072, backend=backend)
|
||||
|
||||
@pytest.mark.skipif(
|
||||
backend._lib.OPENSSL_VERSION_NUMBER < 0x1000000f,
|
||||
reason="Requires a newer OpenSSL. Must be >= 1.0.0"
|
||||
)
|
||||
def test_large_key_size_on_new_openssl(self):
|
||||
parameters = dsa.DSAParameters.generate(2048, backend)
|
||||
assert bit_length(parameters.p) == 2048
|
||||
parameters = dsa.DSAParameters.generate(3072, backend)
|
||||
assert bit_length(parameters.p) == 3072
|
||||
|
||||
|
||||
class TestOpenSSLRandomEngine(object):
|
||||
def teardown_method(self, method):
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@ import os
|
|||
|
||||
import pytest
|
||||
|
||||
from cryptography.exceptions import _Reasons
|
||||
from cryptography.hazmat.primitives.asymmetric import dsa
|
||||
|
||||
from cryptography.utils import bit_length
|
||||
|
||||
from ...utils import (
|
||||
load_vectors_from_file, load_fips_dsa_key_pair_vectors
|
||||
load_vectors_from_file, load_fips_dsa_key_pair_vectors,
|
||||
raises_unsupported_algorithm
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -61,6 +62,7 @@ def _check_dsa_private_key(skey):
|
|||
assert skey_parameters.generator == pkey_parameters.generator
|
||||
|
||||
|
||||
@pytest.mark.dsa
|
||||
class TestDSA(object):
|
||||
_parameters_1024 = {
|
||||
'p': 'd38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341eabb47'
|
||||
|
|
@ -168,11 +170,10 @@ class TestDSA(object):
|
|||
def test_generate_dsa_parameters(self, backend):
|
||||
parameters = dsa.DSAParameters.generate(1024, backend)
|
||||
assert bit_length(parameters.p) == 1024
|
||||
if backend._lib.OPENSSL_VERSION_NUMBER >= 0x1000000fL:
|
||||
parameters = dsa.DSAParameters.generate(2048, backend)
|
||||
assert bit_length(parameters.p) == 2048
|
||||
parameters = dsa.DSAParameters.generate(3072, backend)
|
||||
assert bit_length(parameters.p) == 3072
|
||||
|
||||
def test_generate_invalid_dsa_parameters(self, backend):
|
||||
with pytest.raises(ValueError):
|
||||
dsa.DSAParameters.generate(1, backend)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"vector",
|
||||
|
|
@ -183,12 +184,9 @@ class TestDSA(object):
|
|||
)
|
||||
)
|
||||
def test_generate_dsa_keys(self, vector, backend):
|
||||
class Object(object):
|
||||
pass
|
||||
parameters = Object()
|
||||
parameters.p = vector['p']
|
||||
parameters.q = vector['q']
|
||||
parameters.g = vector['g']
|
||||
parameters = dsa.DSAParameters(modulus=vector['p'],
|
||||
subgroup_order=vector['q'],
|
||||
generator=vector['g'])
|
||||
skey = dsa.DSAPrivateKey.generate(parameters, backend)
|
||||
|
||||
skey_parameters = skey.parameters()
|
||||
|
|
@ -720,3 +718,14 @@ class TestDSA(object):
|
|||
generator=int(self._parameters_1024['g'], 16),
|
||||
y=None
|
||||
)
|
||||
|
||||
|
||||
def test_dsa_generate_invalid_backend():
|
||||
pretend_backend = object()
|
||||
|
||||
with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
|
||||
dsa.DSAParameters.generate(1024, pretend_backend)
|
||||
|
||||
pretend_parameters = object()
|
||||
with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
|
||||
dsa.DSAPrivateKey.generate(pretend_parameters, pretend_backend)
|
||||
|
|
|
|||
Loading…
Reference in a new issue