aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-06-22 18:06:28 -0600
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-06-25 08:25:52 -0600
commit0197ed8dedcd24d3b690d1b76eb6866df14f56dd (patch)
treec773e0eb29ba4d16b5ce8dd1422dbff000711175 /cryptography
parent42ee73b26e18fc9a03badd885a8a3847f3907cad (diff)
downloadcryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.tar.gz
cryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.tar.bz2
cryptography-0197ed8dedcd24d3b690d1b76eb6866df14f56dd.zip
DSA opaque OpenSSL
Diffstat (limited to 'cryptography')
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py90
-rw-r--r--cryptography/hazmat/backends/openssl/dsa.py121
-rw-r--r--cryptography/hazmat/primitives/asymmetric/dsa.py78
3 files changed, 233 insertions, 56 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index d08cd3e4..e895da83 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -32,6 +32,7 @@ from cryptography.hazmat.backends.openssl.ciphers import (
_AESCTRCipherContext, _CipherContext
)
from cryptography.hazmat.backends.openssl.dsa import (
+ _DSAParameters, _DSAPrivateKey, _DSAPublicKey,
_DSASignatureContext, _DSAVerificationContext
)
from cryptography.hazmat.backends.openssl.ec import (
@@ -467,19 +468,10 @@ class Backend(object):
dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey)
assert dsa_cdata != self._ffi.NULL
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
- return self._dsa_cdata_to_private_key(dsa_cdata)
+ return _DSAPrivateKey(self, dsa_cdata)
else:
raise UnsupportedAlgorithm("Unsupported key type.")
- def _dsa_cdata_to_private_key(self, cdata):
- return dsa.DSAPrivateKey(
- modulus=self._bn_to_int(cdata.p),
- subgroup_order=self._bn_to_int(cdata.q),
- generator=self._bn_to_int(cdata.g),
- x=self._bn_to_int(cdata.priv_key),
- y=self._bn_to_int(cdata.pub_key)
- )
-
def _pem_password_cb(self, password):
"""
Generate a pem_password_cb function pointer that copied the password to
@@ -615,37 +607,79 @@ class Backend(object):
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)
- )
+ return _DSAParameters(self, ctx)
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)
+ if isinstance(parameters, dsa.DSAParameters):
+ ctx.p = self._int_to_bn(parameters.p)
+ ctx.q = self._int_to_bn(parameters.q)
+ ctx.g = self._int_to_bn(parameters.g)
+ else:
+ ctx.p = self._lib.BN_dup(parameters._dsa_cdata.p)
+ ctx.q = self._lib.BN_dup(parameters._dsa_cdata.q)
+ ctx.g = self._lib.BN_dup(parameters._dsa_cdata.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)
- )
+ return _DSAPrivateKey(self, ctx)
def create_dsa_signature_ctx(self, private_key, algorithm):
- return _DSASignatureContext(self, private_key, algorithm)
+ dsa_cdata = self._dsa_cdata_from_private_key(private_key)
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+ key = _DSAPrivateKey(self, dsa_cdata)
+ return _DSASignatureContext(self, key, algorithm)
def create_dsa_verification_ctx(self, public_key, signature,
algorithm):
- return _DSAVerificationContext(self, public_key, signature,
- algorithm)
+ dsa_cdata = self._dsa_cdata_from_public_key(public_key)
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+ key = _DSAPublicKey(self, dsa_cdata)
+ return _DSAVerificationContext(self, key, signature, algorithm)
+
+ def load_dsa_private_numbers(self, numbers):
+ parameter_numbers = numbers.public_numbers.parameter_numbers
+ dsa._check_dsa_parameters(parameter_numbers)
+ dsa_cdata = self._lib.DSA_new()
+ assert dsa_cdata != self._ffi.NULL
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+
+ dsa_cdata.p = self._int_to_bn(parameter_numbers.p)
+ dsa_cdata.q = self._int_to_bn(parameter_numbers.q)
+ dsa_cdata.g = self._int_to_bn(parameter_numbers.g)
+ dsa_cdata.pub_key = self._int_to_bn(numbers.public_numbers.y)
+ dsa_cdata.priv_key = self._int_to_bn(numbers.x)
+
+ return _DSAPrivateKey(self, dsa_cdata)
+
+ def load_dsa_public_numbers(self, numbers):
+ dsa._check_dsa_parameters(numbers.parameter_numbers)
+ # TODO check more
+ dsa_cdata = self._lib.DSA_new()
+ assert dsa_cdata != self._ffi.NULL
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+
+ dsa_cdata.p = self._int_to_bn(numbers.parameter_numbers.p)
+ dsa_cdata.q = self._int_to_bn(numbers.parameter_numbers.q)
+ dsa_cdata.g = self._int_to_bn(numbers.parameter_numbers.g)
+ dsa_cdata.pub_key = self._int_to_bn(numbers.y)
+
+ return _DSAPublicKey(self, dsa_cdata)
+
+ def load_dsa_parameter_numbers(self, numbers):
+ dsa._check_dsa_parameters(numbers)
+ # TODO check more
+ dsa_cdata = self._lib.DSA_new()
+ assert dsa_cdata != self._ffi.NULL
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+
+ dsa_cdata.p = self._int_to_bn(numbers.p)
+ dsa_cdata.q = self._int_to_bn(numbers.q)
+ dsa_cdata.g = self._int_to_bn(numbers.g)
+
+ return _DSAParameters(self, dsa_cdata)
def _dsa_cdata_from_public_key(self, public_key):
# Does not GC the DSA cdata. You *must* make sure it's freed
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py
index ec05c3aa..d492372f 100644
--- a/cryptography/hazmat/backends/openssl/dsa.py
+++ b/cryptography/hazmat/backends/openssl/dsa.py
@@ -16,6 +16,10 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives.asymmetric import dsa
+from cryptography.hazmat.primitives.interfaces import (
+ DSAParametersWithNumbers, DSAPrivateKeyWithNumbers, DSAPublicKeyWithNumbers
+)
@utils.register_interface(interfaces.AsymmetricVerificationContext)
@@ -32,9 +36,7 @@ class _DSAVerificationContext(object):
self._hash_ctx.update(data)
def verify(self):
- self._dsa_cdata = self._backend._dsa_cdata_from_public_key(
- self._public_key)
- self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata,
+ self._dsa_cdata = self._backend._ffi.gc(self._public_key._dsa_cdata,
self._backend._lib.DSA_free)
data_to_verify = self._hash_ctx.finalize()
@@ -43,7 +45,7 @@ class _DSAVerificationContext(object):
# must be an integer.
res = self._backend._lib.DSA_verify(
0, data_to_verify, len(data_to_verify), self._signature,
- len(self._signature), self._dsa_cdata)
+ len(self._signature), self._public_key._dsa_cdata)
if res != 1:
errors = self._backend._consume_errors()
@@ -61,17 +63,13 @@ class _DSASignatureContext(object):
self._private_key = private_key
self._algorithm = algorithm
self._hash_ctx = hashes.Hash(self._algorithm, self._backend)
- self._dsa_cdata = self._backend._dsa_cdata_from_private_key(
- self._private_key)
- self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata,
- self._backend._lib.DSA_free)
def update(self, data):
self._hash_ctx.update(data)
def finalize(self):
data_to_sign = self._hash_ctx.finalize()
- sig_buf_len = self._backend._lib.DSA_size(self._dsa_cdata)
+ sig_buf_len = self._backend._lib.DSA_size(self._private_key._dsa_cdata)
sig_buf = self._backend._ffi.new("unsigned char[]", sig_buf_len)
buflen = self._backend._ffi.new("unsigned int *")
@@ -79,8 +77,111 @@ class _DSASignatureContext(object):
# must be an integer.
res = self._backend._lib.DSA_sign(
0, data_to_sign, len(data_to_sign), sig_buf,
- buflen, self._dsa_cdata)
+ buflen, self._private_key._dsa_cdata)
assert res == 1
assert buflen[0]
return self._backend._ffi.buffer(sig_buf)[:buflen[0]]
+
+
+@utils.register_interface(DSAParametersWithNumbers)
+class _DSAParameters(object):
+ def __init__(self, backend, dsa_cdata):
+ self._backend = backend
+ self._dsa_cdata = dsa_cdata
+
+ def parameter_numbers(self):
+ return dsa.DSAParameterNumbers(
+ p=self._backend._bn_to_int(self._dsa_cdata.p),
+ q=self._backend._bn_to_int(self._dsa_cdata.q),
+ g=self._backend._bn_to_int(self._dsa_cdata.g)
+ )
+
+
+@utils.register_interface(DSAPrivateKeyWithNumbers)
+class _DSAPrivateKey(object):
+ def __init__(self, backend, dsa_cdata):
+ self._backend = backend
+ self._dsa_cdata = dsa_cdata
+ self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
+
+ @property
+ def key_size(self):
+ return self._key_size
+
+ def signer(self, algorithm):
+ return _DSASignatureContext(self._backend, self, algorithm)
+
+ def private_numbers(self):
+ return dsa.DSAPrivateNumbers(
+ public_numbers=dsa.DSAPublicNumbers(
+ parameter_numbers=dsa.DSAParameterNumbers(
+ p=self._backend._bn_to_int(self._dsa_cdata.p),
+ q=self._backend._bn_to_int(self._dsa_cdata.q),
+ g=self._backend._bn_to_int(self._dsa_cdata.g)
+ ),
+ y=self._backend._bn_to_int(self._dsa_cdata.pub_key)
+ ),
+ x=self._backend._bn_to_int(self._dsa_cdata.priv_key)
+ )
+
+ def public_key(self):
+ dsa_cdata = self._backend._lib.DSA_new()
+ assert dsa_cdata != self._backend._ffi.NULL
+ dsa_cdata = self._backend._ffi.gc(
+ dsa_cdata, self._backend._lib.DSA_free
+ )
+ dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p)
+ dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
+ dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
+ dsa_cdata.pub_key = self._backend._lib.BN_dup(self._dsa_cdata.pub_key)
+ return _DSAPublicKey(self._backend, dsa_cdata)
+
+ def parameters(self):
+ dsa_cdata = self._backend._lib.DSA_new()
+ assert dsa_cdata != self._backend._ffi.NULL
+ dsa_cdata = self._backend._ffi.gc(
+ dsa_cdata, self._backend._lib.DSA_free
+ )
+ dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p)
+ dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
+ dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
+ return _DSAParameters(self._backend, dsa_cdata)
+
+
+@utils.register_interface(DSAPublicKeyWithNumbers)
+class _DSAPublicKey(object):
+ def __init__(self, backend, dsa_cdata):
+ self._backend = backend
+ self._dsa_cdata = dsa_cdata
+ self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
+
+ @property
+ def key_size(self):
+ return self._key_size
+
+ def verifier(self, signature, algorithm):
+ return _DSAVerificationContext(
+ self._backend, self, signature, algorithm
+ )
+
+ def public_numbers(self):
+ return dsa.DSAPublicNumbers(
+ parameter_numbers=dsa.DSAParameterNumbers(
+ p=self._backend._bn_to_int(self._dsa_cdata.p),
+ q=self._backend._bn_to_int(self._dsa_cdata.q),
+ g=self._backend._bn_to_int(self._dsa_cdata.g)
+ ),
+ y=self._backend._bn_to_int(self._dsa_cdata.pub_key)
+ )
+
+ def parameters(self):
+ dsa_cdata = self._backend._lib.DSA_new()
+ assert dsa_cdata != self._backend._ffi.NULL
+ dsa_cdata = self._backend._ffi.gc(
+ dsa_cdata, self._backend._lib.DSA_free
+ )
+ dsa_cdata.p = self._backend._lib.BN_dup(self._dsa_cdata.p)
+ dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
+ dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
+ return _DSAParameters(self._backend, dsa_cdata)
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index 4d78679e..4675bd0a 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -21,31 +21,38 @@ from cryptography.hazmat.backends.interfaces import DSABackend
from cryptography.hazmat.primitives import interfaces
-def _check_dsa_parameters(modulus, subgroup_order, generator):
- if (
- not isinstance(modulus, six.integer_types) or
- not isinstance(subgroup_order, six.integer_types) or
- not isinstance(generator, six.integer_types)
- ):
- raise TypeError("DSA parameters must be integers.")
-
- if (utils.bit_length(modulus),
- utils.bit_length(subgroup_order)) not in (
+def generate_parameters(key_size, backend):
+ return backend.generate_dsa_parameters(key_size)
+
+
+def generate_private_key(parameters):
+ return parameters._backend.generate_dsa_private_key(parameters)
+
+
+def _check_dsa_parameters(parameters):
+ if (utils.bit_length(parameters.p),
+ utils.bit_length(parameters.q)) not in (
(1024, 160),
(2048, 256),
(3072, 256)):
- raise ValueError("modulus and subgroup_order lengths must be "
+ raise ValueError("p and q lengths must be "
"one of these pairs (1024, 160) or (2048, 256) "
"or (3072, 256).")
- if generator <= 1 or generator >= modulus:
- raise ValueError("generator must be > 1 and < modulus.")
+ if parameters.g <= 1 or parameters.g >= parameters.p:
+ raise ValueError("g must be > 1 and < p.")
@utils.register_interface(interfaces.DSAParameters)
class DSAParameters(object):
def __init__(self, modulus, subgroup_order, generator):
- _check_dsa_parameters(modulus, subgroup_order, generator)
+ _check_dsa_parameters(
+ DSAParameterNumbers(
+ p=modulus,
+ q=subgroup_order,
+ g=generator
+ )
+ )
self._modulus = modulus
self._subgroup_order = subgroup_order
@@ -59,7 +66,13 @@ class DSAParameters(object):
_Reasons.BACKEND_MISSING_INTERFACE
)
- return backend.generate_dsa_parameters(key_size)
+ parameters = backend.generate_dsa_parameters(key_size)
+ numbers = parameters.parameter_numbers()
+ return cls(
+ modulus=numbers.p,
+ subgroup_order=numbers.q,
+ generator=numbers.g
+ )
@property
def modulus(self):
@@ -89,7 +102,13 @@ class DSAParameters(object):
@utils.register_interface(interfaces.DSAPrivateKey)
class DSAPrivateKey(object):
def __init__(self, modulus, subgroup_order, generator, x, y):
- _check_dsa_parameters(modulus, subgroup_order, generator)
+ _check_dsa_parameters(
+ DSAParameterNumbers(
+ p=modulus,
+ q=subgroup_order,
+ g=generator
+ )
+ )
if (
not isinstance(x, six.integer_types) or
not isinstance(y, six.integer_types)
@@ -116,7 +135,15 @@ class DSAPrivateKey(object):
_Reasons.BACKEND_MISSING_INTERFACE
)
- return backend.generate_dsa_private_key(parameters)
+ key = backend.generate_dsa_private_key(parameters)
+ private_numbers = key.private_numbers()
+ return cls(
+ modulus=private_numbers.public_numbers.parameter_numbers.p,
+ subgroup_order=private_numbers.public_numbers.parameter_numbers.q,
+ generator=private_numbers.public_numbers.parameter_numbers.g,
+ x=private_numbers.x,
+ y=private_numbers.public_numbers.y
+ )
def signer(self, algorithm, backend):
if not isinstance(backend, DSABackend):
@@ -151,7 +178,13 @@ class DSAPrivateKey(object):
@utils.register_interface(interfaces.DSAPublicKey)
class DSAPublicKey(object):
def __init__(self, modulus, subgroup_order, generator, y):
- _check_dsa_parameters(modulus, subgroup_order, generator)
+ _check_dsa_parameters(
+ DSAParameterNumbers(
+ p=modulus,
+ q=subgroup_order,
+ g=generator
+ )
+ )
if not isinstance(y, six.integer_types):
raise TypeError("y must be an integer.")
@@ -210,6 +243,9 @@ class DSAParameterNumbers(object):
def g(self):
return self._g
+ def parameters(self, backend):
+ return backend.load_dsa_parameter_numbers(self)
+
class DSAPublicNumbers(object):
def __init__(self, y, parameter_numbers):
@@ -232,6 +268,9 @@ class DSAPublicNumbers(object):
def parameter_numbers(self):
return self._parameter_numbers
+ def public_key(self, backend):
+ return backend.load_dsa_public_numbers(self)
+
class DSAPrivateNumbers(object):
def __init__(self, x, public_numbers):
@@ -252,3 +291,6 @@ class DSAPrivateNumbers(object):
@property
def public_numbers(self):
return self._public_numbers
+
+ def private_key(self, backend):
+ return backend.load_dsa_private_numbers(self)