aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-04-05 08:55:09 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-04-05 08:55:09 -0500
commit6abaf40a591bbae5e2eeebb8a29e6558aeae047c (patch)
tree5e2a7de8ca3c3f32da66773fcf24a45555e57cd7 /cryptography
parent509343e400942e78f5c1d0d5f380002939b24266 (diff)
parent29474ac7dab3f5c8b664463ed28ec83b7b77250b (diff)
downloadcryptography-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.py15
-rw-r--r--cryptography/hazmat/backends/multibackend.py16
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py52
-rw-r--r--cryptography/hazmat/primitives/asymmetric/dsa.py22
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)