diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-04-05 08:55:09 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-04-05 08:55:09 -0500 |
commit | 6abaf40a591bbae5e2eeebb8a29e6558aeae047c (patch) | |
tree | 5e2a7de8ca3c3f32da66773fcf24a45555e57cd7 /cryptography | |
parent | 509343e400942e78f5c1d0d5f380002939b24266 (diff) | |
parent | 29474ac7dab3f5c8b664463ed28ec83b7b77250b (diff) | |
download | cryptography-6abaf40a591bbae5e2eeebb8a29e6558aeae047c.tar.gz cryptography-6abaf40a591bbae5e2eeebb8a29e6558aeae047c.tar.bz2 cryptography-6abaf40a591bbae5e2eeebb8a29e6558aeae047c.zip |
Merge pull request #739 from skeuomorf/dsa-backend
DSA backend
Diffstat (limited to 'cryptography')
-rw-r--r-- | cryptography/hazmat/backends/interfaces.py | 15 | ||||
-rw-r--r-- | cryptography/hazmat/backends/multibackend.py | 16 | ||||
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 52 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/asymmetric/dsa.py | 22 |
4 files changed, 102 insertions, 3 deletions
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py index 27b609ed..20c21118 100644 --- a/cryptography/hazmat/backends/interfaces.py +++ b/cryptography/hazmat/backends/interfaces.py @@ -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): diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py index aa649dd3..86cded85 100644 --- a/cryptography/hazmat/backends/multibackend.py +++ b/cryptography/hazmat/backends/multibackend.py @@ -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) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 0c632aee..900d25c2 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -25,11 +25,12 @@ 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 -from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives.asymmetric import dsa, rsa from cryptography.hazmat.primitives.asymmetric.padding import ( MGF1, PKCS1v15, PSS ) @@ -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) @@ -415,6 +417,52 @@ class Backend(object): else: return isinstance(algorithm, hashes.SHA1) + def generate_dsa_parameters(self, key_size): + if key_size not in (1024, 2048, 3072): + raise ValueError( + "Key size must be 1024 or 2048 or 3072 bits") + + 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") + + ctx = self._lib.DSA_new() + assert ctx != self._ffi.NULL + ctx = self._ffi.gc(ctx, self._lib.DSA_free) + + res = self._lib.DSA_generate_parameters_ex( + ctx, key_size, self._ffi.NULL, 0, + self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + + 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) + ) + + 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) + + 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) + ) + class GetCipherByName(object): def __init__(self, fmt): diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py index 974db0a6..4c2de36a 100644 --- a/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -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 @@ -49,6 +51,16 @@ class DSAParameters(object): self._subgroup_order = subgroup_order self._generator = generator + @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 def modulus(self): return self._modulus @@ -96,6 +108,16 @@ class DSAPrivateKey(object): self._x = x self._y = y + @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 def key_size(self): return utils.bit_length(self._modulus) |