From 4da28c35d93e14a5e6b0a252751e7cfbaf0fe372 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 7 Nov 2013 07:50:17 +0800 Subject: ARC4 support --- cryptography/hazmat/bindings/openssl/backend.py | 7 +++- .../hazmat/primitives/ciphers/algorithms.py | 19 ++++++++++ docs/hazmat/primitives/symmetric-encryption.rst | 10 +++++ tests/hazmat/primitives/test_arc4.py | 43 ++++++++++++++++++++++ tests/hazmat/primitives/test_utils.py | 13 ++++++- tests/hazmat/primitives/utils.py | 39 ++++++++++++++++++++ 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 tests/hazmat/primitives/test_arc4.py diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 0c3d22d5..1cb886dc 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -21,7 +21,7 @@ import cffi from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers.algorithms import ( - AES, Blowfish, Camellia, CAST5, TripleDES, + AES, Blowfish, Camellia, CAST5, TripleDES, ARC4, ) from cryptography.hazmat.primitives.ciphers.modes import ( CBC, CTR, ECB, OFB, CFB @@ -254,6 +254,11 @@ class Ciphers(object): ECB, GetCipherByName("cast5-ecb") ) + self.register_cipher_adapter( + ARC4, + type(None), + GetCipherByName("rc4") + ) def create_encrypt_ctx(self, cipher, mode): return _CipherContext(self._backend, cipher, mode, diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index 8046bd26..cbfaceb8 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -116,3 +116,22 @@ class CAST5(object): @property def key_size(self): return len(self.key) * 8 + + +class ARC4(object): + name = "RC4" + key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256]) + + def __init__(self, key): + super(ARC4, self).__init__() + self.key = key + + # Verify that the key size matches the expected key size + if self.key_size not in self.key_sizes: + raise ValueError("Invalid key size ({0}) for {1}".format( + self.key_size, self.name + )) + + @property + def key_size(self): + return len(self.key) * 8 diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 7d3b072d..4d0703bb 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -149,6 +149,16 @@ Weak Ciphers :param bytes key: The secret key, 32-448 bits in length (in increments of 8). This must be kept secret. +.. class:: ARC4(key) + + ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its + initial stream output. Its use is strongly discouraged. ARC4 does not use + mode constructions. + + :param bytes key: The secret key, ``40``, ``56``, ``64``, ``80``, ``128``, + ``192``, or ``256`` bits in length. This must be kept + secret. + Modes ~~~~~ diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py new file mode 100644 index 00000000..cf0c5eb4 --- /dev/null +++ b/tests/hazmat/primitives/test_arc4.py @@ -0,0 +1,43 @@ +# 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 binascii +import os + +from cryptography.hazmat.primitives.ciphers import algorithms + +from .utils import generate_stream_encryption_test +from ...utils import load_nist_vectors_from_file + + +class TestARC4(object): + test_thing = generate_stream_encryption_test( + lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("ciphers", "ARC4"), + [ + "rfc-6229-40.txt", + "rfc-6229-56.txt", + "rfc-6229-64.txt", + "rfc-6229-80.txt", + "rfc-6229-128.txt", + "rfc-6229-192.txt", + "rfc-6229-256.txt", + ], + lambda key: algorithms.ARC4(binascii.unhexlify((key))), + only_if=lambda backend: backend.ciphers.supported( + algorithms.ARC4("\x00" * 16), None + ), + skip_message="Does not support ARC4", + ) diff --git a/tests/hazmat/primitives/test_utils.py b/tests/hazmat/primitives/test_utils.py index d7247e67..cee0b20e 100644 --- a/tests/hazmat/primitives/test_utils.py +++ b/tests/hazmat/primitives/test_utils.py @@ -2,7 +2,7 @@ import pytest from .utils import ( base_hash_test, encrypt_test, hash_test, long_string_hash_test, - base_hmac_test, hmac_test + base_hmac_test, hmac_test, stream_encryption_test ) @@ -70,3 +70,14 @@ class TestBaseHMACTest(object): skip_message="message!" ) assert exc_info.value.args[0] == "message!" + + +class TestStreamEncryptionTest(object): + def test_skips_if_only_if_returns_false(self): + with pytest.raises(pytest.skip.Exception) as exc_info: + stream_encryption_test( + None, None, None, + only_if=lambda backend: False, + skip_message="message!" + ) + assert exc_info.value.args[0] == "message!" diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index e6e97d1d..90c15b13 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -49,6 +49,45 @@ def encrypt_test(backend, cipher_factory, mode_factory, params, only_if, assert actual_plaintext == binascii.unhexlify(plaintext) +def generate_stream_encryption_test(param_loader, path, file_names, + cipher_factory, only_if=None, + skip_message=None): + def test_stream_encryption(self): + for backend in _ALL_BACKENDS: + for file_name in file_names: + for params in param_loader(os.path.join(path, file_name)): + yield ( + stream_encryption_test, + backend, + cipher_factory, + params, + only_if, + skip_message + ) + return test_stream_encryption + + +def stream_encryption_test(backend, cipher_factory, params, only_if, + skip_message): + if not only_if(backend): + pytest.skip(skip_message) + plaintext = params.pop("plaintext") + ciphertext = params.pop("ciphertext") + offset = params.pop("offset") + cipher = Cipher(cipher_factory(**params), None, backend) + encryptor = cipher.encryptor() + # throw away offset bytes + encryptor.update(b"\x00" * int(offset)) + actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext)) + actual_ciphertext += encryptor.finalize() + assert actual_ciphertext == binascii.unhexlify(ciphertext) + decryptor = cipher.decryptor() + decryptor.update(b"\x00" * int(offset)) + actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext)) + actual_plaintext += decryptor.finalize() + assert actual_plaintext == binascii.unhexlify(plaintext) + + def generate_hash_test(param_loader, path, file_names, hash_cls, only_if=None, skip_message=None): def test_hash(self): -- cgit v1.2.3 From a5f04c053ca819d6d8be485d2b62a6bed8bdf195 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 7 Nov 2013 08:02:13 +0800 Subject: add ARC4 keysize testing --- tests/hazmat/primitives/test_ciphers.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index dfafab3f..653f7ce6 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -18,7 +18,7 @@ import binascii import pytest from cryptography.hazmat.primitives.ciphers.algorithms import ( - AES, Camellia, TripleDES, Blowfish, CAST5 + AES, Camellia, TripleDES, Blowfish, CAST5, ARC4 ) @@ -91,3 +91,22 @@ class TestCAST5(object): def test_invalid_key_size(self): with pytest.raises(ValueError): CAST5(binascii.unhexlify(b"0" * 34)) + + +class TestARC4(object): + @pytest.mark.parametrize(("key", "keysize"), [ + (b"0" * 10, 40), + (b"0" * 14, 56), + (b"0" * 16, 64), + (b"0" * 20, 80), + (b"0" * 32, 128), + (b"0" * 48, 192), + (b"0" * 64, 256), + ]) + def test_key_size(self, key, keysize): + cipher = ARC4(binascii.unhexlify(key)) + assert cipher.key_size == keysize + + def test_invalid_key_size(self): + with pytest.raises(ValueError): + ARC4(binascii.unhexlify(b"0" * 34)) -- cgit v1.2.3 From c0542e2accbda302e5bb12a09fa6049bee50feef Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 10:15:00 -0800 Subject: Include all the requirements in the dev-requirements, even those which will be installed by `pip install .` --- AUTHORS.rst | 1 - dev-requirements.txt | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index b3b7f35d..0ef9958d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,4 +10,3 @@ PGP key fingerprints are enclosed in parentheses. * Christian Heimes * Paul Kehrer * Jarret Raim - diff --git a/dev-requirements.txt b/dev-requirements.txt index 752517dd..73b876f2 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,3 +4,5 @@ pytest coverage sphinx tox +cffi +six -- cgit v1.2.3 From ab5f0116a2fc906b854b0593675492ec5e406a3d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 10:34:00 -0800 Subject: Be more and more explicit about how to do things correctly --- docs/hazmat/primitives/cryptographic-hashes.rst | 7 ++++--- docs/hazmat/primitives/symmetric-encryption.rst | 23 +++++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 76ca20c0..20fa23cf 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -12,9 +12,9 @@ Message Digests results (with a high probability) in different digests. This is an implementation of - :class:`cryptography.hazmat.primitives.interfaces.HashContext` meant to + :class:`~cryptography.hazmat.primitives.interfaces.HashContext` meant to be used with - :class:`cryptography.hazmat.primitives.interfaces.HashAlgorithm` + :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` implementations to provide an incremental interface to calculating various message digests. @@ -102,7 +102,8 @@ MD5 .. warning:: MD5 is a deprecated hash algorithm that has practical known collision - attacks. You are strongly discouraged from using it. + attacks. You are strongly discouraged from using it. Existing applications + should strongly consider moving away. .. class:: MD5() diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 5f1a64a1..5542e832 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -14,13 +14,22 @@ Symmetric Encryption Symmetric encryption is a way to encrypt (hide the plaintext value) material -where the encrypter and decrypter both use the same key. +where the encrypter and decrypter both use the same key. Note that symmetric +encryption is **not** sufficient for most applications, because it only +provides secrecy (an attacker can't see the message) but not authenticity (an +attacker can create bogus messages and force the application to decrypt them). +For this reason it is *strongly* reccomended to combine encryption with a +message authentication code, such as :doc:`HMAC `, in +an "encrypt-then-MAC" formulation as `described by Colin Percival`_. .. class:: Cipher(algorithm, mode) - Cipher objects combine an algorithm (such as AES) with a mode (such as - CBC, CTR, or GCM). A simple example of encrypting (and then decrypting) - content with AES is: + Cipher objects combine an algorithm (such as + :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`) with a + mode (such as + :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` or + :class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`). A simple + example of encrypting (and then decrypting) content with AES is: .. doctest:: @@ -143,8 +152,7 @@ Weak Ciphers Blowfish is a block cipher developed by Bruce Schneier. It is known to be susceptible to attacks when using weak keys. The author has recommended - that users of Blowfish move to newer algorithms like - :class:`AES`. + that users of Blowfish move to newer algorithms, such as :class:`AES`. :param bytes key: The secret key, 32-448 bits in length (in increments of 8). This must be kept secret. @@ -252,3 +260,6 @@ Insecure Modes ciphers. Each block of data is encrypted in the same way. This means identical plaintext blocks will always result in identical ciphertext blocks, and thus result in information leakage + + +.. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html -- cgit v1.2.3 From 27283cfa4300162f6a7a667364acab781c49710f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 10:49:22 -0800 Subject: Try to use the sphinx rtd theme locally if it's installed --- docs/conf.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 69be32e9..77050e72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,6 +14,12 @@ import os import sys +try: + import sphinx_rtd_theme +except ImportError: + sphinx_rtd_theme = None + + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -98,16 +104,18 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' + +if sphinx_rtd_theme: + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +else: + html_theme = "default" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None -- cgit v1.2.3 From e29acd11b4d226dee1ee88bdd34ca72d4500b065 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 11:08:32 -0800 Subject: Put the theme in dev-requirements --- dev-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-requirements.txt b/dev-requirements.txt index 752517dd..8e9a4ab0 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,3 +4,4 @@ pytest coverage sphinx tox +sphinx_rtd_theme -- cgit v1.2.3 From 2ff5352312b0355837d5059927d4abc36c10d6c6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 11:24:48 -0800 Subject: Do this another way --- dev-requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 73b876f2..66f46d83 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,5 +4,4 @@ pytest coverage sphinx tox -cffi -six +-e . -- cgit v1.2.3 From 13ec4799e47b5180d397e2f5028005c58e8e93be Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 8 Nov 2013 14:09:21 -0800 Subject: Include in tox.ini --- tox.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index dab22a6d..257275ce 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,9 @@ commands = coverage report -m [testenv:docs] -deps = sphinx +deps = + sphinx + sphinx_rtd_theme basepython = python2.7 commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs docs/_build/html -- cgit v1.2.3 From 715e85f3f39a2b8f50ae810ba86d64af30e13c56 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 9 Nov 2013 06:45:00 -0800 Subject: Fixed two bugs in the PKCS7 padding where unpadding would accept bad inputs. --- cryptography/hazmat/primitives/padding.py | 4 ++-- tests/hazmat/primitives/test_padding.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py index ddcadd89..eac18c2a 100644 --- a/cryptography/hazmat/primitives/padding.py +++ b/cryptography/hazmat/primitives/padding.py @@ -101,12 +101,12 @@ class _PKCS7UnpaddingContext(object): if self._buffer is None: raise ValueError("Context was already finalized") - if not self._buffer: + if len(self._buffer) != self.block_size // 8: raise ValueError("Invalid padding bytes") pad_size = six.indexbytes(self._buffer, -1) - if pad_size > self.block_size // 8: + if not (0 < pad_size <= self.block_size // 8): raise ValueError("Invalid padding bytes") mismatch = 0 diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index 3cefafaf..6a2b6243 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -29,6 +29,8 @@ class TestPKCS7(object): (128, b"1111111111111111"), (128, b"111111111111111\x06"), (128, b""), + (128, b"\x06" * 6), + (128, b"\x00" * 16), ]) def test_invalid_padding(self, size, padded): unpadder = padding.PKCS7(size).unpadder() -- cgit v1.2.3 From 0994c5628a3d960a45f8aac33f0d5d985eb48cf7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 10 Nov 2013 03:19:14 +0800 Subject: update docs to include arc4 example --- docs/hazmat/primitives/symmetric-encryption.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 9d18ce50..77e61b56 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -159,6 +159,17 @@ Weak Ciphers ``192``, or ``256`` bits in length. This must be kept secret. + .. doctest:: + + >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + >>> algorithm = algorithms.ARC4(key) + >>> cipher = Cipher(algorithm, mode=None) + >>> encryptor = cipher.encryptor() + >>> ct = encryptor.update(b"a secret message") + >>> decryptor = cipher.decryptor() + >>> decryptor.update(ct) + 'a secret message' + .. _symmetric-encryption-modes: -- cgit v1.2.3 From 8fa88eb72e67b15b6d6b7de3c4bc5c5bb7a2fbfa Mon Sep 17 00:00:00 2001 From: cyli Date: Mon, 11 Nov 2013 14:25:53 -0800 Subject: Add all the variable declarations (and customizations necessary to make them work) for ssl.py --- cryptography/hazmat/bindings/openssl/ssl.py | 123 ++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py index 58a64f0b..0f8a7a91 100644 --- a/cryptography/hazmat/bindings/openssl/ssl.py +++ b/cryptography/hazmat/bindings/openssl/ssl.py @@ -16,6 +16,110 @@ INCLUDES = """ """ TYPES = """ +/* Internally invented symbol to tell us if SSLv2 is supported */ +static const int PYOPENSSL_NO_SSL2; + +/* Internally invented symbol to tell us if SNI is supported */ +static const int PYOPENSSL_TLSEXT_HOSTNAME; + +static const int SSL_FILETYPE_PEM; +static const int SSL_FILETYPE_ASN1; +static const int SSL_ERROR_NONE; +static const int SSL_ERROR_ZERO_RETURN; +static const int SSL_ERROR_WANT_READ; +static const int SSL_ERROR_WANT_WRITE; +static const int SSL_ERROR_WANT_X509_LOOKUP; +static const int SSL_ERROR_SYSCALL; +static const int SSL_ERROR_SSL; +static const int SSL_SENT_SHUTDOWN; +static const int SSL_RECEIVED_SHUTDOWN; +static const int SSL_OP_NO_SSLv2; +static const int SSL_OP_NO_SSLv3; +static const int SSL_OP_NO_TLSv1; +static const int SSL_OP_SINGLE_DH_USE; +static const int SSL_OP_EPHEMERAL_RSA; +static const int SSL_OP_MICROSOFT_SESS_ID_BUG; +static const int SSL_OP_NETSCAPE_CHALLENGE_BUG; +static const int SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; +static const int SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; +static const int SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; +static const int SSL_OP_MSIE_SSLV2_RSA_PADDING; +static const int SSL_OP_SSLEAY_080_CLIENT_DH_BUG; +static const int SSL_OP_TLS_D5_BUG; +static const int SSL_OP_TLS_BLOCK_PADDING_BUG; +static const int SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +static const int SSL_OP_CIPHER_SERVER_PREFERENCE; +static const int SSL_OP_TLS_ROLLBACK_BUG; +static const int SSL_OP_PKCS1_CHECK_1; +static const int SSL_OP_PKCS1_CHECK_2; +static const int SSL_OP_NETSCAPE_CA_DN_BUG; +static const int SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG; +static const int SSL_OP_NO_COMPRESSION; +static const int SSL_OP_NO_QUERY_MTU; +static const int SSL_OP_COOKIE_EXCHANGE; +static const int SSL_OP_NO_TICKET; +static const int SSL_OP_ALL; +static const int SSL_VERIFY_PEER; +static const int SSL_VERIFY_FAIL_IF_NO_PEER_CERT; +static const int SSL_VERIFY_CLIENT_ONCE; +static const int SSL_VERIFY_NONE; +static const int SSL_SESS_CACHE_OFF; +static const int SSL_SESS_CACHE_CLIENT; +static const int SSL_SESS_CACHE_SERVER; +static const int SSL_SESS_CACHE_BOTH; +static const int SSL_SESS_CACHE_NO_AUTO_CLEAR; +static const int SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; +static const int SSL_SESS_CACHE_NO_INTERNAL_STORE; +static const int SSL_SESS_CACHE_NO_INTERNAL; +static const int SSL_ST_CONNECT; +static const int SSL_ST_ACCEPT; +static const int SSL_ST_MASK; +static const int SSL_ST_INIT; +static const int SSL_ST_BEFORE; +static const int SSL_ST_OK; +static const int SSL_ST_RENEGOTIATE; +static const int SSL_CB_LOOP; +static const int SSL_CB_EXIT; +static const int SSL_CB_READ; +static const int SSL_CB_WRITE; +static const int SSL_CB_ALERT; +static const int SSL_CB_READ_ALERT; +static const int SSL_CB_WRITE_ALERT; +static const int SSL_CB_ACCEPT_LOOP; +static const int SSL_CB_ACCEPT_EXIT; +static const int SSL_CB_CONNECT_LOOP; +static const int SSL_CB_CONNECT_EXIT; +static const int SSL_CB_HANDSHAKE_START; +static const int SSL_CB_HANDSHAKE_DONE; +static const int SSL_MODE_RELEASE_BUFFERS; +static const int SSL_MODE_ENABLE_PARTIAL_WRITE; +static const int SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; +static const int SSL_MODE_AUTO_RETRY; +static const int SSL3_RANDOM_SIZE; +typedef ... X509_STORE_CTX; +static const int X509_V_OK; +typedef ... SSL_METHOD; +typedef ... SSL_CTX; + +typedef struct { + int master_key_length; + unsigned char master_key[...]; + ...; +} SSL_SESSION; + +typedef struct { + unsigned char server_random[...]; + unsigned char client_random[...]; + ...; +} SSL3_STATE; + +typedef struct { + SSL3_STATE *s3; + SSL_SESSION *session; + ...; +} SSL; + +static const int TLSEXT_NAMETYPE_host_name; """ FUNCTIONS = """ @@ -26,4 +130,23 @@ MACROS = """ """ CUSTOMIZATIONS = """ +#ifdef OPENSSL_NO_SSL2 +static const int PYOPENSSL_NO_SSL2 = 1; +SSL_METHOD* (*SSLv2_method)() = NULL; +SSL_METHOD* (*SSLv2_client_method)() = NULL; +SSL_METHOD* (*SSLv2_server_method)() = NULL; +#else +static const int PYOPENSSL_NO_SSL2 = 0; +#endif + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +static const int PYOPENSSL_TLSEXT_HOSTNAME = 1; +#else +static const int PYOPENSSL_TLSEXT_HOSTNAME = 0; +void (*SSL_set_tlsext_host_name)(SSL *, char *) = NULL; +const char* (*SSL_get_servername)(const SSL *, const int) = NULL; +void (*SSL_CTX_set_tlsext_servername_callback)( + SSL_CTX *, + int (*cb)(const SSL *, int *, void *)) = NULL; +#endif """ -- cgit v1.2.3 From 521c42d26ca164050745a9d33c0e3b7785341bf5 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 11 Nov 2013 14:25:59 -0800 Subject: Simplify the code by doing the filtering earlier, rather than later --- tests/utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/utils.py b/tests/utils.py index 99ba2e2f..cc56a9ac 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -15,7 +15,9 @@ import os.path def load_nist_vectors(vector_data, op): - section, count, data = None, None, {} + section = None + count = None + data = {} for line in vector_data: line = line.strip() @@ -31,7 +33,9 @@ def load_nist_vectors(vector_data, op): # Look for section headers if line.startswith("[") and line.endswith("]"): section = line[1:-1] - data[section] = {} + continue + + if section != op: continue # Build our data using a simple Key = Value format @@ -40,15 +44,15 @@ def load_nist_vectors(vector_data, op): # COUNT is a special token that indicates a new block of data if name.upper() == "COUNT": count = value - data[section][count] = {} + data[count] = {} # For all other tokens we simply want the name, value stored in # the dictionary else: - data[section][count][name.lower()] = value.encode("ascii") + data[count][name.lower()] = value.encode("ascii") # We want to test only for a particular operation, we sort them for the # benefit of the tests of this function. - return [v for k, v in sorted(data[op].items(), key=lambda kv: kv[0])] + return [v for k, v in sorted(data.items(), key=lambda kv: kv[0])] def load_nist_vectors_from_file(filename, op): -- cgit v1.2.3 From a9c9092a50e0c862207865dc9915c3ecccb852e2 Mon Sep 17 00:00:00 2001 From: cyli Date: Mon, 11 Nov 2013 14:26:16 -0800 Subject: Remove the two declarations that are not in 0.9.8 --- cryptography/hazmat/bindings/openssl/ssl.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py index 0f8a7a91..f95a8342 100644 --- a/cryptography/hazmat/bindings/openssl/ssl.py +++ b/cryptography/hazmat/bindings/openssl/ssl.py @@ -54,7 +54,6 @@ static const int SSL_OP_PKCS1_CHECK_1; static const int SSL_OP_PKCS1_CHECK_2; static const int SSL_OP_NETSCAPE_CA_DN_BUG; static const int SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG; -static const int SSL_OP_NO_COMPRESSION; static const int SSL_OP_NO_QUERY_MTU; static const int SSL_OP_COOKIE_EXCHANGE; static const int SSL_OP_NO_TICKET; @@ -91,7 +90,6 @@ static const int SSL_CB_CONNECT_LOOP; static const int SSL_CB_CONNECT_EXIT; static const int SSL_CB_HANDSHAKE_START; static const int SSL_CB_HANDSHAKE_DONE; -static const int SSL_MODE_RELEASE_BUFFERS; static const int SSL_MODE_ENABLE_PARTIAL_WRITE; static const int SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; static const int SSL_MODE_AUTO_RETRY; -- cgit v1.2.3 From 0165629344d8eddfac95c10fc6e103e4b21f2e07 Mon Sep 17 00:00:00 2001 From: cyli Date: Mon, 11 Nov 2013 14:34:14 -0800 Subject: Handle customizations in another PR as per @alex --- cryptography/hazmat/bindings/openssl/ssl.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py index f95a8342..0a6a6fdc 100644 --- a/cryptography/hazmat/bindings/openssl/ssl.py +++ b/cryptography/hazmat/bindings/openssl/ssl.py @@ -16,12 +16,6 @@ INCLUDES = """ """ TYPES = """ -/* Internally invented symbol to tell us if SSLv2 is supported */ -static const int PYOPENSSL_NO_SSL2; - -/* Internally invented symbol to tell us if SNI is supported */ -static const int PYOPENSSL_TLSEXT_HOSTNAME; - static const int SSL_FILETYPE_PEM; static const int SSL_FILETYPE_ASN1; static const int SSL_ERROR_NONE; @@ -128,23 +122,4 @@ MACROS = """ """ CUSTOMIZATIONS = """ -#ifdef OPENSSL_NO_SSL2 -static const int PYOPENSSL_NO_SSL2 = 1; -SSL_METHOD* (*SSLv2_method)() = NULL; -SSL_METHOD* (*SSLv2_client_method)() = NULL; -SSL_METHOD* (*SSLv2_server_method)() = NULL; -#else -static const int PYOPENSSL_NO_SSL2 = 0; -#endif - -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -static const int PYOPENSSL_TLSEXT_HOSTNAME = 1; -#else -static const int PYOPENSSL_TLSEXT_HOSTNAME = 0; -void (*SSL_set_tlsext_host_name)(SSL *, char *) = NULL; -const char* (*SSL_get_servername)(const SSL *, const int) = NULL; -void (*SSL_CTX_set_tlsext_servername_callback)( - SSL_CTX *, - int (*cb)(const SSL *, int *, void *)) = NULL; -#endif """ -- cgit v1.2.3 From d3ce70317016791079212d7256c3b7f195b4a375 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 11 Nov 2013 14:46:20 -0800 Subject: Ignore the sections of the NIST files --- tests/hazmat/primitives/test_3des.py | 12 ++-- tests/hazmat/primitives/test_aes.py | 8 +-- tests/hazmat/primitives/test_arc4.py | 4 +- tests/hazmat/primitives/test_blowfish.py | 8 +-- tests/hazmat/primitives/test_cast5.py | 6 +- tests/test_utils.py | 116 +++++++++++++++++++++++++++++-- tests/utils.py | 13 ++-- 7 files changed, 134 insertions(+), 33 deletions(-) diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py index af6bdc04..1543cfd7 100644 --- a/tests/hazmat/primitives/test_3des.py +++ b/tests/hazmat/primitives/test_3des.py @@ -28,7 +28,7 @@ from ...utils import load_nist_vectors_from_file class TestTripleDES_CBC(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "CBC"), [ "TCBCinvperm.rsp", @@ -42,7 +42,7 @@ class TestTripleDES_CBC(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "CBC"), [ "TCBCMMT1.rsp", @@ -58,7 +58,7 @@ class TestTripleDES_CBC(object): class TestTripleDES_OFB(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "OFB"), [ "TOFBpermop.rsp", @@ -72,7 +72,7 @@ class TestTripleDES_OFB(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "OFB"), [ "TOFBMMT1.rsp", @@ -88,7 +88,7 @@ class TestTripleDES_OFB(object): class TestTripleDES_CFB(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "CFB"), [ "TCFB64invperm.rsp", @@ -102,7 +102,7 @@ class TestTripleDES_CFB(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "3DES", "CFB"), [ "TCFB64MMT1.rsp", diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 66471fac..c4818409 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -26,7 +26,7 @@ from ...utils import ( class TestAES(object): test_CBC = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "AES", "CBC"), [ "CBCGFSbox128.rsp", @@ -50,7 +50,7 @@ class TestAES(object): ) test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "AES", "ECB"), [ "ECBGFSbox128.rsp", @@ -74,7 +74,7 @@ class TestAES(object): ) test_OFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "AES", "OFB"), [ "OFBGFSbox128.rsp", @@ -98,7 +98,7 @@ class TestAES(object): ) test_CFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "AES", "CFB"), [ "CFB128GFSbox128.rsp", diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index cf0c5eb4..71b5d63a 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -23,8 +23,8 @@ from ...utils import load_nist_vectors_from_file class TestARC4(object): - test_thing = generate_stream_encryption_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + test_rfc = generate_stream_encryption_test( + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "ARC4"), [ "rfc-6229-40.txt", diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index a7f13823..6f670ad7 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -24,7 +24,7 @@ from ...utils import load_nist_vectors_from_file class TestBlowfish(object): test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "Blowfish"), ["bf-ecb.txt"], lambda key: algorithms.Blowfish(binascii.unhexlify(key)), @@ -36,7 +36,7 @@ class TestBlowfish(object): ) test_CBC = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "Blowfish"), ["bf-cbc.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), @@ -48,7 +48,7 @@ class TestBlowfish(object): ) test_OFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "Blowfish"), ["bf-ofb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), @@ -60,7 +60,7 @@ class TestBlowfish(object): ) test_CFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "Blowfish"), ["bf-cfb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index b2988437..4256e2c4 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -24,11 +24,9 @@ from ...utils import load_nist_vectors_from_file class TestCAST5(object): test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + lambda path: load_nist_vectors_from_file(path), os.path.join("ciphers", "CAST5"), - [ - "cast5-ecb.txt", - ], + ["cast5-ecb.txt"], lambda key: algorithms.CAST5(binascii.unhexlify((key))), lambda key: modes.ECB(), only_if=lambda backend: backend.ciphers.supported( diff --git a/tests/test_utils.py b/tests/test_utils.py index 0692c8d1..457cd869 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -62,7 +62,19 @@ def test_load_nist_vectors_encrypt(): PLAINTEXT = 9798c4640bad75c7c3227db910174e72 """).splitlines() - assert load_nist_vectors(vector_data, "ENCRYPT") == [ + assert load_nist_vectors(vector_data) == [ + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", + "ciphertext": b"0336763e966d92595a567cc9ce537f5e", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"9798c4640bad75c7c3227db910174e72", + "ciphertext": b"a9a1631bf4996954ebc093957b234589", + }, { "key": b"00000000000000000000000000000000", "iv": b"00000000000000000000000000000000", @@ -116,7 +128,19 @@ def test_load_nist_vectors_decrypt(): PLAINTEXT = 9798c4640bad75c7c3227db910174e72 """).splitlines() - assert load_nist_vectors(vector_data, "DECRYPT") == [ + assert load_nist_vectors(vector_data) == [ + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", + "ciphertext": b"0336763e966d92595a567cc9ce537f5e", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"9798c4640bad75c7c3227db910174e72", + "ciphertext": b"a9a1631bf4996954ebc093957b234589", + }, { "key": b"00000000000000000000000000000000", "iv": b"00000000000000000000000000000000", @@ -134,8 +158,7 @@ def test_load_nist_vectors_decrypt(): def test_load_nist_vectors_from_file_encrypt(): assert load_nist_vectors_from_file( - os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp"), - "ENCRYPT" + os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp") ) == [ { "key": b"00000000000000000000000000000000", @@ -179,13 +202,54 @@ def test_load_nist_vectors_from_file_encrypt(): "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", + "ciphertext": b"0336763e966d92595a567cc9ce537f5e", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"9798c4640bad75c7c3227db910174e72", + "ciphertext": b"a9a1631bf4996954ebc093957b234589", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", + "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"6a118a874519e64e9963798a503f1d35", + "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", + "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"b26aeb1874e47ca8358ff22378f09144", + "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", + "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", + }, ] def test_load_nist_vectors_from_file_decrypt(): assert load_nist_vectors_from_file( os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp"), - "DECRYPT", ) == [ { "key": b"00000000000000000000000000000000", @@ -229,6 +293,48 @@ def test_load_nist_vectors_from_file_decrypt(): "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", + "ciphertext": b"0336763e966d92595a567cc9ce537f5e", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"9798c4640bad75c7c3227db910174e72", + "ciphertext": b"a9a1631bf4996954ebc093957b234589", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", + "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"6a118a874519e64e9963798a503f1d35", + "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", + "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"b26aeb1874e47ca8358ff22378f09144", + "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", + }, + { + "key": b"00000000000000000000000000000000", + "iv": b"00000000000000000000000000000000", + "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", + "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", + }, ] diff --git a/tests/utils.py b/tests/utils.py index cc56a9ac..0b215543 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -14,7 +14,7 @@ import os.path -def load_nist_vectors(vector_data, op): +def load_nist_vectors(vector_data): section = None count = None data = {} @@ -35,32 +35,29 @@ def load_nist_vectors(vector_data, op): section = line[1:-1] continue - if section != op: - continue - # Build our data using a simple Key = Value format name, value = line.split(" = ") # COUNT is a special token that indicates a new block of data if name.upper() == "COUNT": count = value - data[count] = {} + data[section, count] = {} # For all other tokens we simply want the name, value stored in # the dictionary else: - data[count][name.lower()] = value.encode("ascii") + data[section, count][name.lower()] = value.encode("ascii") # We want to test only for a particular operation, we sort them for the # benefit of the tests of this function. return [v for k, v in sorted(data.items(), key=lambda kv: kv[0])] -def load_nist_vectors_from_file(filename, op): +def load_nist_vectors_from_file(filename): base = os.path.join( os.path.dirname(__file__), "hazmat", "primitives", "vectors", ) with open(os.path.join(base, filename), "r") as vector_file: - return load_nist_vectors(vector_file, op) + return load_nist_vectors(vector_file) def load_cryptrec_vectors_from_file(filename): -- cgit v1.2.3 From cf5fb332af542a6a38da8b8f481a358f32e5e154 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 11 Nov 2013 15:39:52 -0800 Subject: Removed some tests that are now duplicates --- tests/test_utils.py | 161 +--------------------------------------------------- 1 file changed, 2 insertions(+), 159 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 457cd869..435690b7 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -24,7 +24,7 @@ from .utils import ( ) -def test_load_nist_vectors_encrypt(): +def test_load_nist_vectors(): vector_data = textwrap.dedent(""" # CAVS 11.1 # Config info for aes_values @@ -90,73 +90,7 @@ def test_load_nist_vectors_encrypt(): ] -def test_load_nist_vectors_decrypt(): - vector_data = textwrap.dedent(""" - # CAVS 11.1 - # Config info for aes_values - # AESVS GFSbox test data for CBC - # State : Encrypt and Decrypt - # Key Length : 128 - # Generated on Fri Apr 22 15:11:33 2011 - - [ENCRYPT] - - COUNT = 0 - KEY = 00000000000000000000000000000000 - IV = 00000000000000000000000000000000 - PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6 - CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e - - COUNT = 1 - KEY = 00000000000000000000000000000000 - IV = 00000000000000000000000000000000 - PLAINTEXT = 9798c4640bad75c7c3227db910174e72 - CIPHERTEXT = a9a1631bf4996954ebc093957b234589 - - [DECRYPT] - - COUNT = 0 - KEY = 00000000000000000000000000000000 - IV = 00000000000000000000000000000000 - CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e - PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6 - - COUNT = 1 - KEY = 00000000000000000000000000000000 - IV = 00000000000000000000000000000000 - CIPHERTEXT = a9a1631bf4996954ebc093957b234589 - PLAINTEXT = 9798c4640bad75c7c3227db910174e72 - """).splitlines() - - assert load_nist_vectors(vector_data) == [ - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - ] - - -def test_load_nist_vectors_from_file_encrypt(): +def test_load_nist_vectors_from_file(): assert load_nist_vectors_from_file( os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp") ) == [ @@ -247,97 +181,6 @@ def test_load_nist_vectors_from_file_encrypt(): ] -def test_load_nist_vectors_from_file_decrypt(): - assert load_nist_vectors_from_file( - os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp"), - ) == [ - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", - "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"6a118a874519e64e9963798a503f1d35", - "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", - "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"b26aeb1874e47ca8358ff22378f09144", - "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", - "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", - "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"6a118a874519e64e9963798a503f1d35", - "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", - "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"b26aeb1874e47ca8358ff22378f09144", - "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", - "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", - }, - ] - - def test_load_cryptrec_vectors(): vector_data = textwrap.dedent(""" # Vectors taken from http://info.isl.ntt.co.jp/crypt/eng/camellia/ -- cgit v1.2.3 From f7f6a9f77ade1b190766c37cc8967375b5093175 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 11 Nov 2013 20:43:52 -0600 Subject: Remove separate file loaders and replace with one All tests updated to work with the new simplified loader --- tests/hazmat/primitives/test_3des.py | 14 +++++----- tests/hazmat/primitives/test_aes.py | 12 ++++---- tests/hazmat/primitives/test_arc4.py | 4 +-- tests/hazmat/primitives/test_blowfish.py | 10 +++---- tests/hazmat/primitives/test_camellia.py | 10 +++---- tests/hazmat/primitives/test_cast5.py | 4 +-- tests/hazmat/primitives/test_hash_vectors.py | 18 ++++++------ tests/hazmat/primitives/test_hmac_vectors.py | 16 +++++------ tests/hazmat/primitives/utils.py | 22 ++++++++++++--- tests/test_utils.py | 24 ++++++++-------- tests/utils.py | 42 ++++++---------------------- 11 files changed, 83 insertions(+), 93 deletions(-) diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py index 1543cfd7..69ec9c9a 100644 --- a/tests/hazmat/primitives/test_3des.py +++ b/tests/hazmat/primitives/test_3des.py @@ -23,12 +23,12 @@ import os from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test -from ...utils import load_nist_vectors_from_file +from ...utils import load_nist_vectors class TestTripleDES_CBC(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "CBC"), [ "TCBCinvperm.rsp", @@ -42,7 +42,7 @@ class TestTripleDES_CBC(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "CBC"), [ "TCBCMMT1.rsp", @@ -58,7 +58,7 @@ class TestTripleDES_CBC(object): class TestTripleDES_OFB(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "OFB"), [ "TOFBpermop.rsp", @@ -72,7 +72,7 @@ class TestTripleDES_OFB(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "OFB"), [ "TOFBMMT1.rsp", @@ -88,7 +88,7 @@ class TestTripleDES_OFB(object): class TestTripleDES_CFB(object): test_KAT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "CFB"), [ "TCFB64invperm.rsp", @@ -102,7 +102,7 @@ class TestTripleDES_CFB(object): ) test_MMT = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "3DES", "CFB"), [ "TCFB64MMT1.rsp", diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index c4818409..7c8cab72 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -20,13 +20,13 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test from ...utils import ( - load_nist_vectors_from_file, load_openssl_vectors_from_file + load_nist_vectors, load_openssl_vectors, ) class TestAES(object): test_CBC = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "AES", "CBC"), [ "CBCGFSbox128.rsp", @@ -50,7 +50,7 @@ class TestAES(object): ) test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "AES", "ECB"), [ "ECBGFSbox128.rsp", @@ -74,7 +74,7 @@ class TestAES(object): ) test_OFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "AES", "OFB"), [ "OFBGFSbox128.rsp", @@ -98,7 +98,7 @@ class TestAES(object): ) test_CFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "AES", "CFB"), [ "CFB128GFSbox128.rsp", @@ -122,7 +122,7 @@ class TestAES(object): ) test_CTR = generate_encrypt_test( - load_openssl_vectors_from_file, + load_openssl_vectors, os.path.join("ciphers", "AES", "CTR"), ["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"], lambda key, iv: algorithms.AES(binascii.unhexlify(key)), diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index 71b5d63a..302658f6 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -19,12 +19,12 @@ import os from cryptography.hazmat.primitives.ciphers import algorithms from .utils import generate_stream_encryption_test -from ...utils import load_nist_vectors_from_file +from ...utils import load_nist_vectors class TestARC4(object): test_rfc = generate_stream_encryption_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "ARC4"), [ "rfc-6229-40.txt", diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index 6f670ad7..eea0ac33 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -19,12 +19,12 @@ import os from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test -from ...utils import load_nist_vectors_from_file +from ...utils import load_nist_vectors class TestBlowfish(object): test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "Blowfish"), ["bf-ecb.txt"], lambda key: algorithms.Blowfish(binascii.unhexlify(key)), @@ -36,7 +36,7 @@ class TestBlowfish(object): ) test_CBC = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "Blowfish"), ["bf-cbc.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), @@ -48,7 +48,7 @@ class TestBlowfish(object): ) test_OFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "Blowfish"), ["bf-ofb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), @@ -60,7 +60,7 @@ class TestBlowfish(object): ) test_CFB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "Blowfish"), ["bf-cfb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py index e1be5d1d..223269a2 100644 --- a/tests/hazmat/primitives/test_camellia.py +++ b/tests/hazmat/primitives/test_camellia.py @@ -20,13 +20,13 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test from ...utils import ( - load_cryptrec_vectors_from_file, load_openssl_vectors_from_file + load_cryptrec_vectors, load_openssl_vectors ) class TestCamellia(object): test_ECB = generate_encrypt_test( - load_cryptrec_vectors_from_file, + load_cryptrec_vectors, os.path.join("ciphers", "Camellia"), [ "camellia-128-ecb.txt", @@ -42,7 +42,7 @@ class TestCamellia(object): ) test_CBC = generate_encrypt_test( - load_openssl_vectors_from_file, + load_openssl_vectors, os.path.join("ciphers", "Camellia"), ["camellia-cbc.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), @@ -54,7 +54,7 @@ class TestCamellia(object): ) test_OFB = generate_encrypt_test( - load_openssl_vectors_from_file, + load_openssl_vectors, os.path.join("ciphers", "Camellia"), ["camellia-ofb.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), @@ -66,7 +66,7 @@ class TestCamellia(object): ) test_CFB = generate_encrypt_test( - load_openssl_vectors_from_file, + load_openssl_vectors, os.path.join("ciphers", "Camellia"), ["camellia-cfb.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index 4256e2c4..486b5b5a 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -19,12 +19,12 @@ import os from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test -from ...utils import load_nist_vectors_from_file +from ...utils import load_nist_vectors class TestCAST5(object): test_ECB = generate_encrypt_test( - lambda path: load_nist_vectors_from_file(path), + load_nist_vectors, os.path.join("ciphers", "CAST5"), ["cast5-ecb.txt"], lambda key: algorithms.CAST5(binascii.unhexlify((key))), diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index fca839c7..b08beca6 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -18,12 +18,12 @@ import os from cryptography.hazmat.primitives import hashes from .utils import generate_hash_test, generate_long_string_hash_test -from ...utils import load_hash_vectors_from_file +from ...utils import load_hash_vectors class TestSHA1(object): test_SHA1 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "SHA1"), [ "SHA1LongMsg.rsp", @@ -37,7 +37,7 @@ class TestSHA1(object): class TestSHA224(object): test_SHA224 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "SHA2"), [ "SHA224LongMsg.rsp", @@ -51,7 +51,7 @@ class TestSHA224(object): class TestSHA256(object): test_SHA256 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "SHA2"), [ "SHA256LongMsg.rsp", @@ -65,7 +65,7 @@ class TestSHA256(object): class TestSHA384(object): test_SHA384 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "SHA2"), [ "SHA384LongMsg.rsp", @@ -79,7 +79,7 @@ class TestSHA384(object): class TestSHA512(object): test_SHA512 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "SHA2"), [ "SHA512LongMsg.rsp", @@ -93,7 +93,7 @@ class TestSHA512(object): class TestRIPEMD160(object): test_RIPEMD160 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "ripemd160"), [ "ripevectors.txt", @@ -113,7 +113,7 @@ class TestRIPEMD160(object): class TestWhirlpool(object): test_whirlpool = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "whirlpool"), [ "iso-test-vectors.txt", @@ -135,7 +135,7 @@ class TestWhirlpool(object): class TestMD5(object): test_md5 = generate_hash_test( - load_hash_vectors_from_file, + load_hash_vectors, os.path.join("hashes", "MD5"), [ "rfc-1321.txt", diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index 52d592b6..570c3d46 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -16,12 +16,12 @@ from __future__ import absolute_import, division, print_function from cryptography.hazmat.primitives import hashes from .utils import generate_hmac_test -from ...utils import load_hash_vectors_from_file +from ...utils import load_hash_vectors class TestHMAC_MD5(object): test_hmac_md5 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-2202-md5.txt", @@ -34,7 +34,7 @@ class TestHMAC_MD5(object): class TestHMAC_SHA1(object): test_hmac_sha1 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-2202-sha1.txt", @@ -47,7 +47,7 @@ class TestHMAC_SHA1(object): class TestHMAC_SHA224(object): test_hmac_sha224 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-4231-sha224.txt", @@ -60,7 +60,7 @@ class TestHMAC_SHA224(object): class TestHMAC_SHA256(object): test_hmac_sha256 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-4231-sha256.txt", @@ -73,7 +73,7 @@ class TestHMAC_SHA256(object): class TestHMAC_SHA384(object): test_hmac_sha384 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-4231-sha384.txt", @@ -86,7 +86,7 @@ class TestHMAC_SHA384(object): class TestHMAC_SHA512(object): test_hmac_sha512 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-4231-sha512.txt", @@ -99,7 +99,7 @@ class TestHMAC_SHA512(object): class TestHMAC_RIPEMD160(object): test_hmac_ripemd160 = generate_hmac_test( - load_hash_vectors_from_file, + load_hash_vectors, "HMAC", [ "rfc-2286-ripemd160.txt", diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 90c15b13..0f975950 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -8,6 +8,8 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac from cryptography.hazmat.primitives.ciphers import Cipher +from ...utils import load_vectors_from_file + def generate_encrypt_test(param_loader, path, file_names, cipher_factory, mode_factory, only_if=lambda backend: True, @@ -15,7 +17,10 @@ def generate_encrypt_test(param_loader, path, file_names, cipher_factory, def test_encryption(self): for backend in _ALL_BACKENDS: for file_name in file_names: - for params in param_loader(os.path.join(path, file_name)): + for params in load_vectors_from_file( + os.path.join(path, file_name), + param_loader + ): yield ( encrypt_test, backend, @@ -55,7 +60,10 @@ def generate_stream_encryption_test(param_loader, path, file_names, def test_stream_encryption(self): for backend in _ALL_BACKENDS: for file_name in file_names: - for params in param_loader(os.path.join(path, file_name)): + for params in load_vectors_from_file( + os.path.join(path, file_name), + param_loader + ): yield ( stream_encryption_test, backend, @@ -93,7 +101,10 @@ def generate_hash_test(param_loader, path, file_names, hash_cls, def test_hash(self): for backend in _ALL_BACKENDS: for file_name in file_names: - for params in param_loader(os.path.join(path, file_name)): + for params in load_vectors_from_file( + os.path.join(path, file_name), + param_loader + ): yield ( hash_test, backend, @@ -173,7 +184,10 @@ def generate_hmac_test(param_loader, path, file_names, algorithm, def test_hmac(self): for backend in _ALL_BACKENDS: for file_name in file_names: - for params in param_loader(os.path.join(path, file_name)): + for params in load_vectors_from_file( + os.path.join(path, file_name), + param_loader + ): yield ( hmac_test, backend, diff --git a/tests/test_utils.py b/tests/test_utils.py index 435690b7..ea8b48fb 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -17,10 +17,8 @@ import textwrap import pytest from .utils import ( - load_nist_vectors, load_nist_vectors_from_file, load_cryptrec_vectors, - load_cryptrec_vectors_from_file, load_openssl_vectors, - load_openssl_vectors_from_file, load_hash_vectors, - load_hash_vectors_from_file + load_nist_vectors, load_vectors_from_file, load_cryptrec_vectors, + load_openssl_vectors, load_hash_vectors, ) @@ -91,8 +89,9 @@ def test_load_nist_vectors(): def test_load_nist_vectors_from_file(): - assert load_nist_vectors_from_file( - os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp") + assert load_vectors_from_file( + os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp"), + load_nist_vectors ) == [ { "key": b"00000000000000000000000000000000", @@ -236,8 +235,9 @@ def test_load_cryptrec_vectors_invalid(): def test_load_cryptrec_vectors_from_file_encrypt(): - test_set = load_cryptrec_vectors_from_file( + test_set = load_vectors_from_file( os.path.join("ciphers", "Camellia", "camellia-128-ecb.txt"), + load_cryptrec_vectors ) assert test_set[0] == ( { @@ -301,8 +301,9 @@ def test_load_openssl_vectors(): def test_load_openssl_vectors_from_file(): - test_list = load_openssl_vectors_from_file( - os.path.join("ciphers", "Camellia", "camellia-ofb.txt") + test_list = load_vectors_from_file( + os.path.join("ciphers", "Camellia", "camellia-ofb.txt"), + load_openssl_vectors ) assert len(test_list) == 24 assert test_list[:4] == [ @@ -392,8 +393,9 @@ def test_load_hash_vectors_bad_data(): def test_load_hash_vectors_from_file(): - test_list = load_hash_vectors_from_file( - os.path.join("hashes", "MD5", "rfc-1321.txt") + test_list = load_vectors_from_file( + os.path.join("hashes", "MD5", "rfc-1321.txt"), + load_hash_vectors ) assert len(test_list) == 7 assert test_list[:4] == [ diff --git a/tests/utils.py b/tests/utils.py index 0b215543..df9232d8 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -14,6 +14,14 @@ import os.path +def load_vectors_from_file(filename, loader): + base = os.path.join( + os.path.dirname(__file__), "hazmat", "primitives", "vectors", + ) + with open(os.path.join(base, filename), "r") as vector_file: + return loader(vector_file) + + def load_nist_vectors(vector_data): section = None count = None @@ -52,23 +60,6 @@ def load_nist_vectors(vector_data): return [v for k, v in sorted(data.items(), key=lambda kv: kv[0])] -def load_nist_vectors_from_file(filename): - base = os.path.join( - os.path.dirname(__file__), "hazmat", "primitives", "vectors", - ) - with open(os.path.join(base, filename), "r") as vector_file: - return load_nist_vectors(vector_file) - - -def load_cryptrec_vectors_from_file(filename): - base = os.path.join( - os.path.dirname(__file__), - "hazmat", "primitives", "vectors", - ) - with open(os.path.join(base, filename), "r") as vector_file: - return load_cryptrec_vectors(vector_file) - - def load_cryptrec_vectors(vector_data): cryptrec_list = [] @@ -97,15 +88,6 @@ def load_cryptrec_vectors(vector_data): return cryptrec_list -def load_openssl_vectors_from_file(filename): - base = os.path.join( - os.path.dirname(__file__), - "hazmat", "primitives", "vectors", - ) - with open(os.path.join(base, filename), "r") as vector_file: - return load_openssl_vectors(vector_file) - - def load_openssl_vectors(vector_data): vectors = [] @@ -167,11 +149,3 @@ def load_hash_vectors(vector_data): else: raise ValueError("Unknown line in hash vector") return vectors - - -def load_hash_vectors_from_file(filename): - base = os.path.join( - os.path.dirname(__file__), "hazmat", "primitives", "vectors" - ) - with open(os.path.join(base, filename), "r") as vector_file: - return load_hash_vectors(vector_file) -- cgit v1.2.3 From 0f4d842449f144c6b5591c83d1ff856d16ea6af1 Mon Sep 17 00:00:00 2001 From: cyli Date: Mon, 11 Nov 2013 22:30:25 -0800 Subject: Simple function declarations (no callbacks) --- cryptography/hazmat/bindings/openssl/ssl.py | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py index 0a6a6fdc..30f40c66 100644 --- a/cryptography/hazmat/bindings/openssl/ssl.py +++ b/cryptography/hazmat/bindings/openssl/ssl.py @@ -116,6 +116,61 @@ static const int TLSEXT_NAMETYPE_host_name; FUNCTIONS = """ void SSL_load_error_strings(); + +int SSL_library_init(); + +/* SSL */ +SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *); +SSL_SESSION *SSL_get1_session(SSL *); +int SSL_set_session(SSL *, SSL_SESSION *); +int SSL_get_verify_mode(const SSL *); +void SSL_set_verify_depth(SSL *, int); +int SSL_get_verify_depth(const SSL *); +SSL *SSL_new(SSL_CTX *); +void SSL_free(SSL *); +int SSL_set_fd(SSL *, int); +void SSL_set_bio(SSL *, BIO *, BIO *); +void SSL_set_connect_state(SSL *); +void SSL_set_accept_state(SSL *); +void SSL_set_shutdown(SSL *, int); +int SSL_get_shutdown(const SSL *); +int SSL_pending(const SSL *); +int SSL_write(SSL *, const void *, int); +int SSL_read(SSL *, void *, int); +X509 *SSL_get_peer_certificate(const SSL *); +int SSL_get_error(const SSL *, int); +int SSL_do_handshake(SSL *); +int SSL_shutdown(SSL *); +const char *SSL_get_cipher_list(const SSL *, int); + +/* context */ +void SSL_CTX_free(SSL_CTX *); +long SSL_CTX_set_timeout(SSL_CTX *, long); +int SSL_CTX_set_default_verify_paths(SSL_CTX *); +void SSL_CTX_set_verify_depth(SSL_CTX *, int); +int SSL_CTX_get_verify_mode(const SSL_CTX *); +int SSL_CTX_get_verify_depth(const SSL_CTX *); +int SSL_CTX_set_cipher_list(SSL_CTX *, const char *); +int SSL_CTX_load_verify_locations(SSL_CTX *, const char *, const char *); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *, pem_password_cb *); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *, void *); +int SSL_CTX_use_certificate(SSL_CTX *, X509 *); +int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *); +int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int); +void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +int SSL_CTX_add_client_CA(SSL_CTX *, X509 *); + +/* X509_STORE_CTX */ +int X509_STORE_CTX_get_error(X509_STORE_CTX *); +void X509_STORE_CTX_set_error(X509_STORE_CTX *, int); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *); + +/* SSL_SESSION */ +void SSL_SESSION_free(SSL_SESSION *); """ MACROS = """ -- cgit v1.2.3 From cee8d525a4b2e42872ad8daf1404d7bebe820021 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 09:29:49 -0800 Subject: Simplify and make better hte tests for load_from_file --- tests/test_utils.py | 165 ++++------------------------------------------------ 1 file changed, 11 insertions(+), 154 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index ea8b48fb..6251242d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,9 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import textwrap +import py import pytest from .utils import ( @@ -88,98 +88,6 @@ def test_load_nist_vectors(): ] -def test_load_nist_vectors_from_file(): - assert load_vectors_from_file( - os.path.join("ciphers", "AES", "CBC", "CBCGFSbox128.rsp"), - load_nist_vectors - ) == [ - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", - "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"6a118a874519e64e9963798a503f1d35", - "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", - "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"b26aeb1874e47ca8358ff22378f09144", - "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", - "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"f34481ec3cc627bacd5dc3fb08f273e6", - "ciphertext": b"0336763e966d92595a567cc9ce537f5e", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"9798c4640bad75c7c3227db910174e72", - "ciphertext": b"a9a1631bf4996954ebc093957b234589", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"96ab5c2ff612d9dfaae8c31f30c42168", - "ciphertext": b"ff4f8391a6a40ca5b25d23bedd44a597", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"6a118a874519e64e9963798a503f1d35", - "ciphertext": b"dc43be40be0e53712f7e2bf5ca707209", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"cb9fceec81286ca3e989bd979b0cb284", - "ciphertext": b"92beedab1895a94faa69b632e5cc47ce", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"b26aeb1874e47ca8358ff22378f09144", - "ciphertext": b"459264f4798f6a78bacb89c15ed3d601", - }, - { - "key": b"00000000000000000000000000000000", - "iv": b"00000000000000000000000000000000", - "plaintext": b"58c8e00b2631686d54eab84b91f0aca1", - "ciphertext": b"08a4e2efec8a8e3312ca7460b9040bbf", - }, - ] - - def test_load_cryptrec_vectors(): vector_data = textwrap.dedent(""" # Vectors taken from http://info.isl.ntt.co.jp/crypt/eng/camellia/ @@ -234,21 +142,6 @@ def test_load_cryptrec_vectors_invalid(): load_cryptrec_vectors(vector_data) -def test_load_cryptrec_vectors_from_file_encrypt(): - test_set = load_vectors_from_file( - os.path.join("ciphers", "Camellia", "camellia-128-ecb.txt"), - load_cryptrec_vectors - ) - assert test_set[0] == ( - { - "key": b"00000000000000000000000000000000", - "plaintext": b"80000000000000000000000000000000", - "ciphertext": b"07923A39EB0A817D1C4D87BDB82D1F1C", - } - ) - assert len(test_set) == 1280 - - def test_load_openssl_vectors(): vector_data = textwrap.dedent( """ @@ -300,40 +193,6 @@ def test_load_openssl_vectors(): ] -def test_load_openssl_vectors_from_file(): - test_list = load_vectors_from_file( - os.path.join("ciphers", "Camellia", "camellia-ofb.txt"), - load_openssl_vectors - ) - assert len(test_list) == 24 - assert test_list[:4] == [ - { - "key": b"2B7E151628AED2A6ABF7158809CF4F3C", - "iv": b"000102030405060708090A0B0C0D0E0F", - "plaintext": b"6BC1BEE22E409F96E93D7E117393172A", - "ciphertext": b"14F7646187817EB586599146B82BD719", - }, - { - "key": b"2B7E151628AED2A6ABF7158809CF4F3C", - "iv": b"50FE67CC996D32B6DA0937E99BAFEC60", - "plaintext": b"AE2D8A571E03AC9C9EB76FAC45AF8E51", - "ciphertext": b"25623DB569CA51E01482649977E28D84", - }, - { - "key": b"2B7E151628AED2A6ABF7158809CF4F3C", - "iv": b"D9A4DADA0892239F6B8B3D7680E15674", - "plaintext": b"30C81C46A35CE411E5FBC1191A0A52EF", - "ciphertext": b"C776634A60729DC657D12B9FCA801E98", - }, - { - "key": b"2B7E151628AED2A6ABF7158809CF4F3C", - "iv": b"A78819583F0308E7A6BF36B1386ABF23", - "plaintext": b"F69F2445DF4F9B17AD2B417BE66C3710", - "ciphertext": b"D776379BE0E50825E681DA1A4C980E8E", - }, - ] - - def test_load_hash_vectors(): vector_data = textwrap.dedent(""" @@ -391,16 +250,14 @@ def test_load_hash_vectors_bad_data(): with pytest.raises(ValueError): load_hash_vectors(vector_data) - -def test_load_hash_vectors_from_file(): - test_list = load_vectors_from_file( - os.path.join("hashes", "MD5", "rfc-1321.txt"), - load_hash_vectors +def test_load_vectors_from_file(request): + path = py.path.local(__file__).dirpath().join( + "hazmat", "primitives", "vectors", "t.txt" ) - assert len(test_list) == 7 - assert test_list[:4] == [ - (b"", "d41d8cd98f00b204e9800998ecf8427e"), - (b"61", "0cc175b9c0f1b6a831c399e269772661"), - (b"616263", "900150983cd24fb0d6963f7d28e17f72"), - (b"6d65737361676520646967657374", "f96b697d7cb7938d525a2f31aaf161d0"), - ] + path.write(textwrap.dedent(""" + abc + 123 + """)) + request.addfinalizer(path.remove) + vectors = load_vectors_from_file("t.txt", lambda f: f.readlines()) + assert vectors == ["\n", "abc\n", "123\n"] -- cgit v1.2.3 From ab53bc525aace45158daf1bdfbac16c5e62593df Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 09:37:59 -0800 Subject: simplify --- tests/test_utils.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 6251242d..9d2ee4a5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,9 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import textwrap -import py import pytest from .utils import ( @@ -250,14 +250,20 @@ def test_load_hash_vectors_bad_data(): with pytest.raises(ValueError): load_hash_vectors(vector_data) -def test_load_vectors_from_file(request): - path = py.path.local(__file__).dirpath().join( - "hazmat", "primitives", "vectors", "t.txt" +def test_load_vectors_from_file(): + vectors = load_vectors_from_file( + os.path.join("ciphers", "Blowfish", "bf-cfb.txt"), + load_nist_vectors, ) - path.write(textwrap.dedent(""" - abc - 123 - """)) - request.addfinalizer(path.remove) - vectors = load_vectors_from_file("t.txt", lambda f: f.readlines()) - assert vectors == ["\n", "abc\n", "123\n"] + assert vectors == [ + { + "key": "0123456789ABCDEFF0E1D2C3B4A59687", + "iv": "FEDCBA9876543210", + "plaintext": ( + "37363534333231204E6F77206973207468652074696D6520666F722000" + ), + "ciphertext": ( + "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3" + ), + } + ] -- cgit v1.2.3 From c2f45d540bda76d675482636077f46b4834ba6e8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 09:50:25 -0800 Subject: fixed bytes --- tests/test_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 9d2ee4a5..26eb86fa 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -257,13 +257,13 @@ def test_load_vectors_from_file(): ) assert vectors == [ { - "key": "0123456789ABCDEFF0E1D2C3B4A59687", - "iv": "FEDCBA9876543210", + "key": b"0123456789ABCDEFF0E1D2C3B4A59687", + "iv": b"FEDCBA9876543210", "plaintext": ( - "37363534333231204E6F77206973207468652074696D6520666F722000" + b"37363534333231204E6F77206973207468652074696D6520666F722000" ), "ciphertext": ( - "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3" + b"E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3" ), } ] -- cgit v1.2.3 From 41172ab654e041680127919712994ec0cab371e8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 10:00:42 -0800 Subject: flake8 --- tests/test_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 26eb86fa..af575b37 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -250,6 +250,7 @@ def test_load_hash_vectors_bad_data(): with pytest.raises(ValueError): load_hash_vectors(vector_data) + def test_load_vectors_from_file(): vectors = load_vectors_from_file( os.path.join("ciphers", "Blowfish", "bf-cfb.txt"), -- cgit v1.2.3 From 217e3b55bf91c4c633a7b79f1b7f8bf2e3e6be31 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 10:27:49 -0800 Subject: Fixed using copied hashes --- cryptography/hazmat/primitives/hashes.py | 2 +- tests/hazmat/primitives/utils.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index bdad5e16..c7748118 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -34,7 +34,7 @@ class Hash(object): if ctx is None: self._ctx = self._backend.hashes.create_ctx(self.algorithm) else: - self._ctx = None + self._ctx = ctx def update(self, data): if isinstance(data, six.text_type): diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 0f975950..9327b0eb 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -155,6 +155,12 @@ def base_hash_test(backend, algorithm, digest_size, block_size, only_if, assert m != m_copy assert m._ctx != m_copy._ctx + m.update(b"abc") + copy = m.copy() + copy.update(b"123") + m.update(b"123") + assert copy.finalize() == m.finalize() + def generate_long_string_hash_test(hash_factory, md, only_if=None, skip_message=None): -- cgit v1.2.3 From ee6f8cec48028aeab213404dbce04bb6441a473c Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 12 Nov 2013 11:25:43 -0800 Subject: Get a HashContext from the backend like we do a CipherContext --- cryptography/hazmat/bindings/openssl/backend.py | 74 +++++++++++++++---------- cryptography/hazmat/primitives/hashes.py | 9 ++- tests/hazmat/primitives/test_hashes.py | 6 +- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 1cb886dc..86c6f660 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -269,47 +269,61 @@ class Ciphers(object): _CipherContext._DECRYPT) -class Hashes(object): - def __init__(self, backend): - super(Hashes, self).__init__() +@interfaces.register(interfaces.HashContext) +class _HashContext(object): + def __init__(self, backend, algorithm, ctx=None): + self.algorithm = algorithm + self._backend = backend - def supported(self, hash_cls): - return (self._backend.ffi.NULL != - self._backend.lib.EVP_get_digestbyname( - hash_cls.name.encode("ascii"))) + if ctx is None: + ctx = self._backend.lib.EVP_MD_CTX_create() + ctx = self._backend.ffi.gc(ctx, + self._backend.lib.EVP_MD_CTX_destroy) + evp_md = self._backend.lib.EVP_get_digestbyname( + algorithm.name.encode("ascii")) + assert evp_md != self._backend.ffi.NULL + res = self._backend.lib.EVP_DigestInit_ex(ctx, evp_md, + self._backend.ffi.NULL) + assert res != 0 - def create_ctx(self, hashobject): - ctx = self._backend.lib.EVP_MD_CTX_create() - ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_MD_CTX_destroy) - evp_md = self._backend.lib.EVP_get_digestbyname( - hashobject.name.encode("ascii")) - assert evp_md != self._backend.ffi.NULL - res = self._backend.lib.EVP_DigestInit_ex(ctx, evp_md, - self._backend.ffi.NULL) + self._ctx = ctx + + def copy(self): + copied_ctx = self._backend.lib.EVP_MD_CTX_create() + copied_ctx = self._backend.ffi.gc(copied_ctx, + self._backend.lib.EVP_MD_CTX_destroy) + res = self._backend.lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx) assert res != 0 - return ctx + return _HashContext(self._backend, self.algorithm, ctx=copied_ctx) - def update_ctx(self, ctx, data): - res = self._backend.lib.EVP_DigestUpdate(ctx, data, len(data)) + def update(self, data): + res = self._backend.lib.EVP_DigestUpdate(self._ctx, data, len(data)) assert res != 0 - def finalize_ctx(self, ctx, digest_size): - buf = self._backend.ffi.new("unsigned char[]", digest_size) - res = self._backend.lib.EVP_DigestFinal_ex(ctx, buf, + def finalize(self): + buf = self._backend.ffi.new("unsigned char[]", + self.algorithm.digest_size) + res = self._backend.lib.EVP_DigestFinal_ex(self._ctx, buf, self._backend.ffi.NULL) assert res != 0 - res = self._backend.lib.EVP_MD_CTX_cleanup(ctx) + res = self._backend.lib.EVP_MD_CTX_cleanup(self._ctx) assert res == 1 - return self._backend.ffi.buffer(buf)[:digest_size] + return self._backend.ffi.buffer(buf)[:self.algorithm.digest_size] - def copy_ctx(self, ctx): - copied_ctx = self._backend.lib.EVP_MD_CTX_create() - copied_ctx = self._backend.ffi.gc(copied_ctx, - self._backend.lib.EVP_MD_CTX_destroy) - res = self._backend.lib.EVP_MD_CTX_copy_ex(copied_ctx, ctx) - assert res != 0 - return copied_ctx + +class Hashes(object): + def __init__(self, backend): + super(Hashes, self).__init__() + self._backend = backend + + def supported(self, algorithm): + return (self._backend.ffi.NULL != + self._backend.lib.EVP_get_digestbyname( + algorithm.name.encode("ascii"))) + + def create_ctx(self, algorithm): + return _HashContext(self._backend, algorithm) class HMACs(object): diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index bdad5e16..c14d0437 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -34,20 +34,19 @@ class Hash(object): if ctx is None: self._ctx = self._backend.hashes.create_ctx(self.algorithm) else: - self._ctx = None + self._ctx = ctx def update(self, data): if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") - self._backend.hashes.update_ctx(self._ctx, data) + self._ctx.update(data) def copy(self): return self.__class__(self.algorithm, backend=self._backend, - ctx=self._backend.hashes.copy_ctx(self._ctx)) + ctx=self._ctx.copy()) def finalize(self): - return self._backend.hashes.finalize_ctx(self._ctx, - self.algorithm.digest_size) + return self._ctx.finalize() @interfaces.register(interfaces.HashAlgorithm) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 07ab2489..6cdb0a07 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -32,9 +32,9 @@ class TestHashContext(object): m.update(six.u("\u00FC")) def test_copy_backend_object(self): - pretend_hashes = pretend.stub(copy_ctx=lambda a: "copiedctx") - pretend_backend = pretend.stub(hashes=pretend_hashes) - pretend_ctx = pretend.stub() + pretend_backend = pretend.stub() + copied_ctx = pretend.stub() + pretend_ctx = pretend.stub(copy=lambda: copied_ctx) h = hashes.Hash(hashes.SHA1(), backend=pretend_backend, ctx=pretend_ctx) assert h._backend is pretend_backend -- cgit v1.2.3 From 0bcbb41964014926c3c604efff68f2d11b592035 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 12 Nov 2013 13:24:56 -0800 Subject: Get a HashContext from the hmac backend like we do a CipherContext --- cryptography/hazmat/bindings/openssl/backend.py | 80 ++++++++++++++++--------- cryptography/hazmat/primitives/hmac.py | 11 ++-- tests/hazmat/primitives/test_hmac.py | 5 +- 3 files changed, 60 insertions(+), 36 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 1cb886dc..60d51305 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -312,44 +312,66 @@ class Hashes(object): return copied_ctx -class HMACs(object): - def __init__(self, backend): - super(HMACs, self).__init__() +@interfaces.register(interfaces.HashContext) +class _HMACContext(object): + def __init__(self, backend, key, algorithm, ctx=None): + self.algorithm = algorithm + self._backend = backend - def create_ctx(self, key, hash_cls): - ctx = self._backend.ffi.new("HMAC_CTX *") - self._backend.lib.HMAC_CTX_init(ctx) - ctx = self._backend.ffi.gc(ctx, self._backend.lib.HMAC_CTX_cleanup) - evp_md = self._backend.lib.EVP_get_digestbyname( - hash_cls.name.encode('ascii')) - assert evp_md != self._backend.ffi.NULL - res = self._backend.lib.Cryptography_HMAC_Init_ex( - ctx, key, len(key), evp_md, self._backend.ffi.NULL + if ctx is None: + ctx = self._backend.ffi.new("HMAC_CTX *") + self._backend.lib.HMAC_CTX_init(ctx) + ctx = self._backend.ffi.gc(ctx, self._backend.lib.HMAC_CTX_cleanup) + evp_md = self._backend.lib.EVP_get_digestbyname( + algorithm.name.encode('ascii')) + assert evp_md != self._backend.ffi.NULL + res = self._backend.lib.Cryptography_HMAC_Init_ex( + ctx, key, len(key), evp_md, self._backend.ffi.NULL + ) + assert res != 0 + + self._ctx = ctx + self._key = key + + def copy(self): + copied_ctx = self._backend.ffi.new("HMAC_CTX *") + self._backend.lib.HMAC_CTX_init(copied_ctx) + copied_ctx = self._backend.ffi.gc( + copied_ctx, self._backend.lib.HMAC_CTX_cleanup + ) + res = self._backend.lib.Cryptography_HMAC_CTX_copy( + copied_ctx, self._ctx ) assert res != 0 - return ctx + return self.__class__( + self._backend, self._key, self.algorithm, ctx=copied_ctx + ) - def update_ctx(self, ctx, data): - res = self._backend.lib.Cryptography_HMAC_Update(ctx, data, len(data)) + def update(self, data): + res = self._backend.lib.Cryptography_HMAC_Update( + self._ctx, data, len(data) + ) assert res != 0 - def finalize_ctx(self, ctx, digest_size): - buf = self._backend.ffi.new("unsigned char[]", digest_size) - buflen = self._backend.ffi.new("unsigned int *", digest_size) - res = self._backend.lib.Cryptography_HMAC_Final(ctx, buf, buflen) + def finalize(self): + buf = self._backend.ffi.new("unsigned char[]", + self.algorithm.digest_size) + buflen = self._backend.ffi.new("unsigned int *", + self.algorithm.digest_size) + res = self._backend.lib.Cryptography_HMAC_Final(self._ctx, buf, buflen) assert res != 0 - self._backend.lib.HMAC_CTX_cleanup(ctx) - return self._backend.ffi.buffer(buf)[:digest_size] + self._backend.lib.HMAC_CTX_cleanup(self._ctx) + return self._backend.ffi.buffer(buf)[:self.algorithm.digest_size] - def copy_ctx(self, ctx): - copied_ctx = self._backend.ffi.new("HMAC_CTX *") - self._backend.lib.HMAC_CTX_init(copied_ctx) - copied_ctx = self._backend.ffi.gc(copied_ctx, - self._backend.lib.HMAC_CTX_cleanup) - res = self._backend.lib.Cryptography_HMAC_CTX_copy(copied_ctx, ctx) - assert res != 0 - return copied_ctx + +class HMACs(object): + def __init__(self, backend): + super(HMACs, self).__init__() + self._backend = backend + + def create_ctx(self, key, algorithm): + return _HMACContext(self._backend, key, algorithm) backend = Backend() diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 1457ed78..27bc0fee 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -40,12 +40,13 @@ class HMAC(object): def update(self, msg): if isinstance(msg, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") - self._backend.hmacs.update_ctx(self._ctx, msg) + self._ctx.update(msg) def copy(self): - return self.__class__(self._key, self.algorithm, backend=self._backend, - ctx=self._backend.hmacs.copy_ctx(self._ctx)) + return self.__class__( + self._key, self.algorithm, ctx=self._ctx.copy(), + backend=self._backend + ) def finalize(self): - return self._backend.hmacs.finalize_ctx(self._ctx, - self.algorithm.digest_size) + return self._ctx.finalize() diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index a44838cf..0f627a10 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -37,9 +37,10 @@ class TestHMAC(object): h.update(six.u("\u00FC")) def test_copy_backend_object(self): - pretend_hmac = pretend.stub(copy_ctx=lambda a: True) + pretend_hmac = pretend.stub() pretend_backend = pretend.stub(hmacs=pretend_hmac) - pretend_ctx = pretend.stub() + copied_ctx = pretend.stub() + pretend_ctx = pretend.stub(copy=lambda: copied_ctx) h = hmac.HMAC(b"key", hashes.SHA1(), backend=pretend_backend, ctx=pretend_ctx) assert h._backend is pretend_backend -- cgit v1.2.3 From ad3102ad806225448bf7274a2c5893cc74eda98e Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 12 Nov 2013 13:26:26 -0800 Subject: Reflow Hashes.supported. --- cryptography/hazmat/bindings/openssl/backend.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 86c6f660..235a8e30 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -318,9 +318,10 @@ class Hashes(object): self._backend = backend def supported(self, algorithm): - return (self._backend.ffi.NULL != - self._backend.lib.EVP_get_digestbyname( - algorithm.name.encode("ascii"))) + digest = self._backend.lib.EVP_get_digestbyname( + algorithm.name.encode("ascii") + ) + return digest != self._backend.ffi.NULL def create_ctx(self, algorithm): return _HashContext(self._backend, algorithm) -- cgit v1.2.3 From a43b6697255a8488cbd7e75182d06bf97bf86750 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 12 Nov 2013 15:35:49 -0600 Subject: GCM loader support --- tests/test_utils.py | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/utils.py | 6 ++- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index af575b37..4dede2e7 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -268,3 +268,133 @@ def test_load_vectors_from_file(): ), } ] + + +def test_load_nist_gcm_vectors(): + vector_data = textwrap.dedent(""" + [Keylen = 128] + [IVlen = 96] + [PTlen = 0] + [AADlen = 0] + [Taglen = 128] + + Count = 0 + Key = 11754cd72aec309bf52f7687212e8957 + IV = 3c819d9a9bed087615030b65 + PT = + AAD = + CT = + Tag = 250327c674aaf477aef2675748cf6971 + + Count = 1 + Key = 272f16edb81a7abbea887357a58c1917 + IV = 794ec588176c703d3d2a7a07 + PT = + AAD = + CT = + Tag = b6e6f197168f5049aeda32dafbdaeb + + Count = 2 + Key = a49a5e26a2f8cb63d05546c2a62f5343 + IV = 907763b19b9b4ab6bd4f0281 + CT = + AAD = + Tag = a2be08210d8c470a8df6e8fbd79ec5cf + FAIL + + Count = 3 + Key = 5c1155084cc0ede76b3bc22e9f7574ef + IV = 9549e4ba69a61cad7856efc1 + PT = d1448fa852b84408e2dad8381f363de7 + AAD = e98e9d9c618e46fef32660976f854ee3 + CT = f78b60ca125218493bea1c50a2e12ef4 + Tag = d72da7f5c6cf0bca7242c71835809449 + + [Keylen = 128] + [IVlen = 96] + [PTlen = 0] + [AADlen = 0] + [Taglen = 120] + + Count = 0 + Key = eac258e99c55e6ae8ef1da26640613d7 + IV = 4e8df20faaf2c8eebe922902 + CT = + AAD = + Tag = e39aeaebe86aa309a4d062d6274339 + PT = + + Count = 1 + Key = 3726cf02fcc6b8639a5497652c94350d + IV = 55fef82cde693ce76efcc193 + CT = + AAD = + Tag = 3d68111a81ed22d2ef5bccac4fc27f + FAIL + + Count = 2 + Key = f202299d5fd74f03b12d2119a6c4c038 + IV = eec51e7958c3f20a1bb71815 + CT = + AAD = + Tag = a81886b3fb26e51fca87b267e1e157 + FAIL + + Count = 3 + Key = fd52925f39546b4c55ffb6b20c59898c + IV = f5cf3227444afd905a5f6dba + CT = + AAD = + Tag = 1665b0f1a0b456e1664cfd3de08ccd + PT = + """).splitlines() + assert load_nist_vectors(vector_data) == [ + {'aad': b'', + 'pt': b'', + 'iv': b'4e8df20faaf2c8eebe922902', + 'tag': b'e39aeaebe86aa309a4d062d6274339', + 'key': b'eac258e99c55e6ae8ef1da26640613d7', + 'ct': b''}, + {'aad': b'', + 'iv': b'55fef82cde693ce76efcc193', + 'tag': b'3d68111a81ed22d2ef5bccac4fc27f', + 'key': b'3726cf02fcc6b8639a5497652c94350d', + 'ct': b'', + 'fail': True}, + {'aad': b'', + 'iv': b'eec51e7958c3f20a1bb71815', + 'tag': b'a81886b3fb26e51fca87b267e1e157', + 'key': b'f202299d5fd74f03b12d2119a6c4c038', + 'ct': b'', + 'fail': True}, + {'aad': b'', + 'pt': b'', + 'iv': b'f5cf3227444afd905a5f6dba', + 'tag': b'1665b0f1a0b456e1664cfd3de08ccd', + 'key': b'fd52925f39546b4c55ffb6b20c59898c', + 'ct': b''}, + {'aad': b'', + 'pt': b'', + 'iv': b'3c819d9a9bed087615030b65', + 'tag': b'250327c674aaf477aef2675748cf6971', + 'key': b'11754cd72aec309bf52f7687212e8957', + 'ct': b''}, + {'aad': b'', + 'pt': b'', + 'iv': b'794ec588176c703d3d2a7a07', + 'tag': b'b6e6f197168f5049aeda32dafbdaeb', + 'key': b'272f16edb81a7abbea887357a58c1917', + 'ct': b''}, + {'aad': b'', + 'iv': b'907763b19b9b4ab6bd4f0281', + 'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf', + 'key': b'a49a5e26a2f8cb63d05546c2a62f5343', + 'ct': b'', + 'fail': True}, + {'aad': b'e98e9d9c618e46fef32660976f854ee3', + 'pt': b'd1448fa852b84408e2dad8381f363de7', + 'iv': b'9549e4ba69a61cad7856efc1', + 'tag': b'd72da7f5c6cf0bca7242c71835809449', + 'key': b'5c1155084cc0ede76b3bc22e9f7574ef', + 'ct': b'f78b60ca125218493bea1c50a2e12ef4'}, + ] diff --git a/tests/utils.py b/tests/utils.py index df9232d8..8fa9af92 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -43,8 +43,12 @@ def load_nist_vectors(vector_data): section = line[1:-1] continue + if line.strip() == "FAIL": + data[section, count]["fail"] = True + continue + # Build our data using a simple Key = Value format - name, value = line.split(" = ") + name, value = [c.strip() for c in line.split("=")] # COUNT is a special token that indicates a new block of data if name.upper() == "COUNT": -- cgit v1.2.3 From 9d0d94d97cb8ed8d15b24018e20c08cf1f7b78b4 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 12 Nov 2013 14:26:10 -0800 Subject: Don't use self.__class__ --- cryptography/hazmat/bindings/openssl/backend.py | 2 +- cryptography/hazmat/primitives/hmac.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 60d51305..4d1be3b0 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -344,7 +344,7 @@ class _HMACContext(object): copied_ctx, self._ctx ) assert res != 0 - return self.__class__( + return _HMACContext( self._backend, self._key, self.algorithm, ctx=copied_ctx ) diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 27bc0fee..57a908c4 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -43,7 +43,7 @@ class HMAC(object): self._ctx.update(msg) def copy(self): - return self.__class__( + return HMAC( self._key, self.algorithm, ctx=self._ctx.copy(), backend=self._backend ) -- cgit v1.2.3 From 73278747b04c3bfca3972d69a917c194db6c24e3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 14:27:19 -0800 Subject: Drop random support for weird inheritance --- cryptography/hazmat/bindings/openssl/backend.py | 3 --- cryptography/hazmat/primitives/ciphers/algorithms.py | 6 ------ cryptography/hazmat/primitives/ciphers/base.py | 2 -- cryptography/hazmat/primitives/ciphers/modes.py | 4 ---- cryptography/hazmat/primitives/hashes.py | 5 +++-- cryptography/hazmat/primitives/hmac.py | 9 ++++++--- cryptography/hazmat/primitives/padding.py | 3 --- 7 files changed, 9 insertions(+), 23 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 235a8e30..b65583df 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -207,7 +207,6 @@ class _CipherContext(object): class Ciphers(object): def __init__(self, backend): - super(Ciphers, self).__init__() self._backend = backend self._cipher_registry = {} self._register_default_ciphers() @@ -314,7 +313,6 @@ class _HashContext(object): class Hashes(object): def __init__(self, backend): - super(Hashes, self).__init__() self._backend = backend def supported(self, algorithm): @@ -329,7 +327,6 @@ class Hashes(object): class HMACs(object): def __init__(self, backend): - super(HMACs, self).__init__() self._backend = backend def create_ctx(self, key, hash_cls): diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index cbfaceb8..32acab14 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -20,7 +20,6 @@ class AES(object): key_sizes = frozenset([128, 192, 256]) def __init__(self, key): - super(AES, self).__init__() self.key = key # Verify that the key size matches the expected key size @@ -40,7 +39,6 @@ class Camellia(object): key_sizes = frozenset([128, 192, 256]) def __init__(self, key): - super(Camellia, self).__init__() self.key = key # Verify that the key size matches the expected key size @@ -60,7 +58,6 @@ class TripleDES(object): key_sizes = frozenset([64, 128, 192]) def __init__(self, key): - super(TripleDES, self).__init__() if len(key) == 8: key += key + key elif len(key) == 16: @@ -84,7 +81,6 @@ class Blowfish(object): key_sizes = frozenset(range(32, 449, 8)) def __init__(self, key): - super(Blowfish, self).__init__() self.key = key # Verify that the key size matches the expected key size @@ -104,7 +100,6 @@ class CAST5(object): key_sizes = frozenset([40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128]) def __init__(self, key): - super(CAST5, self).__init__() self.key = key # Verify that the key size matches the expected key size @@ -123,7 +118,6 @@ class ARC4(object): key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256]) def __init__(self, key): - super(ARC4, self).__init__() self.key = key # Verify that the key size matches the expected key size diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index 1599308c..d48f9cc7 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -18,8 +18,6 @@ from cryptography.hazmat.primitives import interfaces class Cipher(object): def __init__(self, algorithm, mode, backend=None): - super(Cipher, self).__init__() - if backend is None: from cryptography.hazmat.bindings import ( _default_backend as backend, diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py index e54872a6..915fd83d 100644 --- a/cryptography/hazmat/primitives/ciphers/modes.py +++ b/cryptography/hazmat/primitives/ciphers/modes.py @@ -22,7 +22,6 @@ class CBC(object): name = "CBC" def __init__(self, initialization_vector): - super(CBC, self).__init__() self.initialization_vector = initialization_vector @@ -37,7 +36,6 @@ class OFB(object): name = "OFB" def __init__(self, initialization_vector): - super(OFB, self).__init__() self.initialization_vector = initialization_vector @@ -47,7 +45,6 @@ class CFB(object): name = "CFB" def __init__(self, initialization_vector): - super(CFB, self).__init__() self.initialization_vector = initialization_vector @@ -57,5 +54,4 @@ class CTR(object): name = "CTR" def __init__(self, nonce): - super(CTR, self).__init__() self.nonce = nonce diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index c14d0437..6ae622cd 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -42,8 +42,9 @@ class Hash(object): self._ctx.update(data) def copy(self): - return self.__class__(self.algorithm, backend=self._backend, - ctx=self._ctx.copy()) + return Hash( + self.algorithm, backend=self._backend, ctx=self._ctx.copy() + ) def finalize(self): return self._ctx.finalize() diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 1457ed78..ed2dd54a 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -21,7 +21,6 @@ from cryptography.hazmat.primitives import interfaces @interfaces.register(interfaces.HashContext) class HMAC(object): def __init__(self, key, algorithm, ctx=None, backend=None): - super(HMAC, self).__init__() if not isinstance(algorithm, interfaces.HashAlgorithm): raise TypeError("Expected instance of interfaces.HashAlgorithm.") self.algorithm = algorithm @@ -43,8 +42,12 @@ class HMAC(object): self._backend.hmacs.update_ctx(self._ctx, msg) def copy(self): - return self.__class__(self._key, self.algorithm, backend=self._backend, - ctx=self._backend.hmacs.copy_ctx(self._ctx)) + return HMAC( + self._key, + self.algorithm, + backend=self._backend, + ctx=self._backend.hmacs.copy_ctx(self._ctx) + ) def finalize(self): return self._backend.hmacs.finalize_ctx(self._ctx, diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py index eac18c2a..f41c62c3 100644 --- a/cryptography/hazmat/primitives/padding.py +++ b/cryptography/hazmat/primitives/padding.py @@ -18,7 +18,6 @@ from cryptography.hazmat.primitives import interfaces class PKCS7(object): def __init__(self, block_size): - super(PKCS7, self).__init__() if not (0 <= block_size < 256): raise ValueError("block_size must be in range(0, 256)") @@ -37,7 +36,6 @@ class PKCS7(object): @interfaces.register(interfaces.PaddingContext) class _PKCS7PaddingContext(object): def __init__(self, block_size): - super(_PKCS7PaddingContext, self).__init__() self.block_size = block_size # TODO: O(n ** 2) complexity for repeated concatentation, we should use # zero-buffer (#193) @@ -72,7 +70,6 @@ class _PKCS7PaddingContext(object): @interfaces.register(interfaces.PaddingContext) class _PKCS7UnpaddingContext(object): def __init__(self, block_size): - super(_PKCS7UnpaddingContext, self).__init__() self.block_size = block_size # TODO: O(n ** 2) complexity for repeated concatentation, we should use # zero-buffer (#193) -- cgit v1.2.3 From 3f3921e2d082fd99c6186ed7bb174caf481819bd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 14:27:55 -0800 Subject: Don't query OpenSSL for block sizes, we already know them --- cryptography/hazmat/bindings/openssl/backend.py | 7 +++---- cryptography/hazmat/primitives/ciphers/algorithms.py | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 235a8e30..89ee2b53 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -140,6 +140,7 @@ class _CipherContext(object): def __init__(self, backend, cipher, mode, operation): self._backend = backend + self._cipher = cipher ctx = self._backend.lib.EVP_CIPHER_CTX_new() ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free) @@ -185,9 +186,8 @@ class _CipherContext(object): self._ctx = ctx def update(self, data): - block_size = self._backend.lib.EVP_CIPHER_CTX_block_size(self._ctx) buf = self._backend.ffi.new("unsigned char[]", - len(data) + block_size - 1) + len(data) + self._cipher.block_size - 1) outlen = self._backend.ffi.new("int *") res = self._backend.lib.EVP_CipherUpdate(self._ctx, buf, outlen, data, len(data)) @@ -195,8 +195,7 @@ class _CipherContext(object): return self._backend.ffi.buffer(buf)[:outlen[0]] def finalize(self): - block_size = self._backend.lib.EVP_CIPHER_CTX_block_size(self._ctx) - buf = self._backend.ffi.new("unsigned char[]", block_size) + buf = self._backend.ffi.new("unsigned char[]", self._cipher.block_size) outlen = self._backend.ffi.new("int *") res = self._backend.lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) assert res != 0 diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index cbfaceb8..61e93b0e 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -120,6 +120,7 @@ class CAST5(object): class ARC4(object): name = "RC4" + block_size = 1 key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256]) def __init__(self, key): -- cgit v1.2.3 From 152d6bec8c34c52d75373dd8d99a3d159baa9550 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 12 Nov 2013 16:41:13 -0800 Subject: raise an exception if you try to use a HashContext after finalize is called. --- cryptography/exceptions.py | 4 ++++ cryptography/hazmat/primitives/hashes.py | 9 ++++++++- tests/hazmat/primitives/test_hashes.py | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cryptography/exceptions.py b/cryptography/exceptions.py index 391bed82..c2e71493 100644 --- a/cryptography/exceptions.py +++ b/cryptography/exceptions.py @@ -14,3 +14,7 @@ class UnsupportedAlgorithm(Exception): pass + + +class AlreadyFinalized(Exception): + pass diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index 6ae622cd..f85d36a0 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -15,6 +15,7 @@ from __future__ import absolute_import, division, print_function import six +from cryptography import exceptions from cryptography.hazmat.primitives import interfaces @@ -37,17 +38,23 @@ class Hash(object): self._ctx = ctx def update(self, data): + if self._ctx is None: + raise exceptions.AlreadyFinalized() if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") self._ctx.update(data) def copy(self): + if self._ctx is None: + raise exceptions.AlreadyFinalized() return Hash( self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) def finalize(self): - return self._ctx.finalize() + digest = self._ctx.finalize() + self._ctx = None + return digest @interfaces.register(interfaces.HashAlgorithm) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 6cdb0a07..a5c440b8 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -19,6 +19,7 @@ import pytest import six +from cryptography import exceptions from cryptography.hazmat.bindings import _default_backend from cryptography.hazmat.primitives import hashes @@ -51,6 +52,16 @@ class TestHashContext(object): with pytest.raises(TypeError): hashes.Hash(hashes.SHA1) + def test_raises_after_finalize(self): + h = hashes.Hash(hashes.SHA1()) + h.finalize() + + with pytest.raises(exceptions.AlreadyFinalized): + h.update(b"foo") + + with pytest.raises(exceptions.AlreadyFinalized): + h.copy() + class TestSHA1(object): test_SHA1 = generate_base_hash_test( -- cgit v1.2.3 From 01ea17f1f8ae9c13743d4bbc29acba3d48768228 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 16:43:02 -0800 Subject: Remove unnecesary slice bounds --- cryptography/hazmat/bindings/openssl/backend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 4760f9b7..71bb9fcd 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -307,7 +307,7 @@ class _HashContext(object): assert res != 0 res = self._backend.lib.EVP_MD_CTX_cleanup(self._ctx) assert res == 1 - return self._backend.ffi.buffer(buf)[:self.algorithm.digest_size] + return self._backend.ffi.buffer(buf)[:] class Hashes(object): @@ -373,7 +373,7 @@ class _HMACContext(object): res = self._backend.lib.Cryptography_HMAC_Final(self._ctx, buf, buflen) assert res != 0 self._backend.lib.HMAC_CTX_cleanup(self._ctx) - return self._backend.ffi.buffer(buf)[:self.algorithm.digest_size] + return self._backend.ffi.buffer(buf)[:] class HMACs(object): -- cgit v1.2.3 From e590abca527e25f92d21011baa70aea6fc4bb372 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 17:09:31 -0800 Subject: Call out the security reporting info in the CONTRIBUTING file --- CONTRIBUTING.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9f63250f..2a71daee 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -13,3 +13,10 @@ Extensive contribution guidelines are available in the repository at ``docs/contributing.rst``, or online at: https://cryptography.io/en/latest/contributing/ + +.. attention:: + + To report a security issue, please follow the special `security reporting + guidelines`_, do not report them in the public issue tracker. + +.. _`security reporting guidelines`: https://cryptography.io/en/latest/security/ -- cgit v1.2.3 From dd43113a4b713f133e3c3443d69edfef8a4c1e9a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 17:39:27 -0800 Subject: Try this element --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2a71daee..b1672b0f 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -14,7 +14,7 @@ Extensive contribution guidelines are available in the repository at https://cryptography.io/en/latest/contributing/ -.. attention:: +.. highlights:: To report a security issue, please follow the special `security reporting guidelines`_, do not report them in the public issue tracker. -- cgit v1.2.3 From a64cf599d8147fa6ae55d97f657db411058ecc71 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 17:40:08 -0800 Subject: Another element --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index b1672b0f..315e9611 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -14,7 +14,7 @@ Extensive contribution guidelines are available in the repository at https://cryptography.io/en/latest/contributing/ -.. highlights:: +.. pull-quote:: To report a security issue, please follow the special `security reporting guidelines`_, do not report them in the public issue tracker. -- cgit v1.2.3 From bf803fc8810aca3886b35689f056e9c71568ad92 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 17:40:50 -0800 Subject: Donald says this is good --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 315e9611..3cd53118 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -14,7 +14,7 @@ Extensive contribution guidelines are available in the repository at https://cryptography.io/en/latest/contributing/ -.. pull-quote:: +.. note:: To report a security issue, please follow the special `security reporting guidelines`_, do not report them in the public issue tracker. -- cgit v1.2.3 From f139582c9363dc5fa1f34fe377e473e8b4fcc34b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 12 Nov 2013 17:45:30 -0800 Subject: giv eup and use a header --- CONTRIBUTING.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 3cd53118..b47f77e5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -14,9 +14,10 @@ Extensive contribution guidelines are available in the repository at https://cryptography.io/en/latest/contributing/ -.. note:: +Security issues +--------------- - To report a security issue, please follow the special `security reporting - guidelines`_, do not report them in the public issue tracker. +To report a security issue, please follow the special `security reporting +guidelines`_, do not report them in the public issue tracker. .. _`security reporting guidelines`: https://cryptography.io/en/latest/security/ -- cgit v1.2.3 From 063a3a25630df98f4524fdc54a55cef670810d9f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 09:35:23 -0800 Subject: Remove the hash and hmac specific classes, now that the logic is the Context classes they don't really add value --- cryptography/hazmat/bindings/openssl/backend.py | 34 ++++++++----------------- cryptography/hazmat/primitives/hashes.py | 2 +- cryptography/hazmat/primitives/hmac.py | 2 +- tests/hazmat/primitives/test_hash_vectors.py | 20 +++++++-------- tests/hazmat/primitives/test_hashes.py | 16 ++++++------ tests/hazmat/primitives/test_hmac.py | 2 +- tests/hazmat/primitives/test_hmac_vectors.py | 14 +++++----- 7 files changed, 38 insertions(+), 52 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 71bb9fcd..ff2c939c 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -64,8 +64,6 @@ class Backend(object): self._ensure_ffi_initialized() self.ciphers = Ciphers(self) - self.hashes = Hashes(self) - self.hmacs = HMACs(self) @classmethod def _ensure_ffi_initialized(cls): @@ -123,6 +121,16 @@ class Backend(object): """ return self.ffi.string(self.lib.OPENSSL_VERSION_TEXT).decode("ascii") + def create_hmac_ctx(self, key, algorithm): + return _HMACContext(self, key, algorithm) + + def hash_supported(self, algorithm): + digest = self.lib.EVP_get_digestbyname(algorithm.name.encode("ascii")) + return digest != self.ffi.NULL + + def create_hash_ctx(self, algorithm): + return _HashContext(self, algorithm) + class GetCipherByName(object): def __init__(self, fmt): @@ -310,20 +318,6 @@ class _HashContext(object): return self._backend.ffi.buffer(buf)[:] -class Hashes(object): - def __init__(self, backend): - self._backend = backend - - def supported(self, algorithm): - digest = self._backend.lib.EVP_get_digestbyname( - algorithm.name.encode("ascii") - ) - return digest != self._backend.ffi.NULL - - def create_ctx(self, algorithm): - return _HashContext(self._backend, algorithm) - - @interfaces.register(interfaces.HashContext) class _HMACContext(object): def __init__(self, backend, key, algorithm, ctx=None): @@ -376,12 +370,4 @@ class _HMACContext(object): return self._backend.ffi.buffer(buf)[:] -class HMACs(object): - def __init__(self, backend): - self._backend = backend - - def create_ctx(self, key, algorithm): - return _HMACContext(self._backend, key, algorithm) - - backend = Backend() diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index 6ae622cd..3bd3ad46 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -32,7 +32,7 @@ class Hash(object): self._backend = backend if ctx is None: - self._ctx = self._backend.hashes.create_ctx(self.algorithm) + self._ctx = self._backend.create_hash_ctx(self.algorithm) else: self._ctx = ctx diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 0f1b4fac..1a67b332 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -32,7 +32,7 @@ class HMAC(object): self._backend = backend self._key = key if ctx is None: - self._ctx = self._backend.hmacs.create_ctx(key, self.algorithm) + self._ctx = self._backend.create_hmac_ctx(key, self.algorithm) else: self._ctx = ctx diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index b08beca6..a8655812 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -30,7 +30,7 @@ class TestSHA1(object): "SHA1ShortMsg.rsp", ], hashes.SHA1(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA1), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.SHA224), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.SHA256), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.SHA384), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.SHA512), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.Whirlpool), + only_if=lambda backend: backend.hash_supported(hashes.Whirlpool), skip_message="Does not support Whirlpool", ) @@ -128,7 +128,7 @@ class TestWhirlpool(object): ("0c99005beb57eff50a7cf005560ddf5d29057fd86b2" "0bfd62deca0f1ccea4af51fc15490eddc47af32bb2b" "66c34ff9ad8c6008ad677f77126953b226e4ed8b01"), - only_if=lambda backend: backend.hashes.supported(hashes.Whirlpool), + only_if=lambda backend: backend.hash_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.hashes.supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5), skip_message="Does not support MD5", ) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 6cdb0a07..c022f537 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -57,7 +57,7 @@ class TestSHA1(object): hashes.SHA1(), digest_size=20, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.SHA1), + only_if=lambda backend: backend.hash_supported(hashes.SHA1), skip_message="Does not support SHA1", ) @@ -67,7 +67,7 @@ class TestSHA224(object): hashes.SHA224(), digest_size=28, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.SHA224), + only_if=lambda backend: backend.hash_supported(hashes.SHA224), skip_message="Does not support SHA224", ) @@ -77,7 +77,7 @@ class TestSHA256(object): hashes.SHA256(), digest_size=32, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.SHA256), + only_if=lambda backend: backend.hash_supported(hashes.SHA256), skip_message="Does not support SHA256", ) @@ -87,7 +87,7 @@ class TestSHA384(object): hashes.SHA384(), digest_size=48, block_size=128, - only_if=lambda backend: backend.hashes.supported(hashes.SHA384), + only_if=lambda backend: backend.hash_supported(hashes.SHA384), skip_message="Does not support SHA384", ) @@ -97,7 +97,7 @@ class TestSHA512(object): hashes.SHA512(), digest_size=64, block_size=128, - only_if=lambda backend: backend.hashes.supported(hashes.SHA512), + only_if=lambda backend: backend.hash_supported(hashes.SHA512), skip_message="Does not support SHA512", ) @@ -107,7 +107,7 @@ class TestRIPEMD160(object): hashes.RIPEMD160(), digest_size=20, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160), skip_message="Does not support RIPEMD160", ) @@ -117,7 +117,7 @@ class TestWhirlpool(object): hashes.Whirlpool(), digest_size=64, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.Whirlpool), + only_if=lambda backend: backend.hash_supported(hashes.Whirlpool), skip_message="Does not support Whirlpool", ) @@ -127,6 +127,6 @@ class TestMD5(object): hashes.MD5(), digest_size=16, block_size=64, - only_if=lambda backend: backend.hashes.supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5), skip_message="Does not support MD5", ) diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 0f627a10..4186967a 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -27,7 +27,7 @@ from .utils import generate_base_hmac_test class TestHMAC(object): test_copy = generate_base_hmac_test( hashes.MD5(), - only_if=lambda backend: backend.hashes.supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5), skip_message="Does not support MD5", ) diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index 570c3d46..7d0f156a 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -27,7 +27,7 @@ class TestHMAC_MD5(object): "rfc-2202-md5.txt", ], hashes.MD5(), - only_if=lambda backend: backend.hashes.supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5), skip_message="Does not support MD5", ) @@ -40,7 +40,7 @@ class TestHMAC_SHA1(object): "rfc-2202-sha1.txt", ], hashes.SHA1(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA1), + only_if=lambda backend: backend.hash_supported(hashes.SHA1), skip_message="Does not support SHA1", ) @@ -53,7 +53,7 @@ class TestHMAC_SHA224(object): "rfc-4231-sha224.txt", ], hashes.SHA224(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA224), + only_if=lambda backend: backend.hash_supported(hashes.SHA224), skip_message="Does not support SHA224", ) @@ -66,7 +66,7 @@ class TestHMAC_SHA256(object): "rfc-4231-sha256.txt", ], hashes.SHA256(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA256), + only_if=lambda backend: backend.hash_supported(hashes.SHA256), skip_message="Does not support SHA256", ) @@ -79,7 +79,7 @@ class TestHMAC_SHA384(object): "rfc-4231-sha384.txt", ], hashes.SHA384(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA384), + only_if=lambda backend: backend.hash_supported(hashes.SHA384), skip_message="Does not support SHA384", ) @@ -92,7 +92,7 @@ class TestHMAC_SHA512(object): "rfc-4231-sha512.txt", ], hashes.SHA512(), - only_if=lambda backend: backend.hashes.supported(hashes.SHA512), + only_if=lambda backend: backend.hash_supported(hashes.SHA512), skip_message="Does not support SHA512", ) @@ -105,6 +105,6 @@ class TestHMAC_RIPEMD160(object): "rfc-2286-ripemd160.txt", ], hashes.RIPEMD160(), - only_if=lambda backend: backend.hashes.supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160), skip_message="Does not support RIPEMD160", ) -- cgit v1.2.3 From e5aa205070877852ff2d54eebcc0d4ac9cf8465e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 09:49:23 -0800 Subject: Also remove teh ciphers specific class --- cryptography/hazmat/bindings/openssl/backend.py | 122 +++++++++++------------- cryptography/hazmat/primitives/ciphers/base.py | 12 +-- tests/hazmat/bindings/test_openssl.py | 6 +- tests/hazmat/primitives/test_aes.py | 2 +- tests/hazmat/primitives/test_arc4.py | 2 +- tests/hazmat/primitives/test_blowfish.py | 8 +- tests/hazmat/primitives/test_camellia.py | 8 +- tests/hazmat/primitives/test_cast5.py | 2 +- 8 files changed, 77 insertions(+), 85 deletions(-) diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index ff2c939c..844e175f 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -63,7 +63,8 @@ class Backend(object): def __init__(self): self._ensure_ffi_initialized() - self.ciphers = Ciphers(self) + self._cipher_registry = {} + self._register_default_ciphers() @classmethod def _ensure_ffi_initialized(cls): @@ -131,6 +132,60 @@ class Backend(object): def create_hash_ctx(self, algorithm): return _HashContext(self, algorithm) + def cipher_supported(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}") + ) + for mode_cls in [CBC, CFB, OFB]: + self.register_cipher_adapter( + TripleDES, + mode_cls, + GetCipherByName("des-ede3-{mode.name}") + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + Blowfish, + mode_cls, + GetCipherByName("bf-{mode.name}") + ) + self.register_cipher_adapter( + CAST5, + ECB, + GetCipherByName("cast5-ecb") + ) + self.register_cipher_adapter( + ARC4, + type(None), + GetCipherByName("rc4") + ) + + def create_symmetric_encryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) + + def create_symmetric_decryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + class GetCipherByName(object): def __init__(self, fmt): @@ -153,7 +208,7 @@ class _CipherContext(object): ctx = self._backend.lib.EVP_CIPHER_CTX_new() ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free) - registry = self._backend.ciphers._cipher_registry + registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: @@ -212,69 +267,6 @@ class _CipherContext(object): return self._backend.ffi.buffer(buf)[:outlen[0]] -class Ciphers(object): - def __init__(self, backend): - self._backend = backend - self._cipher_registry = {} - self._register_default_ciphers() - - def supported(self, cipher, mode): - try: - adapter = self._cipher_registry[type(cipher), type(mode)] - except KeyError: - return False - evp_cipher = adapter(self._backend, cipher, mode) - return self._backend.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}") - ) - for mode_cls in [CBC, CFB, OFB]: - self.register_cipher_adapter( - TripleDES, - mode_cls, - GetCipherByName("des-ede3-{mode.name}") - ) - for mode_cls in [CBC, CFB, OFB, ECB]: - self.register_cipher_adapter( - Blowfish, - mode_cls, - GetCipherByName("bf-{mode.name}") - ) - self.register_cipher_adapter( - CAST5, - ECB, - GetCipherByName("cast5-ecb") - ) - self.register_cipher_adapter( - ARC4, - type(None), - GetCipherByName("rc4") - ) - - def create_encrypt_ctx(self, cipher, mode): - return _CipherContext(self._backend, cipher, mode, - _CipherContext._ENCRYPT) - - def create_decrypt_ctx(self, cipher, mode): - return _CipherContext(self._backend, cipher, mode, - _CipherContext._DECRYPT) - - @interfaces.register(interfaces.HashContext) class _HashContext(object): def __init__(self, backend, algorithm, ctx=None): diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index d48f9cc7..794d0191 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -28,14 +28,14 @@ class Cipher(object): self._backend = backend def encryptor(self): - return _CipherContext( - self._backend.ciphers.create_encrypt_ctx(self.algorithm, - self.mode)) + return _CipherContext(self._backend.create_symmetric_encryption_ctx( + self.algorithm, self.mode + )) def decryptor(self): - return _CipherContext( - self._backend.ciphers.create_decrypt_ctx(self.algorithm, - self.mode)) + return _CipherContext(self._backend.create_symmetric_decryption_ctx( + self.algorithm, self.mode + )) @interfaces.register(interfaces.CipherContext) diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index f1493e8d..241c6411 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -44,11 +44,11 @@ class TestOpenSSL(object): assert backend.openssl_version_text().startswith("OpenSSL") def test_supports_cipher(self): - assert backend.ciphers.supported(None, None) is False + assert backend.cipher_supported(None, None) is False def test_register_duplicate_cipher_adapter(self): with pytest.raises(ValueError): - backend.ciphers.register_cipher_adapter(AES, CBC, None) + backend.register_cipher_adapter(AES, CBC, None) def test_instances_share_ffi(self): b = Backend() @@ -57,7 +57,7 @@ class TestOpenSSL(object): def test_nonexistent_cipher(self): b = Backend() - b.ciphers.register_cipher_adapter( + b.register_cipher_adapter( FakeCipher, FakeMode, lambda backend, cipher, mode: backend.ffi.NULL diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 7c8cab72..d178da7b 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -127,7 +127,7 @@ class TestAES(object): ["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"], lambda key, iv: algorithms.AES(binascii.unhexlify(key)), lambda key, iv: modes.CTR(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.AES("\x00" * 16), modes.CTR("\x00" * 16) ), skip_message="Does not support AES CTR", diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index 302658f6..d233bec2 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -36,7 +36,7 @@ class TestARC4(object): "rfc-6229-256.txt", ], lambda key: algorithms.ARC4(binascii.unhexlify((key))), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.ARC4("\x00" * 16), None ), skip_message="Does not support ARC4", diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index eea0ac33..d5fbed6f 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -29,7 +29,7 @@ class TestBlowfish(object): ["bf-ecb.txt"], lambda key: algorithms.Blowfish(binascii.unhexlify(key)), lambda key: modes.ECB(), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Blowfish("\x00" * 56), modes.ECB() ), skip_message="Does not support Blowfish ECB", @@ -41,7 +41,7 @@ class TestBlowfish(object): ["bf-cbc.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), lambda key, iv: modes.CBC(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Blowfish("\x00" * 56), modes.CBC("\x00" * 8) ), skip_message="Does not support Blowfish CBC", @@ -53,7 +53,7 @@ class TestBlowfish(object): ["bf-ofb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), lambda key, iv: modes.OFB(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Blowfish("\x00" * 56), modes.OFB("\x00" * 8) ), skip_message="Does not support Blowfish OFB", @@ -65,7 +65,7 @@ class TestBlowfish(object): ["bf-cfb.txt"], lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)), lambda key, iv: modes.CFB(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Blowfish("\x00" * 56), modes.CFB("\x00" * 8) ), skip_message="Does not support Blowfish CFB", diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py index 223269a2..a2c935d9 100644 --- a/tests/hazmat/primitives/test_camellia.py +++ b/tests/hazmat/primitives/test_camellia.py @@ -35,7 +35,7 @@ class TestCamellia(object): ], lambda key: algorithms.Camellia(binascii.unhexlify((key))), lambda key: modes.ECB(), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Camellia("\x00" * 16), modes.ECB() ), skip_message="Does not support Camellia ECB", @@ -47,7 +47,7 @@ class TestCamellia(object): ["camellia-cbc.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), lambda key, iv: modes.CBC(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Camellia("\x00" * 16), modes.CBC("\x00" * 16) ), skip_message="Does not support Camellia CBC", @@ -59,7 +59,7 @@ class TestCamellia(object): ["camellia-ofb.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), lambda key, iv: modes.OFB(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Camellia("\x00" * 16), modes.OFB("\x00" * 16) ), skip_message="Does not support Camellia OFB", @@ -71,7 +71,7 @@ class TestCamellia(object): ["camellia-cfb.txt"], lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)), lambda key, iv: modes.CFB(binascii.unhexlify(iv)), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.Camellia("\x00" * 16), modes.CFB("\x00" * 16) ), skip_message="Does not support Camellia CFB", diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index 486b5b5a..a283dafc 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -29,7 +29,7 @@ class TestCAST5(object): ["cast5-ecb.txt"], lambda key: algorithms.CAST5(binascii.unhexlify((key))), lambda key: modes.ECB(), - only_if=lambda backend: backend.ciphers.supported( + only_if=lambda backend: backend.cipher_supported( algorithms.CAST5("\x00" * 16), modes.ECB() ), skip_message="Does not support CAST5 ECB", -- cgit v1.2.3 From 6392a9c63ce134c4aceefb8a4eb9da2fa7f4f390 Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 13 Nov 2013 10:01:15 -0800 Subject: Document AlreadyFinalized. --- docs/exceptions.rst | 6 ++++++ docs/hazmat/primitives/cryptographic-hashes.rst | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/exceptions.rst b/docs/exceptions.rst index 6ac11b3c..d6c15087 100644 --- a/docs/exceptions.rst +++ b/docs/exceptions.rst @@ -3,7 +3,13 @@ Exceptions .. currentmodule:: cryptography.exceptions +.. class:: AlreadyFinalized + + This is raised when a context is used after being it has been finalized. + + .. class:: UnsupportedAlgorithm This is raised when a backend doesn't support the requested algorithm (or combination of algorithms). + diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 20fa23cf..7eff1b85 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -30,16 +30,25 @@ Message Digests .. method:: update(data) :param bytes data: The bytes you wish to hash. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` .. method:: copy() - :return: a new instance of this object with a copied internal state. + Copy this :class:`Hash` instance, usually so that we may call + :meth:`finalize` and get an intermediate digest value while we continue + to call :meth:`update` on the original. + + :return: A new instance of :class:`Hash` which can be updated + and finalized independently of the original instance. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` .. method:: finalize() Finalize the current context and return the message digest as bytes. - Once ``finalize`` is called this object can no longer be used. + Once ``finalize`` is called this object can no longer be used and + :meth:`update` and :meth:`copy` will raise + :class:`~cryptography.exceptions.AlreadyFinalized`. :return bytes: The message digest as bytes. -- cgit v1.2.3 From e9d64d78b240d7e8c55ed6e04b0387e6666a6038 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 10:28:01 -0800 Subject: Explain ways in which we can make our docs stronger --- docs/contributing.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index 3b301842..98578ee2 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -122,6 +122,18 @@ So, specifically: * No blank line at the end. * Use Sphinx parameter/attribute documentation `syntax`_. +Because of the inherit challenges in implementing correct cryptographic +systems, we want to make our documentation point people in the right directions +as much as possible. To that end: + +* When documenting a generic interface, use a strong algorithm in examples. + (e.g. when showing a hashing example, don't use + :class:`cryptography.hazmat.primitives.hashes.MD5`) +* When giving perscriptive advice, always provide references and supporting + material. +* When there is disagreement about legitimate cryptographic experts, represent + both sides of the argument and describe the tradeoffs clearly. + When documenting a new module in the ``hazmat`` package, its documentation should begin with the "Hazardous Materials" warning: -- cgit v1.2.3 From 9480129db921e84253d3b2a8c8e8becb5f8934b3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 10:33:01 -0800 Subject: Describe that hashes get real broken over time --- docs/hazmat/primitives/cryptographic-hashes.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 20fa23cf..e7b4f2d6 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -27,6 +27,12 @@ Message Digests >>> digest.finalize() 'l\xa1=R\xcap\xc8\x83\xe0\xf0\xbb\x10\x1eBZ\x89\xe8bM\xe5\x1d\xb2\xd29%\x93\xafj\x84\x11\x80\x90' + Keep in mind that attacks against cryptographic hashes only get stronger + with time, and that often algorithms that were once thought to be strong, + become broken. Because of this it's important to include a plan for + upgrading the hash algorithm you use over time. For more information, see + `Lifetimes of cryptographic hash functions`_. + .. method:: update(data) :param bytes data: The bytes you wish to hash. @@ -109,3 +115,6 @@ MD5 MD5 is a deprecated cryptographic hash function. It has a 128-bit message digest and has practical known collision attacks. + + +.. _`Lifetimes of cryptographic hash functions`: http://valerieaurora.org/hash.html -- cgit v1.2.3 From 11e8cc7cf05967f203d5e7084756ccc28e43bdf7 Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 13 Nov 2013 10:37:47 -0800 Subject: Import AlreadyFinalized instead of exceptions. --- cryptography/hazmat/primitives/hashes.py | 6 +++--- tests/hazmat/primitives/test_hashes.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index f85d36a0..adf64d30 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -15,7 +15,7 @@ from __future__ import absolute_import, division, print_function import six -from cryptography import exceptions +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces @@ -39,14 +39,14 @@ class Hash(object): def update(self, data): if self._ctx is None: - raise exceptions.AlreadyFinalized() + raise AlreadyFinalized() if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") self._ctx.update(data) def copy(self): if self._ctx is None: - raise exceptions.AlreadyFinalized() + raise AlreadyFinalized() return Hash( self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index a5c440b8..4c644603 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -19,7 +19,7 @@ import pytest import six -from cryptography import exceptions +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.bindings import _default_backend from cryptography.hazmat.primitives import hashes @@ -56,10 +56,10 @@ class TestHashContext(object): h = hashes.Hash(hashes.SHA1()) h.finalize() - with pytest.raises(exceptions.AlreadyFinalized): + with pytest.raises(AlreadyFinalized): h.update(b"foo") - with pytest.raises(exceptions.AlreadyFinalized): + with pytest.raises(AlreadyFinalized): h.copy() -- cgit v1.2.3 From 5cbab0c815681cff4bdbfde151953df2242ee7c9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 11:55:57 -0800 Subject: typo fix --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 98578ee2..108ecb6a 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -129,7 +129,7 @@ as much as possible. To that end: * When documenting a generic interface, use a strong algorithm in examples. (e.g. when showing a hashing example, don't use :class:`cryptography.hazmat.primitives.hashes.MD5`) -* When giving perscriptive advice, always provide references and supporting +* When giving prescriptive advice, always provide references and supporting material. * When there is disagreement about legitimate cryptographic experts, represent both sides of the argument and describe the tradeoffs clearly. -- cgit v1.2.3 From d118c91cc381ce757a6b14f4e4c60505c1cdb48a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 11:56:49 -0800 Subject: Clearer! --- docs/contributing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 108ecb6a..b86faaa1 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -131,8 +131,8 @@ as much as possible. To that end: :class:`cryptography.hazmat.primitives.hashes.MD5`) * When giving prescriptive advice, always provide references and supporting material. -* When there is disagreement about legitimate cryptographic experts, represent - both sides of the argument and describe the tradeoffs clearly. +* When there is real disagreement between cryptographic experts, represent both + sides of the argument and describe the tradeoffs clearly. When documenting a new module in the ``hazmat`` package, its documentation should begin with the "Hazardous Materials" warning: -- cgit v1.2.3 From a659688c5de3c778eb175d0c3eae1db9a2e513a0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 12:54:03 -0800 Subject: typo --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index b86faaa1..8e5b1ced 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -122,7 +122,7 @@ So, specifically: * No blank line at the end. * Use Sphinx parameter/attribute documentation `syntax`_. -Because of the inherit challenges in implementing correct cryptographic +Because of the inherent challenges in implementing correct cryptographic systems, we want to make our documentation point people in the right directions as much as possible. To that end: -- cgit v1.2.3 From 00fb12ae9d453e1c6db6a046ebf1f68000b44377 Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 13 Nov 2013 13:02:44 -0800 Subject: Accidentally less words. --- docs/exceptions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/exceptions.rst b/docs/exceptions.rst index d6c15087..ab1b28fe 100644 --- a/docs/exceptions.rst +++ b/docs/exceptions.rst @@ -5,7 +5,7 @@ Exceptions .. class:: AlreadyFinalized - This is raised when a context is used after being it has been finalized. + This is raised when a context is used after being finalized. .. class:: UnsupportedAlgorithm -- cgit v1.2.3 From 34511c697f6f17915b5fe5a58214bb38d779f4a8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 13:30:30 -0800 Subject: Use AlreadyFinalized for symmetric ciphers --- cryptography/hazmat/primitives/ciphers/base.py | 5 +++-- cryptography/hazmat/primitives/hashes.py | 6 ++++-- docs/hazmat/primitives/symmetric-encryption.rst | 5 +++++ tests/hazmat/primitives/test_block.py | 10 +++++----- tests/hazmat/primitives/test_hashes.py | 3 +++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index 794d0191..0fe11996 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.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces @@ -45,12 +46,12 @@ class _CipherContext(object): def update(self, data): if self._ctx is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") return self._ctx.update(data) def finalize(self): if self._ctx is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") data = self._ctx.finalize() self._ctx = None return data diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py index b8de6c4b..86c9fe2e 100644 --- a/cryptography/hazmat/primitives/hashes.py +++ b/cryptography/hazmat/primitives/hashes.py @@ -39,19 +39,21 @@ class Hash(object): def update(self, data): if self._ctx is None: - raise AlreadyFinalized() + raise AlreadyFinalized("Context was already finalized") if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") self._ctx.update(data) def copy(self): if self._ctx is None: - raise AlreadyFinalized() + raise AlreadyFinalized("Context was already finalized") return Hash( self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized") digest = self._ctx.finalize() self._ctx = None return digest diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 28b143ba..950ea8b0 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -79,6 +79,7 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. :param bytes data: The data you wish to pass into the context. :return bytes: Returns the data that was encrypted or decrypted. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` When the ``Cipher`` was constructed in a mode that turns it into a stream cipher (e.g. @@ -90,6 +91,10 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. :return bytes: Returns the remainder of the data. + Once ``finalize`` is called this object can no longer be used and + :meth:`update` will raise + :class:`~cryptography.exceptions.AlreadyFinalized`. + Algorithms ~~~~~~~~~~ diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 28f34478..938cff36 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -17,7 +17,7 @@ import binascii import pytest -from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.exceptions import UnsupportedAlgorithm, AlreadyFinalized from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, modes @@ -56,16 +56,16 @@ class TestCipherContext(object): encryptor = cipher.encryptor() encryptor.update(b"a" * 16) encryptor.finalize() - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): encryptor.update(b"b" * 16) - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): encryptor.finalize() decryptor = cipher.decryptor() decryptor.update(b"a" * 16) decryptor.finalize() - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): decryptor.update(b"b" * 16) - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): decryptor.finalize() def test_unaligned_block_encryption(self, backend): diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 991caf15..367e764f 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -62,6 +62,9 @@ class TestHashContext(object): with pytest.raises(AlreadyFinalized): h.copy() + with pytest.raises(AlreadyFinalized): + h.finalize() + class TestSHA1(object): test_SHA1 = generate_base_hash_test( -- cgit v1.2.3 From 22c93731006b070a677ed952405d9cf3b8043ab5 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 13:48:47 -0800 Subject: Added .cache/ to the gitignore, it shows up if you have pytest-cache installed --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d187cfe..9b8c49ba 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__/ _build/ .tox/ +.cache/ *.egg-info/ .coverage cffi-*.egg/ -- cgit v1.2.3 From 2cce618311c892aa5a1be2ef899e8ff7a08ae5ef Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 13 Nov 2013 13:49:41 -0800 Subject: Make HMAC methods raise AlreadyFinalized. --- cryptography/hazmat/primitives/hmac.py | 12 +++++++++++- docs/hazmat/primitives/hmac.rst | 14 ++++++++++++-- tests/hazmat/primitives/test_hmac.py | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index 1a67b332..cd0fd813 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -15,6 +15,7 @@ from __future__ import absolute_import, division, print_function import six +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import interfaces @@ -37,11 +38,15 @@ class HMAC(object): self._ctx = ctx def update(self, msg): + if self._ctx is None: + raise AlreadyFinalized() if isinstance(msg, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") self._ctx.update(msg) def copy(self): + if self._ctx is None: + raise AlreadyFinalized() return HMAC( self._key, self.algorithm, @@ -50,4 +55,9 @@ class HMAC(object): ) def finalize(self): - return self._ctx.finalize() + if self._ctx is None: + raise AlreadyFinalized() + + digest = self._ctx.finalize() + self._ctx = None + return digest diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst index bd1a4934..cff2dbf1 100644 --- a/docs/hazmat/primitives/hmac.rst +++ b/docs/hazmat/primitives/hmac.rst @@ -36,15 +36,25 @@ message. .. method:: update(msg) :param bytes msg: The bytes to hash and authenticate. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` .. method:: copy() - :return: a new instance of this object with a copied internal state. + Copy this :class:`HMAC` instance, usually so that we may call + :meth:`finalize` and get an intermediate digest value while we continue + to call :meth:`update` on the original. + + :return: A new instance of :class:`HMAC` which can be updated + and finalized independently of the original instance. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` .. method:: finalize() Finalize the current context and return the message digest as bytes. - Once ``finalize`` is called this object can no longer be used. + Once ``finalize`` is called this object can no longer be used and + :meth:`update`, :meth:`copy`, and :meth:`finalize` will raise + :class:`~cryptography.exceptions.AlreadyFinalized`. :return bytes: The message digest as bytes. + :raises cryptography.exceptions.AlreadyFinalized: diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 4186967a..d17049e3 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -19,6 +19,7 @@ import pytest import six +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import hashes, hmac from .utils import generate_base_hmac_test @@ -49,3 +50,16 @@ class TestHMAC(object): def test_hmac_algorithm_instance(self): with pytest.raises(TypeError): hmac.HMAC(b"key", hashes.SHA1) + + def test_raises_after_finalize(self): + h = hmac.HMAC(b"key", hashes.SHA1()) + h.finalize() + + with pytest.raises(AlreadyFinalized): + h.update(b"foo") + + with pytest.raises(AlreadyFinalized): + h.copy() + + with pytest.raises(AlreadyFinalized): + h.finalize() -- cgit v1.2.3 From 9b70ba37ff66e18b67efd0f7d196becc77763c41 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 13:49:43 -0800 Subject: Also mention finalize --- docs/hazmat/primitives/symmetric-encryption.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 950ea8b0..4ef15459 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -92,7 +92,7 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. :return bytes: Returns the remainder of the data. Once ``finalize`` is called this object can no longer be used and - :meth:`update` will raise + :meth:`update` and :meth:`finalize` will raise :class:`~cryptography.exceptions.AlreadyFinalized`. Algorithms -- cgit v1.2.3 From 272d537b90af00e5e5153f3818aee7ffe1df4f65 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 13 Nov 2013 13:50:02 -0800 Subject: Here too --- docs/hazmat/primitives/cryptographic-hashes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 525fd889..52e87702 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -53,7 +53,7 @@ Message Digests Finalize the current context and return the message digest as bytes. Once ``finalize`` is called this object can no longer be used and - :meth:`update` and :meth:`copy` will raise + :meth:`update`, :meth:`copy`, and :meth:`finalize` will raise :class:`~cryptography.exceptions.AlreadyFinalized`. :return bytes: The message digest as bytes. -- cgit v1.2.3 From ee66145fc79f1ef2840267718f54fd89463c67f5 Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 13 Nov 2013 13:52:55 -0800 Subject: Add a message. --- cryptography/hazmat/primitives/hmac.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py index cd0fd813..1bbe39c7 100644 --- a/cryptography/hazmat/primitives/hmac.py +++ b/cryptography/hazmat/primitives/hmac.py @@ -39,14 +39,14 @@ class HMAC(object): def update(self, msg): if self._ctx is None: - raise AlreadyFinalized() + raise AlreadyFinalized("Context was already finalized") if isinstance(msg, six.text_type): raise TypeError("Unicode-objects must be encoded before hashing") self._ctx.update(msg) def copy(self): if self._ctx is None: - raise AlreadyFinalized() + raise AlreadyFinalized("Context was already finalized") return HMAC( self._key, self.algorithm, @@ -56,8 +56,7 @@ class HMAC(object): def finalize(self): if self._ctx is None: - raise AlreadyFinalized() - + raise AlreadyFinalized("Context was already finalized") digest = self._ctx.finalize() self._ctx = None return digest -- cgit v1.2.3 From 0a394df31c4165d0230843ebea2717b3cd3caafa Mon Sep 17 00:00:00 2001 From: David Reid Date: Fri, 15 Nov 2013 16:19:50 -0800 Subject: Implement and document an interface for cipher algorithms --- .../hazmat/primitives/ciphers/algorithms.py | 8 +++++++ cryptography/hazmat/primitives/ciphers/base.py | 3 +++ cryptography/hazmat/primitives/interfaces.py | 14 ++++++++++++ docs/hazmat/primitives/interfaces.rst | 26 ++++++++++++++++++++-- tests/hazmat/bindings/test_openssl.py | 12 +++++----- tests/hazmat/primitives/test_block.py | 12 +++++++++- 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index c135f563..1ed487b6 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -13,7 +13,10 @@ from __future__ import absolute_import, division, print_function +from cryptography.hazmat.primitives import interfaces + +@interfaces.register(interfaces.CipherAlgorithm) class AES(object): name = "AES" block_size = 128 @@ -33,6 +36,7 @@ class AES(object): return len(self.key) * 8 +@interfaces.register(interfaces.CipherAlgorithm) class Camellia(object): name = "camellia" block_size = 128 @@ -52,6 +56,7 @@ class Camellia(object): return len(self.key) * 8 +@interfaces.register(interfaces.CipherAlgorithm) class TripleDES(object): name = "3DES" block_size = 64 @@ -75,6 +80,7 @@ class TripleDES(object): return len(self.key) * 8 +@interfaces.register(interfaces.CipherAlgorithm) class Blowfish(object): name = "Blowfish" block_size = 64 @@ -94,6 +100,7 @@ class Blowfish(object): return len(self.key) * 8 +@interfaces.register(interfaces.CipherAlgorithm) class CAST5(object): name = "CAST5" block_size = 64 @@ -113,6 +120,7 @@ class CAST5(object): return len(self.key) * 8 +@interfaces.register(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 0fe11996..78bf7e0c 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -24,6 +24,9 @@ class Cipher(object): _default_backend as backend, ) + if not isinstance(algorithm, interfaces.CipherAlgorithm): + raise TypeError("Expected interface of interfaces.CipherAlgorithm") + self.algorithm = algorithm self.mode = mode self._backend = backend diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py index 67dbe6fa..bbbb266c 100644 --- a/cryptography/hazmat/primitives/interfaces.py +++ b/cryptography/hazmat/primitives/interfaces.py @@ -25,6 +25,20 @@ def register(iface): return register_decorator +class CipherAlgorithm(six.with_metaclass(abc.ABCMeta)): + @abc.abstractproperty + def name(self): + """ + A string naming this mode. (e.g. AES, Camellia) + """ + + @abc.abstractproperty + def key_size(self): + """ + The size of the key being used as an integer in bits. (e.g. 128, 256) + """ + + class Mode(six.with_metaclass(abc.ABCMeta)): @abc.abstractproperty def name(self): diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst index 7068316e..11cff51a 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -12,11 +12,33 @@ to document argument and return types. .. _`Abstract Base Classes`: http://docs.python.org/3.2/library/abc.html -Cipher Modes -~~~~~~~~~~~~ +Symmetric Ciphers +~~~~~~~~~~~~~~~~~ .. currentmodule:: cryptography.hazmat.primitives.interfaces + +.. class:: CipherAlgorithm + + A named symmetric encryption algorithm. + + .. attribute:: name + + :type: str + + The standard name for the mode, for example, "AES", "Camellia", or + "Blowfish". + + .. attribute:: key_size + + :type: int + + The number of bits in the key being used. + + +Cipher Modes +------------ + Interfaces used by the symmetric cipher modes described in :ref:`Symmetric Encryption Modes `. diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 241c6411..e4f8dd8b 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -15,16 +15,18 @@ import pytest from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.bindings.openssl.backend import backend, Backend +from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import CBC -class FakeMode(object): +class DummyMode(object): pass -class FakeCipher(object): +@interfaces.register(interfaces.CipherAlgorithm) +class DummyCipher(object): pass @@ -58,12 +60,12 @@ class TestOpenSSL(object): def test_nonexistent_cipher(self): b = Backend() b.register_cipher_adapter( - FakeCipher, - FakeMode, + DummyCipher, + DummyMode, lambda backend, cipher, mode: backend.ffi.NULL ) cipher = Cipher( - FakeCipher(), FakeMode(), backend=b, + DummyCipher(), DummyMode(), backend=b, ) with pytest.raises(UnsupportedAlgorithm): cipher.encryptor() diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 938cff36..963136b9 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -24,6 +24,11 @@ from cryptography.hazmat.primitives.ciphers import ( ) +@interfaces.register(interfaces.CipherAlgorithm) +class DummyCipher(object): + pass + + class TestCipher(object): def test_instantiate_without_backend(self): Cipher( @@ -45,6 +50,11 @@ class TestCipher(object): ) assert isinstance(cipher.decryptor(), interfaces.CipherContext) + def test_instantiate_with_non_algorithm(self): + algorithm = object() + with pytest.raises(TypeError): + Cipher(algorithm, mode=None) + class TestCipherContext(object): def test_use_after_finalize(self, backend): @@ -90,7 +100,7 @@ class TestCipherContext(object): def test_nonexistent_cipher(self, backend): cipher = Cipher( - object(), object(), backend + DummyCipher(), object(), backend ) with pytest.raises(UnsupportedAlgorithm): cipher.encryptor() -- cgit v1.2.3 From 9316f4c54edc24487d75c7bc3cb3490d79e364a3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 15 Nov 2013 16:38:42 -0800 Subject: Fixed some spelling mistakes --- docs/conf.py | 1 + docs/glossary.rst | 2 +- docs/hazmat/primitives/symmetric-encryption.rst | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 77050e72..4cddbe41 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,6 +38,7 @@ extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', 'cryptography-docs', + 'sphinxcontrib.spelling', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/glossary.rst b/docs/glossary.rst index e4fc8283..b6f2d06f 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -27,4 +27,4 @@ Glossary asymmetric cryptography Cryptographic operations where encryption and decryption use different - keys. There are seperate encryption and decryption keys. + keys. There are separate encryption and decryption keys. diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 4ef15459..984fe81d 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -18,7 +18,7 @@ where the encrypter and decrypter both use the same key. Note that symmetric encryption is **not** sufficient for most applications, because it only provides secrecy (an attacker can't see the message) but not authenticity (an attacker can create bogus messages and force the application to decrypt them). -For this reason it is *strongly* reccomended to combine encryption with a +For this reason it is *strongly* recommended to combine encryption with a message authentication code, such as :doc:`HMAC `, in an "encrypt-then-MAC" formulation as `described by Colin Percival`_. @@ -121,10 +121,10 @@ Algorithms .. class:: TripleDES(key) - Triple DES (Data Encryption Standard), sometimes refered to as 3DES, is a - block cipher standardized by NIST. Triple DES has known cryptoanalytic + Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a + block cipher standardized by NIST. Triple DES has known crypto-analytic flaws, however none of them currently enable a practical attack. - Nonetheless, Triples DES is not reccomended for new applications because it + Nonetheless, Triples DES is not recommended for new applications because it is incredibly slow; old applications should consider moving away from it. :param bytes key: The secret key, either ``64``, ``128``, or ``192`` bits -- cgit v1.2.3 From b04080f61d35e147f0e67ae8b009b5860900df82 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 15 Nov 2013 16:39:46 -0800 Subject: Revert this --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 4cddbe41..77050e72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,7 +38,6 @@ extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', 'cryptography-docs', - 'sphinxcontrib.spelling', ] # Add any paths that contain templates here, relative to this directory. -- cgit v1.2.3 From 54e04003c2bc136e27c379441e2407191cd9377b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 15 Nov 2013 16:44:41 -0800 Subject: Two more fixes --- docs/contributing.rst | 2 +- docs/security.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 8e5b1ced..97f31e0b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -132,7 +132,7 @@ as much as possible. To that end: * When giving prescriptive advice, always provide references and supporting material. * When there is real disagreement between cryptographic experts, represent both - sides of the argument and describe the tradeoffs clearly. + sides of the argument and describe the trade-offs clearly. When documenting a new module in the ``hazmat`` package, its documentation should begin with the "Hazardous Materials" warning: diff --git a/docs/security.rst b/docs/security.rst index 36c8e0f7..88959709 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -5,7 +5,7 @@ We take the security of ``cryptography`` seriously. If you believe you've identified a security issue in it, please report it to ``alex.gaynor@gmail.com``. Message may be encrypted with PGP using key fingerprint ``E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084`` (this public -key is available from most commonly-used keyservers). +key is available from most commonly-used key servers). Once you’ve submitted an issue via email, you should receive an acknowledgment within 48 hours, and depending on the action to be taken, you may receive -- cgit v1.2.3 From b317c7a0dd197140b7ef1fd3446941f5b568e645 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 15 Nov 2013 16:45:52 -0800 Subject: Another two --- docs/hazmat/primitives/symmetric-encryption.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 984fe81d..eef359d6 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -14,7 +14,7 @@ Symmetric Encryption Symmetric encryption is a way to encrypt (hide the plaintext value) material -where the encrypter and decrypter both use the same key. Note that symmetric +where the sender and receiver both use the same key. Note that symmetric encryption is **not** sufficient for most applications, because it only provides secrecy (an attacker can't see the message) but not authenticity (an attacker can create bogus messages and force the application to decrypt them). -- cgit v1.2.3 From 144209df8e996b59eee31f9531ce0cbe1baf3a7f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 16 Nov 2013 11:55:12 -0800 Subject: Run pytest in --strict mode so that typso in pytest.mark give errors --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 257275ce..56603da2 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,7 @@ deps = coverage pretend commands = - coverage run --source=cryptography/,tests/ -m pytest + coverage run --source=cryptography/,tests/ -m pytest --strict coverage report -m [testenv:docs] -- cgit v1.2.3 From 601dd098216a3d86a27370717b1cc3371df4c468 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 17 Nov 2013 11:17:59 -0800 Subject: This document is now basically accurate --- docs/architecture.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/architecture.rst b/docs/architecture.rst index 4cf639c2..5ca2c252 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -1,11 +1,6 @@ Architecture ============ -.. warning:: - - Because ``cryptography`` is so young, much of this document is - aspirational, rather than documentation. - ``cryptography`` has three different layers: * ``cryptography``: This package contains higher level recipes, for example -- cgit v1.2.3 From d44d510cc4865957ae9b3d948add0ac1237e8fe8 Mon Sep 17 00:00:00 2001 From: cyli Date: Sun, 17 Nov 2013 16:06:42 -0800 Subject: Simple macros --- cryptography/hazmat/bindings/openssl/ssl.py | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py index 30f40c66..04611309 100644 --- a/cryptography/hazmat/bindings/openssl/ssl.py +++ b/cryptography/hazmat/bindings/openssl/ssl.py @@ -173,7 +173,43 @@ X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *); void SSL_SESSION_free(SSL_SESSION *); """ -MACROS = """ +MACROS = MACROS = """ +long SSL_set_mode(SSL *, long); +long SSL_get_mode(SSL *); + +long SSL_set_options(SSL *, long); +long SSL_get_options(SSL *); + +int SSL_want_read(const SSL *); +int SSL_want_write(const SSL *); + +int SSL_total_renegotiations(const SSL *); + +long SSL_CTX_set_options(SSL_CTX *, long); +long SSL_CTX_get_options(SSL_CTX *); +long SSL_CTX_set_mode(SSL_CTX *, long); +long SSL_CTX_get_mode(SSL_CTX *); +long SSL_CTX_set_session_cache_mode(SSL_CTX *, long); +long SSL_CTX_get_session_cache_mode(SSL_CTX *); +long SSL_CTX_set_tmp_dh(SSL_CTX *, DH *); +long SSL_CTX_add_extra_chain_cert(SSL_CTX *, X509 *); + +/*- These aren't macros these functions are all const X on openssl > 1.0.x -*/ + +/* methods */ +const SSL_METHOD *SSLv3_method(); +const SSL_METHOD *SSLv3_server_method(); +const SSL_METHOD *SSLv3_client_method(); +const SSL_METHOD *TLSv1_method(); +const SSL_METHOD *TLSv1_server_method(); +const SSL_METHOD *TLSv1_client_method(); +const SSL_METHOD *SSLv23_method(); +const SSL_METHOD *SSLv23_server_method(); +const SSL_METHOD *SSLv23_client_method(); + +/*- These aren't macros these arguments are all const X on openssl > 1.0.x -*/ +SSL_CTX *SSL_CTX_new(const SSL_METHOD *); +long SSL_CTX_get_timeout(const SSL_CTX *); """ CUSTOMIZATIONS = """ -- cgit v1.2.3 From 39a044110b191dbf8a42111ae1935dcbf12096f4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 18 Nov 2013 12:28:52 -0600 Subject: de-opaque EVP_CIPHER_CTX a bit --- cryptography/hazmat/bindings/openssl/evp.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cryptography/hazmat/bindings/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py index da54f89d..8cb44610 100644 --- a/cryptography/hazmat/bindings/openssl/evp.py +++ b/cryptography/hazmat/bindings/openssl/evp.py @@ -16,10 +16,13 @@ INCLUDES = """ """ TYPES = """ +typedef ... EVP_CIPHER; typedef struct { + const EVP_CIPHER *cipher; + ENGINE *engine; + int encrypt; ...; } EVP_CIPHER_CTX; -typedef ... EVP_CIPHER; typedef ... EVP_MD; typedef struct env_md_ctx_st EVP_MD_CTX; -- cgit v1.2.3 From c985dbb47be06cbb39ecceba9bfbe70088e10fcf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 18 Nov 2013 14:11:55 -0600 Subject: modify nist loader to support multi-line GCM sections --- tests/test_utils.py | 20 ++++++++++++++++++++ tests/utils.py | 10 +++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 4dede2e7..0d71174b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -347,8 +347,28 @@ def test_load_nist_gcm_vectors(): AAD = Tag = 1665b0f1a0b456e1664cfd3de08ccd PT = + + [Keylen = 128] + [IVlen = 8] + [PTlen = 104] + [AADlen = 0] + [Taglen = 128] + + Count = 0 + Key = 58fab7632bcf10d2bcee58520bf37414 + IV = 3c + CT = 15c4db4cbb451211179d57017f + AAD = + Tag = eae841d4355feeb3f786bc86625f1e5b + FAIL """).splitlines() assert load_nist_vectors(vector_data) == [ + {'aad': b'', + 'iv': b'3c', + 'tag': b'eae841d4355feeb3f786bc86625f1e5b', + 'key': b'58fab7632bcf10d2bcee58520bf37414', + 'ct': b'15c4db4cbb451211179d57017f', + 'fail': True}, {'aad': b'', 'pt': b'', 'iv': b'4e8df20faaf2c8eebe922902', diff --git a/tests/utils.py b/tests/utils.py index 8fa9af92..988a80b0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -40,7 +40,15 @@ def load_nist_vectors(vector_data): # Look for section headers if line.startswith("[") and line.endswith("]"): - section = line[1:-1] + if "=" in line: + # GCM section headers + if "Keylen" in line: + section = line[1:-1] + else: + section += line[1:-1] + else: + # non-GCM section headers + section = line[1:-1] continue if line.strip() == "FAIL": -- cgit v1.2.3 From dcf62db81ad60b3591ae6d83dce43c311a347ac2 Mon Sep 17 00:00:00 2001 From: David Reid Date: Mon, 18 Nov 2013 13:02:00 -0800 Subject: Move interfaces.register to utils.register_interface in preparation for more interface modules. --- cryptography/hazmat/bindings/openssl/backend.py | 7 ++++--- .../hazmat/primitives/ciphers/algorithms.py | 13 +++++++------ cryptography/hazmat/primitives/ciphers/base.py | 3 ++- cryptography/hazmat/primitives/ciphers/modes.py | 19 ++++++++++--------- cryptography/hazmat/primitives/hashes.py | 19 ++++++++++--------- cryptography/hazmat/primitives/hmac.py | 3 ++- cryptography/hazmat/primitives/interfaces.py | 7 ------- cryptography/hazmat/primitives/padding.py | 5 +++-- cryptography/utils.py | 21 +++++++++++++++++++++ tests/hazmat/bindings/test_openssl.py | 3 ++- tests/hazmat/primitives/test_block.py | 3 ++- 11 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 cryptography/utils.py diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 844e175f..92cd3868 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -18,6 +18,7 @@ import sys import cffi +from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers.algorithms import ( @@ -196,7 +197,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 +268,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 +311,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/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 -- cgit v1.2.3 From 749ac5b6f95fdc1f09bdbefdf7744c43606b6573 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 18 Nov 2013 18:12:41 -0600 Subject: simplify nist loader to completely ignore sections --- tests/test_utils.py | 52 ++++++++++++++++++++++++++-------------------------- tests/utils.py | 40 +++++++++++----------------------------- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 0d71174b..5c58fd76 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -364,11 +364,29 @@ def test_load_nist_gcm_vectors(): """).splitlines() assert load_nist_vectors(vector_data) == [ {'aad': b'', - 'iv': b'3c', - 'tag': b'eae841d4355feeb3f786bc86625f1e5b', - 'key': b'58fab7632bcf10d2bcee58520bf37414', - 'ct': b'15c4db4cbb451211179d57017f', + 'pt': b'', + 'iv': b'3c819d9a9bed087615030b65', + 'tag': b'250327c674aaf477aef2675748cf6971', + 'key': b'11754cd72aec309bf52f7687212e8957', + 'ct': b''}, + {'aad': b'', + 'pt': b'', + 'iv': b'794ec588176c703d3d2a7a07', + 'tag': b'b6e6f197168f5049aeda32dafbdaeb', + 'key': b'272f16edb81a7abbea887357a58c1917', + 'ct': b''}, + {'aad': b'', + 'iv': b'907763b19b9b4ab6bd4f0281', + 'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf', + 'key': b'a49a5e26a2f8cb63d05546c2a62f5343', + 'ct': b'', 'fail': True}, + {'aad': b'e98e9d9c618e46fef32660976f854ee3', + 'pt': b'd1448fa852b84408e2dad8381f363de7', + 'iv': b'9549e4ba69a61cad7856efc1', + 'tag': b'd72da7f5c6cf0bca7242c71835809449', + 'key': b'5c1155084cc0ede76b3bc22e9f7574ef', + 'ct': b'f78b60ca125218493bea1c50a2e12ef4'}, {'aad': b'', 'pt': b'', 'iv': b'4e8df20faaf2c8eebe922902', @@ -394,27 +412,9 @@ def test_load_nist_gcm_vectors(): 'key': b'fd52925f39546b4c55ffb6b20c59898c', 'ct': b''}, {'aad': b'', - 'pt': b'', - 'iv': b'3c819d9a9bed087615030b65', - 'tag': b'250327c674aaf477aef2675748cf6971', - 'key': b'11754cd72aec309bf52f7687212e8957', - 'ct': b''}, - {'aad': b'', - 'pt': b'', - 'iv': b'794ec588176c703d3d2a7a07', - 'tag': b'b6e6f197168f5049aeda32dafbdaeb', - 'key': b'272f16edb81a7abbea887357a58c1917', - 'ct': b''}, - {'aad': b'', - 'iv': b'907763b19b9b4ab6bd4f0281', - 'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf', - 'key': b'a49a5e26a2f8cb63d05546c2a62f5343', - 'ct': b'', + 'iv': b'3c', + 'tag': b'eae841d4355feeb3f786bc86625f1e5b', + 'key': b'58fab7632bcf10d2bcee58520bf37414', + 'ct': b'15c4db4cbb451211179d57017f', 'fail': True}, - {'aad': b'e98e9d9c618e46fef32660976f854ee3', - 'pt': b'd1448fa852b84408e2dad8381f363de7', - 'iv': b'9549e4ba69a61cad7856efc1', - 'tag': b'd72da7f5c6cf0bca7242c71835809449', - 'key': b'5c1155084cc0ede76b3bc22e9f7574ef', - 'ct': b'f78b60ca125218493bea1c50a2e12ef4'}, ] diff --git a/tests/utils.py b/tests/utils.py index 988a80b0..94f97d59 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -23,36 +23,19 @@ def load_vectors_from_file(filename, loader): def load_nist_vectors(vector_data): - section = None - count = None - data = {} + test_data = None + data = [] for line in vector_data: line = line.strip() - # Blank lines are ignored - if not line: - continue - - # Lines starting with # are comments - if line.startswith("#"): - continue - - # Look for section headers - if line.startswith("[") and line.endswith("]"): - if "=" in line: - # GCM section headers - if "Keylen" in line: - section = line[1:-1] - else: - section += line[1:-1] - else: - # non-GCM section headers - section = line[1:-1] + # Blank lines, comments, and section headers are ignored + if not line or line.startswith("#") or (line.startswith("[") + and line.endswith("]")): continue if line.strip() == "FAIL": - data[section, count]["fail"] = True + test_data["fail"] = True continue # Build our data using a simple Key = Value format @@ -60,16 +43,15 @@ def load_nist_vectors(vector_data): # COUNT is a special token that indicates a new block of data if name.upper() == "COUNT": - count = value - data[section, count] = {} + test_data = {} + data.append(test_data) + continue # For all other tokens we simply want the name, value stored in # the dictionary else: - data[section, count][name.lower()] = value.encode("ascii") + test_data[name.lower()] = value.encode("ascii") - # We want to test only for a particular operation, we sort them for the - # benefit of the tests of this function. - return [v for k, v in sorted(data.items(), key=lambda kv: kv[0])] + return data def load_cryptrec_vectors(vector_data): -- cgit v1.2.3