aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography/hazmat
diff options
context:
space:
mode:
Diffstat (limited to 'cryptography/hazmat')
-rw-r--r--cryptography/hazmat/bindings/openssl/backend.py10
-rw-r--r--cryptography/hazmat/primitives/hashes.py59
-rw-r--r--cryptography/hazmat/primitives/hmac.py38
-rw-r--r--cryptography/hazmat/primitives/interfaces.py46
4 files changed, 100 insertions, 53 deletions
diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py
index fc73dd39..32adfed9 100644
--- a/cryptography/hazmat/bindings/openssl/backend.py
+++ b/cryptography/hazmat/bindings/openssl/backend.py
@@ -18,6 +18,7 @@ import sys
import cffi
+from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import interfaces
from cryptography.hazmat.primitives.block.ciphers import (
AES, Blowfish, Camellia, CAST5, TripleDES,
@@ -128,9 +129,12 @@ class _CipherContext(object):
ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
registry = self._backend.ciphers._cipher_registry
- evp_cipher = registry[type(cipher), type(mode)](
- self._backend, cipher, mode
- )
+ try:
+ adapter = registry[type(cipher), type(mode)]
+ except KeyError:
+ raise UnsupportedAlgorithm
+
+ evp_cipher = adapter(self._backend, cipher, mode)
assert evp_cipher != self._backend.ffi.NULL
if isinstance(mode, interfaces.ModeWithInitializationVector):
iv_nonce = mode.initialization_vector
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index 3ccb59d1..bdad5e16 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -13,89 +13,94 @@
from __future__ import absolute_import, division, print_function
-import abc
+import six
-import binascii
+from cryptography.hazmat.primitives import interfaces
-import six
+@interfaces.register(interfaces.HashContext)
+class Hash(object):
+ def __init__(self, algorithm, backend=None, ctx=None):
+ if not isinstance(algorithm, interfaces.HashAlgorithm):
+ raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+ self.algorithm = algorithm
-class BaseHash(six.with_metaclass(abc.ABCMeta)):
- def __init__(self, data=None, backend=None, ctx=None):
if backend is None:
from cryptography.hazmat.bindings import _default_backend
backend = _default_backend
+
self._backend = backend
+
if ctx is None:
- self._ctx = self._backend.hashes.create_ctx(self)
+ self._ctx = self._backend.hashes.create_ctx(self.algorithm)
else:
self._ctx = None
- if data is not None:
- self.update(data)
-
def update(self, data):
if isinstance(data, six.text_type):
raise TypeError("Unicode-objects must be encoded before hashing")
self._backend.hashes.update_ctx(self._ctx, data)
def copy(self):
- return self.__class__(backend=self._backend, ctx=self._copy_ctx())
-
- def digest(self):
- return self._backend.hashes.finalize_ctx(self._copy_ctx(),
- self.digest_size)
-
- def hexdigest(self):
- return str(binascii.hexlify(self.digest()).decode("ascii"))
+ return self.__class__(self.algorithm, backend=self._backend,
+ ctx=self._backend.hashes.copy_ctx(self._ctx))
- def _copy_ctx(self):
- return self._backend.hashes.copy_ctx(self._ctx)
+ def finalize(self):
+ return self._backend.hashes.finalize_ctx(self._ctx,
+ self.algorithm.digest_size)
-class SHA1(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class SHA1(object):
name = "sha1"
digest_size = 20
block_size = 64
-class SHA224(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class SHA224(object):
name = "sha224"
digest_size = 28
block_size = 64
-class SHA256(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class SHA256(object):
name = "sha256"
digest_size = 32
block_size = 64
-class SHA384(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class SHA384(object):
name = "sha384"
digest_size = 48
block_size = 128
-class SHA512(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class SHA512(object):
name = "sha512"
digest_size = 64
block_size = 128
-class RIPEMD160(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class RIPEMD160(object):
name = "ripemd160"
digest_size = 20
block_size = 64
-class Whirlpool(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class Whirlpool(object):
name = "whirlpool"
digest_size = 64
block_size = 64
-class MD5(BaseHash):
+@interfaces.register(interfaces.HashAlgorithm)
+class MD5(object):
name = "md5"
digest_size = 16
block_size = 64
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 4da0cc3f..1457ed78 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -13,47 +13,39 @@
from __future__ import absolute_import, division, print_function
-import binascii
-
import six
+from cryptography.hazmat.primitives import interfaces
+
+@interfaces.register(interfaces.HashContext)
class HMAC(object):
- def __init__(self, key, msg=None, digestmod=None, ctx=None, backend=None):
+ def __init__(self, key, algorithm, ctx=None, backend=None):
super(HMAC, self).__init__()
+ if not isinstance(algorithm, interfaces.HashAlgorithm):
+ raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+ self.algorithm = algorithm
+
if backend is None:
from cryptography.hazmat.bindings import _default_backend
backend = _default_backend
- if digestmod is None:
- raise TypeError("digestmod is a required argument")
-
self._backend = backend
- self.digestmod = digestmod
- self.key = key
+ self._key = key
if ctx is None:
- self._ctx = self._backend.hmacs.create_ctx(key, self.digestmod)
+ self._ctx = self._backend.hmacs.create_ctx(key, self.algorithm)
else:
self._ctx = ctx
- if msg is not None:
- self.update(msg)
-
def update(self, msg):
if isinstance(msg, six.text_type):
raise TypeError("Unicode-objects must be encoded before hashing")
self._backend.hmacs.update_ctx(self._ctx, msg)
def copy(self):
- return self.__class__(self.key, digestmod=self.digestmod,
- backend=self._backend, ctx=self._copy_ctx())
-
- def digest(self):
- return self._backend.hmacs.finalize_ctx(self._copy_ctx(),
- self.digestmod.digest_size)
-
- def hexdigest(self):
- return str(binascii.hexlify(self.digest()).decode("ascii"))
+ return self.__class__(self._key, self.algorithm, backend=self._backend,
+ ctx=self._backend.hmacs.copy_ctx(self._ctx))
- def _copy_ctx(self):
- return self._backend.hmacs.copy_ctx(self._ctx)
+ def finalize(self):
+ return self._backend.hmacs.finalize_ctx(self._ctx,
+ self.algorithm.digest_size)
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index 217490fd..ebf5e31e 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -59,3 +59,49 @@ class PaddingContext(six.with_metaclass(abc.ABCMeta)):
"""
finalize return bytes
"""
+
+
+class HashAlgorithm(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def name(self):
+ """
+ A string naming this algorithm. (ex. sha256, md5)
+ """
+
+ @abc.abstractproperty
+ def digest_size(self):
+ """
+ The size of the resulting digest in bytes.
+ """
+
+ @abc.abstractproperty
+ def block_size(self):
+ """
+ The internal block size of the hash algorithm in bytes.
+ """
+
+
+class HashContext(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def algorithm(self):
+ """
+ A HashAlgorithm that will be used by this context.
+ """
+
+ @abc.abstractmethod
+ def update(self, data):
+ """
+ hash data as bytes
+ """
+
+ @abc.abstractmethod
+ def finalize(self):
+ """
+ finalize this copy of the hash and return the digest as bytes.
+ """
+
+ @abc.abstractmethod
+ def copy(self):
+ """
+ return a HashContext that is a copy of the current context.
+ """