aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-10-22 20:14:56 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2013-10-22 20:14:56 -0700
commit6deb472b88d18b2b982d5e252a8cc7eb114324d7 (patch)
treea94fb1889f872c6541730a1685e941cd06f05ddf
parent25c0037d0d1bf4b4d426cc03b9390456d127d4d7 (diff)
parent14c3a35447c61e63196a46100a009ee2ea3102a2 (diff)
downloadcryptography-6deb472b88d18b2b982d5e252a8cc7eb114324d7.tar.gz
cryptography-6deb472b88d18b2b982d5e252a8cc7eb114324d7.tar.bz2
cryptography-6deb472b88d18b2b982d5e252a8cc7eb114324d7.zip
Merge pull request #173 from reaperhulk/split-backend
Split backend up (refs #170)
-rw-r--r--cryptography/bindings/openssl/backend.py68
-rw-r--r--cryptography/primitives/block/base.py16
-rw-r--r--cryptography/primitives/hashes.py10
-rw-r--r--tests/bindings/test_openssl.py4
-rw-r--r--tests/primitives/test_cryptrec.py2
-rw-r--r--tests/primitives/test_hash_vectors.py20
-rw-r--r--tests/primitives/test_hashes.py23
-rw-r--r--tests/primitives/test_openssl_vectors.py8
8 files changed, 82 insertions, 69 deletions
diff --git a/cryptography/bindings/openssl/backend.py b/cryptography/bindings/openssl/backend.py
index 492f2e54..9c80be66 100644
--- a/cryptography/bindings/openssl/backend.py
+++ b/cryptography/bindings/openssl/backend.py
@@ -23,15 +23,6 @@ from cryptography.primitives.block.ciphers import AES, Camellia, TripleDES
from cryptography.primitives.block.modes import CBC, CTR, ECB, OFB, CFB
-class GetCipherByName(object):
- def __init__(self, fmt):
- self._fmt = fmt
-
- def __call__(self, backend, cipher, mode):
- cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower()
- return backend.lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
-
-
class Backend(object):
"""
OpenSSL API wrapper.
@@ -99,8 +90,8 @@ class Backend(object):
self.lib.OpenSSL_add_all_algorithms()
self.lib.SSL_load_error_strings()
- self._cipher_registry = {}
- self._register_default_ciphers()
+ self.ciphers = Ciphers(self.ffi, self.lib)
+ self.hashes = Hashes(self.ffi, self.lib)
def openssl_version_text(self):
"""
@@ -110,7 +101,25 @@ class Backend(object):
"""
return self.ffi.string(self.lib.OPENSSL_VERSION_TEXT).decode("ascii")
- def supports_cipher(self, cipher, mode):
+
+class GetCipherByName(object):
+ def __init__(self, fmt):
+ self._fmt = fmt
+
+ def __call__(self, backend, cipher, mode):
+ cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower()
+ return backend.lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
+
+
+class Ciphers(object):
+ def __init__(self, ffi, lib):
+ super(Ciphers, self).__init__()
+ self.ffi = ffi
+ self.lib = lib
+ self._cipher_registry = {}
+ self._register_default_ciphers()
+
+ def supported(self, cipher, mode):
try:
adapter = self._cipher_registry[type(cipher), type(mode)]
except KeyError:
@@ -142,8 +151,8 @@ class Backend(object):
GetCipherByName("des-ede3-{mode.name}")
)
- def create_block_cipher_encrypt_context(self, cipher, mode):
- ctx, evp, iv_nonce = self._create_block_cipher_context(cipher, mode)
+ def create_encrypt_ctx(self, cipher, mode):
+ ctx, evp, iv_nonce = self._create_ctx(cipher, mode)
res = self.lib.EVP_EncryptInit_ex(ctx, evp, self.ffi.NULL, cipher.key,
iv_nonce)
assert res != 0
@@ -152,8 +161,8 @@ class Backend(object):
self.lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
return ctx
- def create_block_cipher_decrypt_context(self, cipher, mode):
- ctx, evp, iv_nonce = self._create_block_cipher_context(cipher, mode)
+ def create_decrypt_ctx(self, cipher, mode):
+ ctx, evp, iv_nonce = self._create_ctx(cipher, mode)
res = self.lib.EVP_DecryptInit_ex(ctx, evp, self.ffi.NULL, cipher.key,
iv_nonce)
assert res != 0
@@ -162,7 +171,7 @@ class Backend(object):
self.lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
return ctx
- def _create_block_cipher_context(self, cipher, mode):
+ def _create_ctx(self, cipher, mode):
ctx = self.lib.EVP_CIPHER_CTX_new()
ctx = self.ffi.gc(ctx, self.lib.EVP_CIPHER_CTX_free)
evp_cipher = self._cipher_registry[type(cipher), type(mode)](
@@ -178,7 +187,7 @@ class Backend(object):
return (ctx, evp_cipher, iv_nonce)
- def update_encrypt_context(self, ctx, data):
+ def update_encrypt_ctx(self, ctx, data):
block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx)
buf = self.ffi.new("unsigned char[]", len(data) + block_size - 1)
outlen = self.ffi.new("int *")
@@ -186,7 +195,7 @@ class Backend(object):
assert res != 0
return self.ffi.buffer(buf)[:outlen[0]]
- def update_decrypt_context(self, ctx, data):
+ def update_decrypt_ctx(self, ctx, data):
block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx)
buf = self.ffi.new("unsigned char[]", len(data) + block_size - 1)
outlen = self.ffi.new("int *")
@@ -194,7 +203,7 @@ class Backend(object):
assert res != 0
return self.ffi.buffer(buf)[:outlen[0]]
- def finalize_encrypt_context(self, ctx):
+ def finalize_encrypt_ctx(self, ctx):
block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx)
buf = self.ffi.new("unsigned char[]", block_size)
outlen = self.ffi.new("int *")
@@ -204,7 +213,7 @@ class Backend(object):
assert res == 1
return self.ffi.buffer(buf)[:outlen[0]]
- def finalize_decrypt_context(self, ctx):
+ def finalize_decrypt_ctx(self, ctx):
block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx)
buf = self.ffi.new("unsigned char[]", block_size)
outlen = self.ffi.new("int *")
@@ -214,11 +223,18 @@ class Backend(object):
assert res == 1
return self.ffi.buffer(buf)[:outlen[0]]
- def supports_hash(self, hash_cls):
+
+class Hashes(object):
+ def __init__(self, ffi, lib):
+ super(Hashes, self).__init__()
+ self.ffi = ffi
+ self.lib = lib
+
+ def supported(self, hash_cls):
return (self.ffi.NULL !=
self.lib.EVP_get_digestbyname(hash_cls.name.encode("ascii")))
- def create_hash_context(self, hashobject):
+ def create_ctx(self, hashobject):
ctx = self.lib.EVP_MD_CTX_create()
ctx = self.ffi.gc(ctx, self.lib.EVP_MD_CTX_destroy)
evp_md = self.lib.EVP_get_digestbyname(hashobject.name.encode("ascii"))
@@ -227,11 +243,11 @@ class Backend(object):
assert res != 0
return ctx
- def update_hash_context(self, ctx, data):
+ def update_ctx(self, ctx, data):
res = self.lib.EVP_DigestUpdate(ctx, data, len(data))
assert res != 0
- def finalize_hash_context(self, ctx, digest_size):
+ def finalize_ctx(self, ctx, digest_size):
buf = self.ffi.new("unsigned char[]", digest_size)
res = self.lib.EVP_DigestFinal_ex(ctx, buf, self.ffi.NULL)
assert res != 0
@@ -239,7 +255,7 @@ class Backend(object):
assert res == 1
return self.ffi.buffer(buf)[:digest_size]
- def copy_hash_context(self, ctx):
+ def copy_ctx(self, ctx):
copied_ctx = self.lib.EVP_MD_CTX_create()
copied_ctx = self.ffi.gc(copied_ctx, self.lib.EVP_MD_CTX_destroy)
res = self.lib.EVP_MD_CTX_copy_ex(copied_ctx, ctx)
diff --git a/cryptography/primitives/block/base.py b/cryptography/primitives/block/base.py
index e9f52887..e9b949c0 100644
--- a/cryptography/primitives/block/base.py
+++ b/cryptography/primitives/block/base.py
@@ -39,19 +39,17 @@ class _CipherEncryptionContext(object):
def __init__(self, cipher, mode, backend):
super(_CipherEncryptionContext, self).__init__()
self._backend = backend
- self._ctx = self._backend.create_block_cipher_encrypt_context(
- cipher, mode
- )
+ self._ctx = self._backend.ciphers.create_encrypt_ctx(cipher, mode)
def update(self, data):
if self._ctx is None:
raise ValueError("Context was already finalized")
- return self._backend.update_encrypt_context(self._ctx, data)
+ return self._backend.ciphers.update_encrypt_ctx(self._ctx, data)
def finalize(self):
if self._ctx is None:
raise ValueError("Context was already finalized")
- data = self._backend.finalize_encrypt_context(self._ctx)
+ data = self._backend.ciphers.finalize_encrypt_ctx(self._ctx)
self._ctx = None
return data
@@ -61,18 +59,16 @@ class _CipherDecryptionContext(object):
def __init__(self, cipher, mode, backend):
super(_CipherDecryptionContext, self).__init__()
self._backend = backend
- self._ctx = self._backend.create_block_cipher_decrypt_context(
- cipher, mode
- )
+ self._ctx = self._backend.ciphers.create_decrypt_ctx(cipher, mode)
def update(self, data):
if self._ctx is None:
raise ValueError("Context was already finalized")
- return self._backend.update_decrypt_context(self._ctx, data)
+ return self._backend.ciphers.update_decrypt_ctx(self._ctx, data)
def finalize(self):
if self._ctx is None:
raise ValueError("Context was already finalized")
- data = self._backend.finalize_decrypt_context(self._ctx)
+ data = self._backend.ciphers.finalize_decrypt_ctx(self._ctx)
self._ctx = None
return data
diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py
index 4cd68adc..023041cb 100644
--- a/cryptography/primitives/hashes.py
+++ b/cryptography/primitives/hashes.py
@@ -27,7 +27,7 @@ class BaseHash(six.with_metaclass(abc.ABCMeta)):
backend = _default_backend
self._backend = backend
if ctx is None:
- self._ctx = self._backend.create_hash_context(self)
+ self._ctx = self._backend.hashes.create_ctx(self)
else:
self._ctx = None
@@ -37,20 +37,20 @@ class BaseHash(six.with_metaclass(abc.ABCMeta)):
def update(self, data):
if isinstance(data, six.text_type):
raise TypeError("Unicode-objects must be encoded before hashing")
- self._backend.update_hash_context(self._ctx, data)
+ 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.finalize_hash_context(self._copy_ctx(),
- self.digest_size)
+ return self._backend.hashes.finalize_ctx(self._copy_ctx(),
+ self.digest_size)
def hexdigest(self):
return str(binascii.hexlify(self.digest()).decode("ascii"))
def _copy_ctx(self):
- return self._backend.copy_hash_context(self._ctx)
+ return self._backend.hashes.copy_ctx(self._ctx)
class SHA1(BaseHash):
diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py
index bdfbed36..6f9c9d25 100644
--- a/tests/bindings/test_openssl.py
+++ b/tests/bindings/test_openssl.py
@@ -34,8 +34,8 @@ class TestOpenSSL(object):
assert backend.openssl_version_text().startswith("OpenSSL")
def test_supports_cipher(self):
- assert backend.supports_cipher(None, None) is False
+ assert backend.ciphers.supported(None, None) is False
def test_register_duplicate_cipher_adapter(self):
with pytest.raises(ValueError):
- backend.register_cipher_adapter(AES, CBC, None)
+ backend.ciphers.register_cipher_adapter(AES, CBC, None)
diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py
index d8c9aaa3..5e0b12df 100644
--- a/tests/primitives/test_cryptrec.py
+++ b/tests/primitives/test_cryptrec.py
@@ -37,7 +37,7 @@ class TestCamelliaECB(object):
],
lambda key: ciphers.Camellia(binascii.unhexlify((key))),
lambda key: modes.ECB(),
- only_if=lambda backend: backend.supports_cipher(
+ only_if=lambda backend: backend.ciphers.supported(
ciphers.Camellia("\x00" * 16), modes.ECB()
),
skip_message="Does not support Camellia ECB",
diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py
index b42021c9..e3854726 100644
--- a/tests/primitives/test_hash_vectors.py
+++ b/tests/primitives/test_hash_vectors.py
@@ -30,7 +30,7 @@ class TestSHA1(object):
"SHA1ShortMsg.rsp",
],
hashes.SHA1,
- only_if=lambda backend: backend.supports_hash(hashes.SHA1),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA1),
skip_message="Does not support SHA1",
)
@@ -44,7 +44,7 @@ class TestSHA224(object):
"SHA224ShortMsg.rsp",
],
hashes.SHA224,
- only_if=lambda backend: backend.supports_hash(hashes.SHA224),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA224),
skip_message="Does not support SHA224",
)
@@ -58,7 +58,7 @@ class TestSHA256(object):
"SHA256ShortMsg.rsp",
],
hashes.SHA256,
- only_if=lambda backend: backend.supports_hash(hashes.SHA256),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA256),
skip_message="Does not support SHA256",
)
@@ -72,7 +72,7 @@ class TestSHA384(object):
"SHA384ShortMsg.rsp",
],
hashes.SHA384,
- only_if=lambda backend: backend.supports_hash(hashes.SHA384),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA384),
skip_message="Does not support SHA384",
)
@@ -86,7 +86,7 @@ class TestSHA512(object):
"SHA512ShortMsg.rsp",
],
hashes.SHA512,
- only_if=lambda backend: backend.supports_hash(hashes.SHA512),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA512),
skip_message="Does not support SHA512",
)
@@ -99,14 +99,14 @@ class TestRIPEMD160(object):
"ripevectors.txt",
],
hashes.RIPEMD160,
- only_if=lambda backend: backend.supports_hash(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hashes.supported(hashes.RIPEMD160),
skip_message="Does not support RIPEMD160",
)
test_RIPEMD160_long_string = generate_long_string_hash_test(
hashes.RIPEMD160,
"52783243c1697bdbe16d37f97f68f08325dc1528",
- only_if=lambda backend: backend.supports_hash(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hashes.supported(hashes.RIPEMD160),
skip_message="Does not support RIPEMD160",
)
@@ -119,7 +119,7 @@ class TestWhirlpool(object):
"iso-test-vectors.txt",
],
hashes.Whirlpool,
- only_if=lambda backend: backend.supports_hash(hashes.Whirlpool),
+ only_if=lambda backend: backend.hashes.supported(hashes.Whirlpool),
skip_message="Does not support Whirlpool",
)
@@ -128,7 +128,7 @@ class TestWhirlpool(object):
("0c99005beb57eff50a7cf005560ddf5d29057fd86b2"
"0bfd62deca0f1ccea4af51fc15490eddc47af32bb2b"
"66c34ff9ad8c6008ad677f77126953b226e4ed8b01"),
- only_if=lambda backend: backend.supports_hash(hashes.Whirlpool),
+ only_if=lambda backend: backend.hashes.supported(hashes.Whirlpool),
skip_message="Does not support Whirlpool",
)
@@ -141,6 +141,6 @@ class TestMD5(object):
"rfc-1321.txt",
],
hashes.MD5,
- only_if=lambda backend: backend.supports_hash(hashes.MD5),
+ only_if=lambda backend: backend.hashes.supported(hashes.MD5),
skip_message="Does not support MD5",
)
diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py
index 2efda050..174fd5f4 100644
--- a/tests/primitives/test_hashes.py
+++ b/tests/primitives/test_hashes.py
@@ -39,17 +39,18 @@ class TestBaseHash(object):
class TestCopyHash(object):
def test_copy_backend_object(self):
- pretend_backend = pretend.stub(copy_hash_context=lambda a: "copiedctx")
+ pretend_hashes = pretend.stub(copy_ctx=lambda a: "copiedctx")
+ pretend_backend = pretend.stub(hashes=pretend_hashes)
pretend_ctx = pretend.stub()
h = hashes.SHA1(backend=pretend_backend, ctx=pretend_ctx)
assert h._backend is pretend_backend
assert h.copy()._backend is h._backend
-class TestDefaultAPISHA1(object):
+class TestDefaultBackendSHA1(object):
def test_default_backend_creation(self):
"""
- This test assumes the presence of SHA1 in the default API.
+ This test assumes the presence of SHA1 in the default backend.
"""
h = hashes.SHA1()
assert h._backend is _default_backend
@@ -60,7 +61,7 @@ class TestSHA1(object):
hashes.SHA1,
digest_size=20,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.SHA1),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA1),
skip_message="Does not support SHA1",
)
@@ -70,7 +71,7 @@ class TestSHA224(object):
hashes.SHA224,
digest_size=28,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.SHA224),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA224),
skip_message="Does not support SHA224",
)
@@ -80,7 +81,7 @@ class TestSHA256(object):
hashes.SHA256,
digest_size=32,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.SHA256),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA256),
skip_message="Does not support SHA256",
)
@@ -90,7 +91,7 @@ class TestSHA384(object):
hashes.SHA384,
digest_size=48,
block_size=128,
- only_if=lambda backend: backend.supports_hash(hashes.SHA384),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA384),
skip_message="Does not support SHA384",
)
@@ -100,7 +101,7 @@ class TestSHA512(object):
hashes.SHA512,
digest_size=64,
block_size=128,
- only_if=lambda backend: backend.supports_hash(hashes.SHA512),
+ only_if=lambda backend: backend.hashes.supported(hashes.SHA512),
skip_message="Does not support SHA512",
)
@@ -110,7 +111,7 @@ class TestRIPEMD160(object):
hashes.RIPEMD160,
digest_size=20,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hashes.supported(hashes.RIPEMD160),
skip_message="Does not support RIPEMD160",
)
@@ -120,7 +121,7 @@ class TestWhirlpool(object):
hashes.Whirlpool,
digest_size=64,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.Whirlpool),
+ only_if=lambda backend: backend.hashes.supported(hashes.Whirlpool),
skip_message="Does not support Whirlpool",
)
@@ -130,6 +131,6 @@ class TestMD5(object):
hashes.MD5,
digest_size=16,
block_size=64,
- only_if=lambda backend: backend.supports_hash(hashes.MD5),
+ only_if=lambda backend: backend.hashes.supported(hashes.MD5),
skip_message="Does not support MD5",
)
diff --git a/tests/primitives/test_openssl_vectors.py b/tests/primitives/test_openssl_vectors.py
index ff42b169..0f242efc 100644
--- a/tests/primitives/test_openssl_vectors.py
+++ b/tests/primitives/test_openssl_vectors.py
@@ -32,7 +32,7 @@ class TestCamelliaCBC(object):
["camellia-cbc.txt"],
lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.CBC(binascii.unhexlify(iv)),
- only_if=lambda backend: backend.supports_cipher(
+ only_if=lambda backend: backend.ciphers.supported(
ciphers.Camellia("\x00" * 16), modes.CBC("\x00" * 16)
),
skip_message="Does not support Camellia CBC",
@@ -46,7 +46,7 @@ class TestCamelliaOFB(object):
["camellia-ofb.txt"],
lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.OFB(binascii.unhexlify(iv)),
- only_if=lambda backend: backend.supports_cipher(
+ only_if=lambda backend: backend.ciphers.supported(
ciphers.Camellia("\x00" * 16), modes.OFB("\x00" * 16)
),
skip_message="Does not support Camellia OFB",
@@ -60,7 +60,7 @@ class TestCamelliaCFB(object):
["camellia-cfb.txt"],
lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.CFB(binascii.unhexlify(iv)),
- only_if=lambda backend: backend.supports_cipher(
+ only_if=lambda backend: backend.ciphers.supported(
ciphers.Camellia("\x00" * 16), modes.CFB("\x00" * 16)
),
skip_message="Does not support Camellia CFB",
@@ -74,7 +74,7 @@ class TestAESCTR(object):
["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"],
lambda key, iv: ciphers.AES(binascii.unhexlify(key)),
lambda key, iv: modes.CTR(binascii.unhexlify(iv)),
- only_if=lambda backend: backend.supports_cipher(
+ only_if=lambda backend: backend.ciphers.supported(
ciphers.AES("\x00" * 16), modes.CTR("\x00" * 16)
),
skip_message="Does not support AES CTR",