aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorDavid Reid <dreid@dreid.org>2014-05-01 12:56:56 -0700
committerDavid Reid <dreid@dreid.org>2014-05-01 12:56:56 -0700
commit7d47b98e0e95f759a18e2651a5cc6e466bccef9f (patch)
tree9d0e0ef64fde6f79f8a3d29c7f42ca2a3b94f8e8 /cryptography
parent7f39ebc6b32c4e3a92f17357271668c9553dc830 (diff)
parentf58d1ab6cf5d90ae06a593fca52ab388d75da068 (diff)
downloadcryptography-7d47b98e0e95f759a18e2651a5cc6e466bccef9f.tar.gz
cryptography-7d47b98e0e95f759a18e2651a5cc6e466bccef9f.tar.bz2
cryptography-7d47b98e0e95f759a18e2651a5cc6e466bccef9f.zip
Merge pull request #982 from reaperhulk/dsa-verify
DSA verification
Diffstat (limited to 'cryptography')
-rw-r--r--cryptography/hazmat/backends/interfaces.py19
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py72
-rw-r--r--cryptography/hazmat/primitives/asymmetric/dsa.py10
3 files changed, 101 insertions, 0 deletions
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index aaaca5e2..e63b079b 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -145,6 +145,25 @@ class DSABackend(object):
a DSAParameters object.
"""
+ @abc.abstractmethod
+ def create_dsa_verification_ctx(self, public_key, signature, algorithm):
+ """
+ Returns an object conforming to the AsymmetricVerificationContext
+ interface.
+ """
+
+ @abc.abstractmethod
+ def dsa_hash_supported(self, algorithm):
+ """
+ Return True if the hash algorithm is supported by the backend for DSA.
+ """
+
+ @abc.abstractmethod
+ def dsa_parameters_supported(self, p, q, g):
+ """
+ Return True if the parameters are supported by the backend for DSA.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class TraditionalOpenSSLSerializationBackend(object):
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index f9154f3b..37deb2ae 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -474,6 +474,35 @@ class Backend(object):
y=self._bn_to_int(ctx.pub_key)
)
+ def create_dsa_verification_ctx(self, public_key, signature,
+ algorithm):
+ return _DSAVerificationContext(self, public_key, signature,
+ algorithm)
+
+ def _dsa_cdata_from_public_key(self, public_key):
+ # Does not GC the DSA cdata. You *must* make sure it's freed
+ # correctly yourself!
+ ctx = self._lib.DSA_new()
+ assert ctx != self._ffi.NULL
+ parameters = public_key.parameters()
+ ctx.p = self._int_to_bn(parameters.p)
+ ctx.q = self._int_to_bn(parameters.q)
+ ctx.g = self._int_to_bn(parameters.g)
+ ctx.pub_key = self._int_to_bn(public_key.y)
+ return ctx
+
+ def dsa_hash_supported(self, algorithm):
+ if self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f:
+ return isinstance(algorithm, hashes.SHA1)
+ else:
+ return self.hash_supported(algorithm)
+
+ def dsa_parameters_supported(self, p, q, g):
+ if self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f:
+ return (utils.bit_length(p) <= 1024 and utils.bit_length(q) <= 160)
+ else:
+ return True
+
def decrypt_rsa(self, private_key, ciphertext, padding):
key_size_bytes = int(math.ceil(private_key.key_size / 8.0))
if key_size_bytes != len(ciphertext):
@@ -1297,6 +1326,49 @@ class _RSAVerificationContext(object):
raise InvalidSignature
+@utils.register_interface(interfaces.AsymmetricVerificationContext)
+class _DSAVerificationContext(object):
+ def __init__(self, backend, public_key, signature, algorithm):
+ self._backend = backend
+ self._public_key = public_key
+ self._signature = signature
+ self._algorithm = algorithm
+
+ self._hash_ctx = _HashContext(backend, self._algorithm)
+
+ def update(self, data):
+ if self._hash_ctx is None:
+ raise AlreadyFinalized("Context has already been finalized")
+
+ self._hash_ctx.update(data)
+
+ def verify(self):
+ if self._hash_ctx is None:
+ raise AlreadyFinalized("Context has already been finalized")
+
+ self._dsa_cdata = self._backend._dsa_cdata_from_public_key(
+ self._public_key)
+ self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata,
+ self._backend._lib.DSA_free)
+
+ data_to_verify = self._hash_ctx.finalize()
+ self._hash_ctx = None
+
+ # The first parameter passed to DSA_verify is unused by OpenSSL but
+ # 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)
+
+ if res != 1:
+ errors = self._backend._consume_errors()
+ assert errors
+ if res == -1:
+ assert errors[0].lib == self._backend._lib.ERR_LIB_ASN1
+
+ raise InvalidSignature
+
+
@utils.register_interface(interfaces.CMACContext)
class _CMACContext(object):
def __init__(self, backend, algorithm, ctx=None):
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index 4c2de36a..57a7ef3d 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -151,6 +151,16 @@ class DSAPublicKey(object):
self._generator = generator
self._y = y
+ def verifier(self, signature, algorithm, backend):
+ if not isinstance(backend, DSABackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement DSABackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
+ return backend.create_dsa_verification_ctx(self, signature,
+ algorithm)
+
@property
def key_size(self):
return utils.bit_length(self._modulus)