From dff22d4707a50b8164c5c6acd5521bcd91160cd1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 27 Sep 2013 13:43:06 -0500 Subject: Camellia block cipher support * Tests for CBC, OFB, CFB, and ECB * Tests will be automatically skipped if camellia support is not present in your OpenSSL library (e.g. OS X 10.8 with default OpenSSL) * Test for unsupported cipher in create_block_cipher_context * Docs for the cipher --- tests/bindings/test_openssl.py | 18 ++++++ tests/primitives/test_ciphers.py | 17 +++++- tests/primitives/test_cryptrec.py | 64 +++++++++++++++++++ tests/primitives/test_openssl_vectors.py | 102 +++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 tests/primitives/test_cryptrec.py create mode 100644 tests/primitives/test_openssl_vectors.py (limited to 'tests') diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index b23c4ccc..85ecc49c 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.api import api @@ -28,3 +30,19 @@ class TestOpenSSL(object): for every OpenSSL. """ assert api.openssl_version_text().startswith("OpenSSL") + + def test_supports(self): + assert api.supports("not-a-real-cipher") is False + + def test_create_block_cipher_context_with_unsupported_cipher(self): + class FakeCipher(object): + name = "FakeCipher" + key_size = 24 + + class FakeMode(object): + name = "CCC" + + with pytest.raises(AssertionError): + cipher = FakeCipher() + mode = FakeMode() + api.create_block_cipher_context(cipher, mode) diff --git a/tests/primitives/test_ciphers.py b/tests/primitives/test_ciphers.py index 5ee9f223..27d35850 100644 --- a/tests/primitives/test_ciphers.py +++ b/tests/primitives/test_ciphers.py @@ -17,7 +17,7 @@ import binascii import pytest -from cryptography.primitives.block.ciphers import AES +from cryptography.primitives.block.ciphers import AES, Camellia class TestAES(object): @@ -33,3 +33,18 @@ class TestAES(object): def test_invalid_key_size(self): with pytest.raises(ValueError): AES(binascii.unhexlify(b"0" * 12)) + + +class TestCamellia(object): + @pytest.mark.parametrize(("key", "keysize"), [ + (b"0" * 32, 128), + (b"0" * 48, 192), + (b"0" * 64, 256), + ]) + def test_key_size(self, key, keysize): + cipher = Camellia(binascii.unhexlify(key)) + assert cipher.key_size == keysize + + def test_invalid_key_size(self): + with pytest.raises(ValueError): + Camellia(binascii.unhexlify(b"0" * 12)) diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py new file mode 100644 index 00000000..54ae4d0c --- /dev/null +++ b/tests/primitives/test_cryptrec.py @@ -0,0 +1,64 @@ +# 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. + +""" +Test using the CRYPTREC (Camellia) Test Vectors +""" + +from __future__ import absolute_import, division, print_function + +import binascii +import itertools +import os + +import pytest + +from cryptography.bindings.openssl.api import api +from cryptography.primitives.block import BlockCipher, ciphers, modes + +from ..utils import load_cryptrec_vectors_from_file + +CAMELLIA_ECB_SUPPORTED = api.supports('camellia-128-ecb') + + +def parameterize_encrypt_test(cipher, vector_type, params, fnames): + return pytest.mark.parametrize(params, + list(itertools.chain.from_iterable( + load_cryptrec_vectors_from_file( + os.path.join(cipher, vector_type, fname), + ) + for fname in fnames + )) + ) + + +@pytest.mark.skipif("not CAMELLIA_ECB_SUPPORTED") +class TestCamelliaECB(object): + + @parameterize_encrypt_test( + "Camellia", "NTT", + ("key", "plaintext", "ciphertext"), + [ + "camellia-128-ecb.txt", + "camellia-192-ecb.txt", + "camellia-256-ecb.txt", + ] + ) + def test_NTT(self, key, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.Camellia(binascii.unhexlify(key)), + modes.ECB(), + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext).upper() == ciphertext diff --git a/tests/primitives/test_openssl_vectors.py b/tests/primitives/test_openssl_vectors.py new file mode 100644 index 00000000..0ecbcd9d --- /dev/null +++ b/tests/primitives/test_openssl_vectors.py @@ -0,0 +1,102 @@ +# 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. + +""" +Test using the OpenSSL Test Vectors +""" + +from __future__ import absolute_import, division, print_function + +import binascii +import itertools +import os + +import pytest + +from cryptography.bindings.openssl.api import api +from cryptography.primitives.block import BlockCipher, ciphers, modes + +from ..utils import load_openssl_vectors_from_file + +CAMELLIA_CBC_SUPPORTED = api.supports('camellia-128-cbc') +CAMELLIA_OFB_SUPPORTED = api.supports('camellia-128-ofb') +CAMELLIA_CFB_SUPPORTED = api.supports('camellia-128-cfb') + + +def parameterize_encrypt_test(cipher, params, fnames): + return pytest.mark.parametrize(params, + list(itertools.chain.from_iterable( + load_openssl_vectors_from_file(os.path.join(cipher, fname)) + for fname in fnames + )) + ) + + +@pytest.mark.skipif("not CAMELLIA_CBC_SUPPORTED") +class TestCamelliaCBC(object): + + @parameterize_encrypt_test( + "Camellia", + ("key", "iv", "plaintext", "ciphertext"), + [ + "camellia-cbc.txt", + ] + ) + def test_OpenSSL(self, key, iv, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.Camellia(binascii.unhexlify(key)), + modes.CBC(binascii.unhexlify(iv)), + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext).upper() == ciphertext + + +@pytest.mark.skipif("not CAMELLIA_OFB_SUPPORTED") +class TestCamelliaOFB(object): + + @parameterize_encrypt_test( + "Camellia", + ("key", "iv", "plaintext", "ciphertext"), + [ + "camellia-ofb.txt", + ] + ) + def test_OpenSSL(self, key, iv, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.Camellia(binascii.unhexlify(key)), + modes.OFB(binascii.unhexlify(iv)), + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext).upper() == ciphertext + + +@pytest.mark.skipif("not CAMELLIA_CFB_SUPPORTED") +class TestCamelliaCFB(object): + + @parameterize_encrypt_test( + "Camellia", + ("key", "iv", "plaintext", "ciphertext"), + [ + "camellia-cfb.txt", + ] + ) + def test_OpenSSL(self, key, iv, plaintext, ciphertext): + cipher = BlockCipher( + ciphers.Camellia(binascii.unhexlify(key)), + modes.CFB(binascii.unhexlify(iv)), + ) + actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) + actual_ciphertext += cipher.finalize() + assert binascii.hexlify(actual_ciphertext).upper() == ciphertext -- cgit v1.2.3 From f2ce1ae856e43a292ea7a6aae26d75b508f0a363 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 3 Oct 2013 21:54:05 -0500 Subject: rebase and modify to support some changed behaviors * Update code to reflect new api object (ffi and lib are no longer private) * tests updated to take an api object * skipif marks removed for now as we need to use the api passed to each individual test. skip testing done inside the test * changed name of supports in api to supports_cipher (future PRs will contain supports_hash) --- tests/bindings/test_openssl.py | 19 ++----------------- tests/primitives/test_cryptrec.py | 10 ++++------ tests/primitives/test_openssl_vectors.py | 13 ++++++------- 3 files changed, 12 insertions(+), 30 deletions(-) (limited to 'tests') diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py index 85ecc49c..e5b78d18 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.api import api @@ -31,18 +29,5 @@ class TestOpenSSL(object): """ assert api.openssl_version_text().startswith("OpenSSL") - def test_supports(self): - assert api.supports("not-a-real-cipher") is False - - def test_create_block_cipher_context_with_unsupported_cipher(self): - class FakeCipher(object): - name = "FakeCipher" - key_size = 24 - - class FakeMode(object): - name = "CCC" - - with pytest.raises(AssertionError): - cipher = FakeCipher() - mode = FakeMode() - api.create_block_cipher_context(cipher, mode) + def test_supports_cipher(self): + assert api.supports_cipher("not-a-real-cipher") is False diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py index 54ae4d0c..fb2bf19a 100644 --- a/tests/primitives/test_cryptrec.py +++ b/tests/primitives/test_cryptrec.py @@ -23,13 +23,10 @@ import os import pytest -from cryptography.bindings.openssl.api import api from cryptography.primitives.block import BlockCipher, ciphers, modes from ..utils import load_cryptrec_vectors_from_file -CAMELLIA_ECB_SUPPORTED = api.supports('camellia-128-ecb') - def parameterize_encrypt_test(cipher, vector_type, params, fnames): return pytest.mark.parametrize(params, @@ -42,9 +39,7 @@ def parameterize_encrypt_test(cipher, vector_type, params, fnames): ) -@pytest.mark.skipif("not CAMELLIA_ECB_SUPPORTED") class TestCamelliaECB(object): - @parameterize_encrypt_test( "Camellia", "NTT", ("key", "plaintext", "ciphertext"), @@ -54,10 +49,13 @@ class TestCamelliaECB(object): "camellia-256-ecb.txt", ] ) - def test_NTT(self, key, plaintext, ciphertext): + def test_NTT(self, key, plaintext, ciphertext, api): + if not api.supports_cipher('camellia-128-ecb'): + pytest.skip() cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.ECB(), + api ) actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) actual_ciphertext += cipher.finalize() diff --git a/tests/primitives/test_openssl_vectors.py b/tests/primitives/test_openssl_vectors.py index 0ecbcd9d..ccd07194 100644 --- a/tests/primitives/test_openssl_vectors.py +++ b/tests/primitives/test_openssl_vectors.py @@ -28,10 +28,6 @@ from cryptography.primitives.block import BlockCipher, ciphers, modes from ..utils import load_openssl_vectors_from_file -CAMELLIA_CBC_SUPPORTED = api.supports('camellia-128-cbc') -CAMELLIA_OFB_SUPPORTED = api.supports('camellia-128-ofb') -CAMELLIA_CFB_SUPPORTED = api.supports('camellia-128-cfb') - def parameterize_encrypt_test(cipher, params, fnames): return pytest.mark.parametrize(params, @@ -42,7 +38,6 @@ def parameterize_encrypt_test(cipher, params, fnames): ) -@pytest.mark.skipif("not CAMELLIA_CBC_SUPPORTED") class TestCamelliaCBC(object): @parameterize_encrypt_test( @@ -53,6 +48,8 @@ class TestCamelliaCBC(object): ] ) def test_OpenSSL(self, key, iv, plaintext, ciphertext): + if not api.supports_cipher('camellia-128-cbc'): + pytest.skip() cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CBC(binascii.unhexlify(iv)), @@ -62,7 +59,6 @@ class TestCamelliaCBC(object): assert binascii.hexlify(actual_ciphertext).upper() == ciphertext -@pytest.mark.skipif("not CAMELLIA_OFB_SUPPORTED") class TestCamelliaOFB(object): @parameterize_encrypt_test( @@ -73,6 +69,8 @@ class TestCamelliaOFB(object): ] ) def test_OpenSSL(self, key, iv, plaintext, ciphertext): + if not api.supports_cipher('camellia-128-ofb'): + pytest.skip() cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.OFB(binascii.unhexlify(iv)), @@ -82,7 +80,6 @@ class TestCamelliaOFB(object): assert binascii.hexlify(actual_ciphertext).upper() == ciphertext -@pytest.mark.skipif("not CAMELLIA_CFB_SUPPORTED") class TestCamelliaCFB(object): @parameterize_encrypt_test( @@ -93,6 +90,8 @@ class TestCamelliaCFB(object): ] ) def test_OpenSSL(self, key, iv, plaintext, ciphertext): + if not api.supports_cipher('camellia-128-cfb'): + pytest.skip() cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CFB(binascii.unhexlify(iv)), -- cgit v1.2.3 From 84bb1bb2c04c8e05a072587f9e622f6a5e99de56 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 6 Oct 2013 12:24:47 -0500 Subject: remove openssl api dependency in test_openssl_vectors Update some single quotes to double for consistency --- tests/primitives/test_cryptrec.py | 4 ++-- tests/primitives/test_openssl_vectors.py | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'tests') diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py index fb2bf19a..de26ebd2 100644 --- a/tests/primitives/test_cryptrec.py +++ b/tests/primitives/test_cryptrec.py @@ -50,8 +50,8 @@ class TestCamelliaECB(object): ] ) def test_NTT(self, key, plaintext, ciphertext, api): - if not api.supports_cipher('camellia-128-ecb'): - pytest.skip() + if not api.supports_cipher("camellia-128-ecb"): + pytest.skip("Does not support Camellia ECB") cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.ECB(), diff --git a/tests/primitives/test_openssl_vectors.py b/tests/primitives/test_openssl_vectors.py index ccd07194..acb982a5 100644 --- a/tests/primitives/test_openssl_vectors.py +++ b/tests/primitives/test_openssl_vectors.py @@ -23,7 +23,6 @@ import os import pytest -from cryptography.bindings.openssl.api import api from cryptography.primitives.block import BlockCipher, ciphers, modes from ..utils import load_openssl_vectors_from_file @@ -47,9 +46,9 @@ class TestCamelliaCBC(object): "camellia-cbc.txt", ] ) - def test_OpenSSL(self, key, iv, plaintext, ciphertext): - if not api.supports_cipher('camellia-128-cbc'): - pytest.skip() + def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): + if not api.supports_cipher("camellia-128-cbc"): + pytest.skip("Does not support Camellia CBC") cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CBC(binascii.unhexlify(iv)), @@ -68,9 +67,9 @@ class TestCamelliaOFB(object): "camellia-ofb.txt", ] ) - def test_OpenSSL(self, key, iv, plaintext, ciphertext): - if not api.supports_cipher('camellia-128-ofb'): - pytest.skip() + def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): + if not api.supports_cipher("camellia-128-ofb"): + pytest.skip("Does not support Camellia OFB") cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.OFB(binascii.unhexlify(iv)), @@ -89,9 +88,9 @@ class TestCamelliaCFB(object): "camellia-cfb.txt", ] ) - def test_OpenSSL(self, key, iv, plaintext, ciphertext): - if not api.supports_cipher('camellia-128-cfb'): - pytest.skip() + def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): + if not api.supports_cipher("camellia-128-cfb"): + pytest.skip("Does not support Camellia CFB") cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CFB(binascii.unhexlify(iv)), -- cgit v1.2.3 From 20034b110a9e8b4e0b539bd0b8e28aa510ec9afc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 15 Oct 2013 19:10:53 -0500 Subject: add pragma: no cover to handle coverage in the tests for the moment --- tests/primitives/test_cryptrec.py | 2 +- tests/primitives/test_openssl_vectors.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py index de26ebd2..121e62cb 100644 --- a/tests/primitives/test_cryptrec.py +++ b/tests/primitives/test_cryptrec.py @@ -50,7 +50,7 @@ class TestCamelliaECB(object): ] ) def test_NTT(self, key, plaintext, ciphertext, api): - if not api.supports_cipher("camellia-128-ecb"): + if not api.supports_cipher("camellia-128-ecb"): # pragma: no cover pytest.skip("Does not support Camellia ECB") cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), diff --git a/tests/primitives/test_openssl_vectors.py b/tests/primitives/test_openssl_vectors.py index acb982a5..d30efa5c 100644 --- a/tests/primitives/test_openssl_vectors.py +++ b/tests/primitives/test_openssl_vectors.py @@ -48,7 +48,7 @@ class TestCamelliaCBC(object): ) def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): if not api.supports_cipher("camellia-128-cbc"): - pytest.skip("Does not support Camellia CBC") + pytest.skip("Does not support Camellia CBC") # pragma: no cover cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CBC(binascii.unhexlify(iv)), @@ -69,7 +69,7 @@ class TestCamelliaOFB(object): ) def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): if not api.supports_cipher("camellia-128-ofb"): - pytest.skip("Does not support Camellia OFB") + pytest.skip("Does not support Camellia OFB") # pragma: no cover cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.OFB(binascii.unhexlify(iv)), @@ -90,7 +90,7 @@ class TestCamelliaCFB(object): ) def test_OpenSSL(self, key, iv, plaintext, ciphertext, api): if not api.supports_cipher("camellia-128-cfb"): - pytest.skip("Does not support Camellia CFB") + pytest.skip("Does not support Camellia CFB") # pragma: no cover cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.CFB(binascii.unhexlify(iv)), -- cgit v1.2.3 From f54277876b76c867af3ad121bae7581b765fcb7c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 15 Oct 2013 20:02:10 -0500 Subject: use the pragmas consistently. --- tests/primitives/test_cryptrec.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/primitives/test_cryptrec.py b/tests/primitives/test_cryptrec.py index 121e62cb..c30bda48 100644 --- a/tests/primitives/test_cryptrec.py +++ b/tests/primitives/test_cryptrec.py @@ -50,8 +50,8 @@ class TestCamelliaECB(object): ] ) def test_NTT(self, key, plaintext, ciphertext, api): - if not api.supports_cipher("camellia-128-ecb"): # pragma: no cover - pytest.skip("Does not support Camellia ECB") + if not api.supports_cipher("camellia-128-ecb"): + pytest.skip("Does not support Camellia ECB") # pragma: no cover cipher = BlockCipher( ciphers.Camellia(binascii.unhexlify(key)), modes.ECB(), -- cgit v1.2.3