diff options
-rw-r--r-- | cryptography/hazmat/bindings/interfaces.py | 59 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/backend.py | 13 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/ciphers/algorithms.py | 13 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/ciphers/base.py | 3 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/ciphers/modes.py | 19 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/hashes.py | 19 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/hmac.py | 3 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/interfaces.py | 7 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/padding.py | 5 | ||||
-rw-r--r-- | cryptography/utils.py | 21 | ||||
-rw-r--r-- | docs/hazmat/bindings/index.rst | 1 | ||||
-rw-r--r-- | docs/hazmat/bindings/interfaces.rst | 129 | ||||
-rw-r--r-- | tests/hazmat/bindings/test_openssl.py | 3 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_block.py | 3 |
14 files changed, 258 insertions, 40 deletions
diff --git a/cryptography/hazmat/bindings/interfaces.py b/cryptography/hazmat/bindings/interfaces.py new file mode 100644 index 00000000..ffcd5f14 --- /dev/null +++ b/cryptography/hazmat/bindings/interfaces.py @@ -0,0 +1,59 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + + +class CipherBackend(six.with_metaclass(abc.ABCMeta)): + @abc.abstractmethod + def cipher_supported(self, cipher, mode): + """ + """ + + @abc.abstractmethod + def register_cipher_adapter(self, cipher, mode): + """ + """ + + @abc.abstractmethod + def create_symmetric_encryption_ctx(self, cipher, mode): + """ + """ + + @abc.abstractmethod + def create_symmetric_decryption_ctx(self, cipher, mode): + """ + """ + + +class HashBackend(six.with_metaclass(abc.ABCMeta)): + @abc.abstractmethod + def hash_supported(self, algorithm): + """ + """ + + @abc.abstractmethod + def create_hash_ctx(self, algorithm): + """ + """ + + +class HMACBackend(six.with_metaclass(abc.ABCMeta)): + @abc.abstractmethod + def create_hmac_ctx(self, key, algorithm): + """ + """ diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 844e175f..db4d18e7 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -18,7 +18,11 @@ import sys import cffi +from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.bindings.interfaces import ( + CipherBackend, HashBackend, HMACBackend +) from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers.algorithms import ( AES, Blowfish, Camellia, CAST5, TripleDES, ARC4, @@ -28,6 +32,9 @@ from cryptography.hazmat.primitives.ciphers.modes import ( ) +@utils.register_interface(CipherBackend) +@utils.register_interface(HashBackend) +@utils.register_interface(HMACBackend) class Backend(object): """ OpenSSL API wrapper. @@ -196,7 +203,7 @@ class GetCipherByName(object): return backend.lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) -@interfaces.register(interfaces.CipherContext) +@utils.register_interface(interfaces.CipherContext) class _CipherContext(object): _ENCRYPT = 1 _DECRYPT = 0 @@ -267,7 +274,7 @@ class _CipherContext(object): return self._backend.ffi.buffer(buf)[:outlen[0]] -@interfaces.register(interfaces.HashContext) +@utils.register_interface(interfaces.HashContext) class _HashContext(object): def __init__(self, backend, algorithm, ctx=None): self.algorithm = algorithm @@ -310,7 +317,7 @@ class _HashContext(object): return self._backend.ffi.buffer(buf)[:] -@interfaces.register(interfaces.HashContext) +@utils.register_interface(interfaces.HashContext) class _HMACContext(object): def __init__(self, backend, key, algorithm, ctx=None): self.algorithm = algorithm diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index 1ed487b6..75a87265 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -13,10 +13,11 @@ from __future__ import absolute_import, division, print_function +from cryptography import utils from cryptography.hazmat.primitives import interfaces -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class AES(object): name = "AES" block_size = 128 @@ -36,7 +37,7 @@ class AES(object): return len(self.key) * 8 -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class Camellia(object): name = "camellia" block_size = 128 @@ -56,7 +57,7 @@ class Camellia(object): return len(self.key) * 8 -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class TripleDES(object): name = "3DES" block_size = 64 @@ -80,7 +81,7 @@ class TripleDES(object): return len(self.key) * 8 -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class Blowfish(object): name = "Blowfish" block_size = 64 @@ -100,7 +101,7 @@ class Blowfish(object): return len(self.key) * 8 -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class CAST5(object): name = "CAST5" block_size = 64 @@ -120,7 +121,7 @@ class CAST5(object): return len(self.key) * 8 -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class ARC4(object): name = "RC4" block_size = 1 diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index 78bf7e0c..3d733afc 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -13,6 +13,7 @@ from __future__ import absolute_import, division, print_function +from cryptography import utils from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces @@ -42,7 +43,7 @@ class Cipher(object): )) -@interfaces.register(interfaces.CipherContext) +@utils.register_interface(interfaces.CipherContext) class _CipherContext(object): def __init__(self, ctx): self._ctx = ctx diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py index 915fd83d..1d0de689 100644 --- a/cryptography/hazmat/primitives/ciphers/modes.py +++ b/cryptography/hazmat/primitives/ciphers/modes.py @@ -13,11 +13,12 @@ from __future__ import absolute_import, division, print_function +from cryptography import utils from cryptography.hazmat.primitives import interfaces -@interfaces.register(interfaces.Mode) -@interfaces.register(interfaces.ModeWithInitializationVector) +@utils.register_interface(interfaces.Mode) +@utils.register_interface(interfaces.ModeWithInitializationVector) class CBC(object): name = "CBC" @@ -25,13 +26,13 @@ class CBC(object): self.initialization_vector = initialization_vector -@interfaces.register(interfaces.Mode) +@utils.register_interface(interfaces.Mode) class ECB(object): name = "ECB" -@interfaces.register(interfaces.Mode) -@interfaces.register(interfaces.ModeWithInitializationVector) +@utils.register_interface(interfaces.Mode) +@utils.register_interface(interfaces.ModeWithInitializationVector) class OFB(object): name = "OFB" @@ -39,8 +40,8 @@ class OFB(object): self.initialization_vector = initialization_vector -@interfaces.register(interfaces.Mode) -@interfaces.register(interfaces.ModeWithInitializationVector) +@utils.register_interface(interfaces.Mode) +@utils.register_interface(interfaces.ModeWithInitializationVector) class CFB(object): name = "CFB" @@ -48,8 +49,8 @@ class CFB(object): self.initialization_vector = initialization_vector -@interfaces.register(interfaces.Mode) -@interfaces.register(interfaces.ModeWithNonce) +@utils.register_interface(interfaces.Mode) +@utils.register_interface(interfaces.ModeWithNonce) class CTR(object): name = "CTR" diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index 86c9fe2e..93fc8c42 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, division, print_function import six +from cryptography import utils from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces -@interfaces.register(interfaces.HashContext) +@utils.register_interface(interfaces.HashContext) class Hash(object): def __init__(self, algorithm, backend=None, ctx=None): if not isinstance(algorithm, interfaces.HashAlgorithm): @@ -59,56 +60,56 @@ class Hash(object): return digest -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class SHA1(object): name = "sha1" digest_size = 20 block_size = 64 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class SHA224(object): name = "sha224" digest_size = 28 block_size = 64 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class SHA256(object): name = "sha256" digest_size = 32 block_size = 64 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class SHA384(object): name = "sha384" digest_size = 48 block_size = 128 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class SHA512(object): name = "sha512" digest_size = 64 block_size = 128 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class RIPEMD160(object): name = "ripemd160" digest_size = 20 block_size = 64 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class Whirlpool(object): name = "whirlpool" digest_size = 64 block_size = 64 -@interfaces.register(interfaces.HashAlgorithm) +@utils.register_interface(interfaces.HashAlgorithm) class MD5(object): name = "md5" digest_size = 16 diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 1bbe39c7..08dfae01 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, division, print_function import six +from cryptography import utils from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces -@interfaces.register(interfaces.HashContext) +@utils.register_interface(interfaces.HashContext) class HMAC(object): def __init__(self, key, algorithm, ctx=None, backend=None): if not isinstance(algorithm, interfaces.HashAlgorithm): diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py index bbbb266c..8cc9d42c 100644 --- a/cryptography/hazmat/primitives/interfaces.py +++ b/cryptography/hazmat/primitives/interfaces.py @@ -18,13 +18,6 @@ import abc import six -def register(iface): - def register_decorator(klass): - iface.register(klass) - return klass - return register_decorator - - class CipherAlgorithm(six.with_metaclass(abc.ABCMeta)): @abc.abstractproperty def name(self): diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py index f41c62c3..2dbac752 100644 --- a/cryptography/hazmat/primitives/padding.py +++ b/cryptography/hazmat/primitives/padding.py @@ -13,6 +13,7 @@ import six +from cryptography import utils from cryptography.hazmat.primitives import interfaces @@ -33,7 +34,7 @@ class PKCS7(object): return _PKCS7UnpaddingContext(self.block_size) -@interfaces.register(interfaces.PaddingContext) +@utils.register_interface(interfaces.PaddingContext) class _PKCS7PaddingContext(object): def __init__(self, block_size): self.block_size = block_size @@ -67,7 +68,7 @@ class _PKCS7PaddingContext(object): return result -@interfaces.register(interfaces.PaddingContext) +@utils.register_interface(interfaces.PaddingContext) class _PKCS7UnpaddingContext(object): def __init__(self, block_size): self.block_size = block_size diff --git a/cryptography/utils.py b/cryptography/utils.py new file mode 100644 index 00000000..e697d515 --- /dev/null +++ b/cryptography/utils.py @@ -0,0 +1,21 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import, division, print_function + + +def register_interface(iface): + def register_decorator(klass): + iface.register(klass) + return klass + return register_decorator diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst index 19e03999..11355bfa 100644 --- a/docs/hazmat/bindings/index.rst +++ b/docs/hazmat/bindings/index.rst @@ -7,3 +7,4 @@ Bindings :maxdepth: 1 openssl + interfaces diff --git a/docs/hazmat/bindings/interfaces.rst b/docs/hazmat/bindings/interfaces.rst new file mode 100644 index 00000000..98c099bb --- /dev/null +++ b/docs/hazmat/bindings/interfaces.rst @@ -0,0 +1,129 @@ +.. hazmat:: + +Backend Interfaces +================== + +.. currentmodule:: cryptography.hazmat.bindings.interfaces + + +.. class:: CipherBackend + + A backend which provides methods for using ciphers for encryption + and decryption. + + .. method:: cipher_supported(cipher, mode) + + Check if a ``cipher`` and ``mode`` combination is supported by + this backend. + + :param cipher: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` + provider. + :param mode: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider. + + :returns: ``True`` if the specified ``cipher`` and ``mode`` combination + is supported by this backend, otherwise ``False`` + + .. method:: register_cipher_adapter(cipher_cls, mode_cls, adapter) + + Register an adapter which can be used to create a backend specific + object from instances of the + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` and + the :class:`~cryptography.hazmat.primitives.interfaces.Mode` primitives. + + :param cipher_cls: A class whose instances provide + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` + :param mode_cls: A class whose instances provide: + :class:`~cryptography.hazmat.primitives.interfaces.Mode` + :param adapter: A ``function`` that takes 3 arguments, ``backend`` (a + :class:`CipherBackend` provider), ``cipher`` (a + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` + provider ), and ``mode`` (a + :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider). + It returns a backend specific object which may be used to construct + a :class:`~cryptogrpahy.hazmat.primitives.interfaces.CipherContext`. + + + .. method:: create_symmetric_encryption_ctx(cipher, mode) + + Create a + :class:`~cryptogrpahy.hazmat.primitives.interfaces.CipherContext` that + can be used for encrypting data with the symmetric ``cipher`` using + the given ``mode``. + + :param cipher: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` + provider. + :param mode: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider. + + :returns: + :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` + + + .. method:: create_symmetric_decryption_ctx(cipher, mode) + + Create a + :class:`~cryptogrpahy.hazmat.primitives.interfaces.CipherContext` that + can be used for decrypting data with the symmetric ``cipher`` using + the given ``mode``. + + :param cipher: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm` + provider. + :param mode: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider. + + :returns: + :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` + + +.. class:: HashBackend + + A backend with methods for using cryptographic hash functions. + + .. method:: hash_supported(algorithm) + + Check if the specified ``algorithm`` is supported by this backend. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` + provider. + + :returns: ``True`` if the specified ``algorithm`` is supported by this + backend, otherwise ``False``. + + + .. method:: create_hash_ctx(algorithm) + + Create a + :class:`~cryptogrpahy.hazmat.primitives.interfaces.HashContext` that + uses the specified ``algorithm`` to calculate a message digest. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` + provider. + + :returns: + :class:`~cryptography.hazmat.primitives.interfaces.HashContext` + + +.. class:: HMACBackend + + A backend with methods for using cryptographic hash functions as message + authentication codes. + + .. method:: create_hmac_ctx(algorithm) + + Create a + :class:`~cryptogrpahy.hazmat.primitives.interfaces.HashContext` that + uses the specified ``algorithm`` to calculate a hash-based message + authentication code. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` + provider. + + :returns: + :class:`~cryptography.hazmat.primitives.interfaces.HashContext` diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index e4f8dd8b..9f27aab7 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -13,6 +13,7 @@ import pytest +from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.bindings.openssl.backend import backend, Backend from cryptography.hazmat.primitives import interfaces @@ -25,7 +26,7 @@ class DummyMode(object): pass -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class DummyCipher(object): pass diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 963136b9..9460c53d 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -17,6 +17,7 @@ import binascii import pytest +from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, AlreadyFinalized from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers import ( @@ -24,7 +25,7 @@ from cryptography.hazmat.primitives.ciphers import ( ) -@interfaces.register(interfaces.CipherAlgorithm) +@utils.register_interface(interfaces.CipherAlgorithm) class DummyCipher(object): pass |