diff options
author | Donald Stufft <donald@stufft.io> | 2013-10-21 15:39:18 -0700 |
---|---|---|
committer | Donald Stufft <donald@stufft.io> | 2013-10-21 15:39:18 -0700 |
commit | c160079df8dd021b6b1e8091025ba27ddc6cd6c0 (patch) | |
tree | dcbc2e2491bffc6ad19eea41bbeeba85d65a48b3 /cryptography | |
parent | 71ed449ffe7e26e9217b6c44bb27e19996315a64 (diff) | |
parent | 6f874ff9279376b6962c514ae0e59b90e7082e15 (diff) | |
download | cryptography-c160079df8dd021b6b1e8091025ba27ddc6cd6c0.tar.gz cryptography-c160079df8dd021b6b1e8091025ba27ddc6cd6c0.tar.bz2 cryptography-c160079df8dd021b6b1e8091025ba27ddc6cd6c0.zip |
Merge pull request #109 from alex/refactor-cipher-names
[WIP] Refactor how cipher names are computed
Diffstat (limited to 'cryptography')
-rw-r--r-- | cryptography/bindings/openssl/api.py | 51 | ||||
-rw-r--r-- | cryptography/primitives/block/base.py | 4 |
2 files changed, 44 insertions, 11 deletions
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 12082c09..7d189d62 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -13,11 +13,23 @@ from __future__ import absolute_import, division, print_function +import itertools import sys import cffi from cryptography.primitives import interfaces +from cryptography.primitives.block.ciphers import AES, Camellia +from cryptography.primitives.block.modes import CBC, CTR, ECB, OFB, CFB + + +class GetCipherByName(object): + def __init__(self, fmt): + self._fmt = fmt + + def __call__(self, api, cipher, mode): + cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() + return api.lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) class API(object): @@ -87,6 +99,9 @@ class API(object): self.lib.OpenSSL_add_all_algorithms() self.lib.SSL_load_error_strings() + self._cipher_registry = {} + self._register_default_ciphers() + def openssl_version_text(self): """ Friendly string name of linked OpenSSL. @@ -95,18 +110,38 @@ class API(object): """ return self.ffi.string(self.lib.OPENSSL_VERSION_TEXT).decode("ascii") - def supports_cipher(self, ciphername): - return (self.ffi.NULL != - self.lib.EVP_get_cipherbyname(ciphername.encode("ascii"))) + def supports_cipher(self, cipher, mode): + try: + adapter = self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + evp_cipher = adapter(self, cipher, mode) + return self.ffi.NULL != evp_cipher + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError("Duplicate registration for: {0} {1}".format( + cipher_cls, mode_cls) + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self): + for cipher_cls, mode_cls in itertools.product( + [AES, Camellia], + [CBC, CTR, ECB, OFB, CFB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") + ) def create_block_cipher_context(self, cipher, mode): ctx = self.lib.EVP_CIPHER_CTX_new() ctx = self.ffi.gc(ctx, self.lib.EVP_CIPHER_CTX_free) - # TODO: compute name using a better algorithm - ciphername = "{0}-{1}-{2}".format( - cipher.name, cipher.key_size, mode.name - ).lower() - evp_cipher = self.lib.EVP_get_cipherbyname(ciphername.encode("ascii")) + evp_cipher = self._cipher_registry[type(cipher), type(mode)]( + self, cipher, mode + ) assert evp_cipher != self.ffi.NULL if isinstance(mode, interfaces.ModeWithInitializationVector): iv_nonce = mode.initialization_vector diff --git a/cryptography/primitives/block/base.py b/cryptography/primitives/block/base.py index 50e9e9e5..42c1f799 100644 --- a/cryptography/primitives/block/base.py +++ b/cryptography/primitives/block/base.py @@ -15,8 +15,6 @@ from __future__ import absolute_import, division, print_function from enum import Enum -from cryptography.bindings import _default_api - class _Operation(Enum): encrypt = 0 @@ -28,7 +26,7 @@ class BlockCipher(object): super(BlockCipher, self).__init__() if api is None: - api = _default_api + from cryptography.bindings import _default_api as api self.cipher = cipher self.mode = mode |