From 13f108f926a84eec9c0598164f25cedaece567e3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 9 Sep 2013 21:41:03 -0500 Subject: Add ECB class + docs + tests * Slightly refactors test_nist to allow fetching of data that has no IV * Does not modify create_block_cipher_context (next commit) --- cryptography/primitives/block/modes.py | 7 +++++ docs/primitives/symmetric-encryption.rst | 12 ++++++++ tests/primitives/test_nist.py | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index de31f086..0bf8010b 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -20,3 +20,10 @@ class CBC(object): def __init__(self, initialization_vector): super(CBC, self).__init__() self.initialization_vector = initialization_vector + + +class ECB(object): + name = "ECB" + + def __init__(self): + super(ECB, self).__init__() diff --git a/docs/primitives/symmetric-encryption.rst b/docs/primitives/symmetric-encryption.rst index 1b8d1d73..8a9bbbdf 100644 --- a/docs/primitives/symmetric-encryption.rst +++ b/docs/primitives/symmetric-encryption.rst @@ -67,3 +67,15 @@ Modes ``block_size`` of the cipher. Do not reuse an ``initialization_vector`` with a given ``key``. + + +Insecure Modes +-------------- + +.. class:: cryptography.primitives.block.modes.ECB() + + ECB (Electronic Code Book) is the simplest mode of operation for block + ciphers. The data is separated into blocks and each block is encrypted + separately. This means identical plaintext blocks will always result in + identical encrypted blocks. Due to this property it is not recommended + for use. Really, don't use it. Just. Don't. diff --git a/tests/primitives/test_nist.py b/tests/primitives/test_nist.py index 8bef118e..3dc8277a 100644 --- a/tests/primitives/test_nist.py +++ b/tests/primitives/test_nist.py @@ -86,3 +86,50 @@ class TestAES_CBC(object): actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) actual_ciphertext += cipher.finalize() assert binascii.hexlify(actual_ciphertext) == ciphertext + + +class TestAES_ECB(object): + @parameterize_encrypt_test( + "AES", "KAT", + ("key", "plaintext", "ciphertext"), + [ + "ECBGFSbox128.rsp", + "ECBGFSbox192.rsp", + "ECBGFSbox256.rsp", + "ECBKeySbox128.rsp", + "ECBKeySbox192.rsp", + "ECBKeySbox256.rsp", + "ECBVarKey128.rsp", + "ECBVarKey192.rsp", + "ECBVarKey256.rsp", + "ECBVarTxt128.rsp", + "ECBVarTxt192.rsp", + "ECBVarTxt256.rsp", + ] + ) + def test_KAT(self, key, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.AES(binascii.unhexlify(key)), + modes.ECB() + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext) == ciphertext + + @parameterize_encrypt_test( + "AES", "MMT", + ("key", "plaintext", "ciphertext"), + [ + "ECBMMT128.rsp", + "ECBMMT192.rsp", + "ECBMMT256.rsp", + ] + ) + def test_MMT(self, key, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.AES(binascii.unhexlify(key)), + modes.ECB() + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext) == ciphertext -- cgit v1.2.3 From fe9b82d1526113f6f08e5de9b8d5e75ab1527bbd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 9 Sep 2013 22:09:21 -0500 Subject: add ECB support to create_block_cipher_context * This is a basic refactor to support ECB and CBC mode in this method. We can use this as a starting point to discuss a better solution. --- cryptography/bindings/openssl/api.py | 14 +++++++++++++- tests/bindings/test_openssl.py | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 54a74d03..17823786 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -74,9 +74,11 @@ class API(object): assert evp_cipher != self._ffi.NULL # TODO: only use the key and initialization_vector as needed. Sometimes # this needs to be a DecryptInit, when? + iv = self._get_iv(mode) + res = self._lib.EVP_EncryptInit_ex( ctx, evp_cipher, self._ffi.NULL, cipher.key, - mode.initialization_vector + iv ) assert res != 0 @@ -85,6 +87,16 @@ class API(object): self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) return ctx + def _get_iv(self, mode): + # TODO: refactor this to visitor pattern + klass_name = mode.__class__.__name__ + if klass_name == 'CBC': + return mode.initialization_vector + elif klass_name == 'ECB': + return self._ffi.NULL + else: + raise NotImplementedError + def update_encrypt_context(self, ctx, plaintext): buf = self._ffi.new("unsigned char[]", len(plaintext)) outlen = self._ffi.new("int *") diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index 1579f002..e4b73460 100644 --- a/tests/bindings/test_openssl.py +++ b/tests/bindings/test_openssl.py @@ -11,6 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import pytest + from cryptography.bindings.openssl import api @@ -28,3 +30,7 @@ class TestOpenSSL(object): for every OpenSSL. """ assert api.openssl_version_text().startswith("OpenSSL") + + def test_get_iv_invalid_mode(self): + with pytest.raises(NotImplementedError): + api._get_iv(None) -- cgit v1.2.3 From 09980a55fe5a3e4f586425a11b20ba89e84d0452 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 08:24:30 -0500 Subject: remove unneeded init in ECB class, add warning to docs for ECB mode --- cryptography/primitives/block/modes.py | 3 --- docs/primitives/symmetric-encryption.rst | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index 0bf8010b..ac3392c5 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -24,6 +24,3 @@ class CBC(object): class ECB(object): name = "ECB" - - def __init__(self): - super(ECB, self).__init__() diff --git a/docs/primitives/symmetric-encryption.rst b/docs/primitives/symmetric-encryption.rst index 8a9bbbdf..d0429d4b 100644 --- a/docs/primitives/symmetric-encryption.rst +++ b/docs/primitives/symmetric-encryption.rst @@ -72,6 +72,7 @@ Modes Insecure Modes -------------- +.. warning:: Do not use. This is an insecure mode. .. class:: cryptography.primitives.block.modes.ECB() ECB (Electronic Code Book) is the simplest mode of operation for block -- cgit v1.2.3 From 29cfa6989bfbc9545c2b40e9e3b316e89c0c14ca Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 10:01:50 -0500 Subject: add get_iv_or_nonce() methods to replace _get_iv() on api --- cryptography/bindings/openssl/api.py | 18 +++++------------- cryptography/primitives/block/modes.py | 6 ++++++ tests/bindings/test_openssl.py | 7 ++----- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 17823786..02957d74 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -72,13 +72,12 @@ class API(object): ) evp_cipher = self._lib.EVP_get_cipherbyname(ciphername.encode("ascii")) assert evp_cipher != self._ffi.NULL - # TODO: only use the key and initialization_vector as needed. Sometimes - # this needs to be a DecryptInit, when? - iv = self._get_iv(mode) + iv_nonce = mode.get_iv_or_nonce(self) + # TODO: Sometimes this needs to be a DecryptInit, when? res = self._lib.EVP_EncryptInit_ex( ctx, evp_cipher, self._ffi.NULL, cipher.key, - iv + iv_nonce ) assert res != 0 @@ -87,15 +86,8 @@ class API(object): self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) return ctx - def _get_iv(self, mode): - # TODO: refactor this to visitor pattern - klass_name = mode.__class__.__name__ - if klass_name == 'CBC': - return mode.initialization_vector - elif klass_name == 'ECB': - return self._ffi.NULL - else: - raise NotImplementedError + def get_null_for_ecb(self): + return self._ffi.NULL def update_encrypt_context(self, ctx, plaintext): buf = self._ffi.new("unsigned char[]", len(plaintext)) diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index ac3392c5..82141437 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -21,6 +21,12 @@ class CBC(object): super(CBC, self).__init__() self.initialization_vector = initialization_vector + def get_iv_or_nonce(self, api): + return self.initialization_vector + class ECB(object): name = "ECB" + + def get_iv_or_nonce(self, api): + return api.get_null_for_ecb() diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index e4b73460..c5927b76 100644 --- a/tests/bindings/test_openssl.py +++ b/tests/bindings/test_openssl.py @@ -11,8 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest - from cryptography.bindings.openssl import api @@ -31,6 +29,5 @@ class TestOpenSSL(object): """ assert api.openssl_version_text().startswith("OpenSSL") - def test_get_iv_invalid_mode(self): - with pytest.raises(NotImplementedError): - api._get_iv(None) + def test_get_null_for_ecb(self): + assert api.get_null_for_ecb() == api._ffi.NULL -- cgit v1.2.3 From dc689293704e9181af452aaef495e4c417160e40 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 10:50:06 -0500 Subject: rename get_null_for_ecb to get_iv_for_ecb per alex's comments --- cryptography/bindings/openssl/api.py | 2 +- cryptography/primitives/block/modes.py | 2 +- tests/bindings/test_openssl.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 02957d74..fd54a8ff 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -86,7 +86,7 @@ class API(object): self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) return ctx - def get_null_for_ecb(self): + def get_iv_for_ecb(self): return self._ffi.NULL def update_encrypt_context(self, ctx, plaintext): diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index 82141437..e4fc886e 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -29,4 +29,4 @@ class ECB(object): name = "ECB" def get_iv_or_nonce(self, api): - return api.get_null_for_ecb() + return api.get_iv_for_ecb() diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index c5927b76..f25236cc 100644 --- a/tests/bindings/test_openssl.py +++ b/tests/bindings/test_openssl.py @@ -29,5 +29,5 @@ class TestOpenSSL(object): """ assert api.openssl_version_text().startswith("OpenSSL") - def test_get_null_for_ecb(self): - assert api.get_null_for_ecb() == api._ffi.NULL + def test_get_iv_for_ecb(self): + assert api.get_iv_for_ecb() == api._ffi.NULL -- cgit v1.2.3 From 5266752c9e462ac988af3d222470a68b2950d2d6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 15:41:37 -0500 Subject: modify modes to use abc so api can determine what attribute to call * Due to a circular dependency issue I had to put the abcs in cryptography.primitives.abc.block.modes * The ABCs look like they do because that is the form that is compatible with 2.x and 3.x --- cryptography/bindings/openssl/api.py | 13 ++++++++++--- cryptography/primitives/abc/__init__.py | 0 cryptography/primitives/abc/block/__init__.py | 0 cryptography/primitives/abc/block/modes.py | 21 +++++++++++++++++++++ cryptography/primitives/block/modes.py | 9 ++++----- tests/bindings/test_openssl.py | 5 +---- 6 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 cryptography/primitives/abc/__init__.py create mode 100644 cryptography/primitives/abc/block/__init__.py create mode 100644 cryptography/primitives/abc/block/modes.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index fd54a8ff..f95e4d62 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -13,6 +13,8 @@ from __future__ import absolute_import, division, print_function +from cryptography.primitives.abc.block import modes + import cffi @@ -72,7 +74,7 @@ class API(object): ) evp_cipher = self._lib.EVP_get_cipherbyname(ciphername.encode("ascii")) assert evp_cipher != self._ffi.NULL - iv_nonce = mode.get_iv_or_nonce(self) + iv_nonce = self._introspect(mode) # TODO: Sometimes this needs to be a DecryptInit, when? res = self._lib.EVP_EncryptInit_ex( @@ -86,8 +88,13 @@ class API(object): self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) return ctx - def get_iv_for_ecb(self): - return self._ffi.NULL + def _introspect(self, mode): + if isinstance(mode, modes.ModeWithInitializationVector): + return mode.initialization_vector + elif isinstance(mode, modes.ModeWithNonce): + return mode.nonce + else: + return self._ffi.NULL def update_encrypt_context(self, ctx, plaintext): buf = self._ffi.new("unsigned char[]", len(plaintext)) diff --git a/cryptography/primitives/abc/__init__.py b/cryptography/primitives/abc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cryptography/primitives/abc/block/__init__.py b/cryptography/primitives/abc/block/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cryptography/primitives/abc/block/modes.py b/cryptography/primitives/abc/block/modes.py new file mode 100644 index 00000000..609a2ae3 --- /dev/null +++ b/cryptography/primitives/abc/block/modes.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 + +import abc + + +ModeWithInitializationVector = abc.ABCMeta('ModeWithInitializationVector', + (object, ), {}) +ModeWithNonce = abc.ABCMeta('ModeWithNonce', (object, ), {}) diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index e4fc886e..1e9b14b7 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -13,6 +13,8 @@ from __future__ import absolute_import, division, print_function +from cryptography.primitives.abc.block import modes + class CBC(object): name = "CBC" @@ -21,12 +23,9 @@ class CBC(object): super(CBC, self).__init__() self.initialization_vector = initialization_vector - def get_iv_or_nonce(self, api): - return self.initialization_vector - class ECB(object): name = "ECB" - def get_iv_or_nonce(self, api): - return api.get_iv_for_ecb() + +modes.ModeWithInitializationVector.register(CBC) diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index f25236cc..b23c4ccc 100644 --- a/tests/bindings/test_openssl.py +++ b/tests/bindings/test_openssl.py @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from cryptography.bindings.openssl import api +from cryptography.bindings.openssl.api import api class TestOpenSSL(object): @@ -28,6 +28,3 @@ class TestOpenSSL(object): for every OpenSSL. """ assert api.openssl_version_text().startswith("OpenSSL") - - def test_get_iv_for_ecb(self): - assert api.get_iv_for_ecb() == api._ffi.NULL -- cgit v1.2.3 From c024255dda87decd65bd05bd767feda0b43f80c7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 18:54:13 -0500 Subject: move abc, inline introspect method, use six for abcs * abc moved to cryptography.primitive.interfaces * six added to dependencies * six used to have py2x/py3x compatible abc * nonce abc removed for now --- cryptography/bindings/openssl/api.py | 18 ++++++------------ cryptography/primitives/abc/__init__.py | 0 cryptography/primitives/abc/block/__init__.py | 0 cryptography/primitives/abc/block/modes.py | 21 --------------------- cryptography/primitives/block/modes.py | 4 ++-- cryptography/primitives/interfaces.py | 21 +++++++++++++++++++++ setup.py | 2 ++ tox.ini | 1 + 8 files changed, 32 insertions(+), 35 deletions(-) delete mode 100644 cryptography/primitives/abc/__init__.py delete mode 100644 cryptography/primitives/abc/block/__init__.py delete mode 100644 cryptography/primitives/abc/block/modes.py create mode 100644 cryptography/primitives/interfaces.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index f95e4d62..917c1846 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -13,7 +13,7 @@ from __future__ import absolute_import, division, print_function -from cryptography.primitives.abc.block import modes +from cryptography.primitives import interfaces import cffi @@ -74,12 +74,14 @@ class API(object): ) evp_cipher = self._lib.EVP_get_cipherbyname(ciphername.encode("ascii")) assert evp_cipher != self._ffi.NULL - iv_nonce = self._introspect(mode) + if isinstance(mode, interfaces.ModeWithInitializationVector): + iv_nonce = mode.initialization_vector + else: + iv_nonce = self._ffi.NULL # TODO: Sometimes this needs to be a DecryptInit, when? res = self._lib.EVP_EncryptInit_ex( - ctx, evp_cipher, self._ffi.NULL, cipher.key, - iv_nonce + ctx, evp_cipher, self._ffi.NULL, cipher.key, iv_nonce ) assert res != 0 @@ -88,14 +90,6 @@ class API(object): self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) return ctx - def _introspect(self, mode): - if isinstance(mode, modes.ModeWithInitializationVector): - return mode.initialization_vector - elif isinstance(mode, modes.ModeWithNonce): - return mode.nonce - else: - return self._ffi.NULL - def update_encrypt_context(self, ctx, plaintext): buf = self._ffi.new("unsigned char[]", len(plaintext)) outlen = self._ffi.new("int *") diff --git a/cryptography/primitives/abc/__init__.py b/cryptography/primitives/abc/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cryptography/primitives/abc/block/__init__.py b/cryptography/primitives/abc/block/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cryptography/primitives/abc/block/modes.py b/cryptography/primitives/abc/block/modes.py deleted file mode 100644 index 609a2ae3..00000000 --- a/cryptography/primitives/abc/block/modes.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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 - - -ModeWithInitializationVector = abc.ABCMeta('ModeWithInitializationVector', - (object, ), {}) -ModeWithNonce = abc.ABCMeta('ModeWithNonce', (object, ), {}) diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py index 1e9b14b7..c722e739 100644 --- a/cryptography/primitives/block/modes.py +++ b/cryptography/primitives/block/modes.py @@ -13,7 +13,7 @@ from __future__ import absolute_import, division, print_function -from cryptography.primitives.abc.block import modes +from cryptography.primitives import interfaces class CBC(object): @@ -28,4 +28,4 @@ class ECB(object): name = "ECB" -modes.ModeWithInitializationVector.register(CBC) +interfaces.ModeWithInitializationVector.register(CBC) diff --git a/cryptography/primitives/interfaces.py b/cryptography/primitives/interfaces.py new file mode 100644 index 00000000..a2b091df --- /dev/null +++ b/cryptography/primitives/interfaces.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 + +import abc +import six + + +class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)): + pass diff --git a/setup.py b/setup.py index 1044c979..cbbf100a 100644 --- a/setup.py +++ b/setup.py @@ -21,9 +21,11 @@ with open("cryptography/__about__.py") as fp: CFFI_DEPENDENCY = "cffi>=0.6" +SIX_DEPENDENCY = "six>=1.4.1" install_requires = [ CFFI_DEPENDENCY, + SIX_DEPENDENCY ] setup_requires = [ diff --git a/tox.ini b/tox.ini index 4d17ebe8..02d521b1 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ envlist = py26,py27,pypy,py32,py33,docs,pep8 deps = pytest-cov pretend + six commands = py.test --cov=cryptography/ --cov=tests/ [testenv:docs] -- cgit v1.2.3 From 7d9e0d9af5343aea7b4b949c20635ed414238927 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Sep 2013 19:10:33 -0500 Subject: address style on import + remove a tox dependency (in setup.py already) --- cryptography/primitives/interfaces.py | 1 + tox.ini | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cryptography/primitives/interfaces.py b/cryptography/primitives/interfaces.py index a2b091df..6f74ccf7 100644 --- a/cryptography/primitives/interfaces.py +++ b/cryptography/primitives/interfaces.py @@ -14,6 +14,7 @@ from __future__ import absolute_import, division, print_function import abc + import six diff --git a/tox.ini b/tox.ini index 02d521b1..4d17ebe8 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,6 @@ envlist = py26,py27,pypy,py32,py33,docs,pep8 deps = pytest-cov pretend - six commands = py.test --cov=cryptography/ --cov=tests/ [testenv:docs] -- cgit v1.2.3