Merge pull request #203 from alex/fernet
[WIP][POC] Implement Fernet
diff --git a/.travis/install.sh b/.travis/install.sh
index fdd7190..4aa3979 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -5,24 +5,8 @@
if [[ "${OPENSSL}" == "0.9.8" ]]; then
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ lucid main"
-fi
-
-if [[ "${TOX_ENV}" == "pypy" ]]; then
- sudo add-apt-repository -y ppa:pypy/ppa
-fi
-
-sudo apt-get -y update
-
-if [[ "${OPENSSL}" == "0.9.8" ]]; then
+ sudo apt-get -y update
sudo apt-get install -y --force-yes libssl-dev/lucid
fi
-if [[ "${TOX_ENV}" == "pypy" ]]; then
- sudo apt-get install -y pypy
-
- # This is required because we need to get rid of the Travis installed PyPy
- # or it'll take precedence over the PPA installed one.
- sudo rm -rf /usr/local/pypy/bin
-fi
-
pip install tox coveralls
diff --git a/cryptography/__about__.py b/cryptography/__about__.py
index 46212bf..54a9dbe 100644
--- a/cryptography/__about__.py
+++ b/cryptography/__about__.py
@@ -26,7 +26,7 @@
__author__ = ("Alex Gaynor, Hynek Schlawack, Donald Stufft, "
"Laurens Van Houtven, Jean-Paul Calderone, Christian Heimes, "
- "and individual contributors.")
+ "Paul Kehrer, and individual contributors.")
__email__ = "cryptography-dev@python.org"
__license__ = "Apache License, Version 2.0"
diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py
index 8b5e344..2a1e118 100644
--- a/cryptography/hazmat/bindings/openssl/binding.py
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -13,9 +13,9 @@
from __future__ import absolute_import, division, print_function
-import sys
-
-import cffi
+from cryptography.hazmat.bindings.utils import (
+ build_ffi, binding_available
+)
_OSX_PRE_INCLUDE = """
#ifdef __APPLE__
@@ -39,20 +39,6 @@
class Binding(object):
"""
OpenSSL API wrapper.
-
- Modules listed in the ``_modules`` listed should have the following
- attributes:
-
- * ``INCLUDES``: A string containg C includes.
- * ``TYPES``: A string containing C declarations for types.
- * ``FUNCTIONS``: A string containing C declarations for functions.
- * ``MACROS``: A string containing C declarations for any macros.
- * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
- can be used to do things like test for a define and provide an
- alternate implementation based on that.
- * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
- library to a list of names which will not be present without the
- condition.
"""
_module_prefix = "cryptography.hazmat.bindings.openssl."
_modules = [
@@ -92,58 +78,10 @@
if cls.ffi is not None and cls.lib is not None:
return
- ffi = cffi.FFI()
- includes = []
- functions = []
- macros = []
- customizations = []
- for name in cls._modules:
- module_name = cls._module_prefix + name
- __import__(module_name)
- module = sys.modules[module_name]
+ cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules,
+ _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE,
+ ["crypto", "ssl"])
- ffi.cdef(module.TYPES)
-
- macros.append(module.MACROS)
- functions.append(module.FUNCTIONS)
- includes.append(module.INCLUDES)
- customizations.append(module.CUSTOMIZATIONS)
-
- # loop over the functions & macros after declaring all the types
- # so we can set interdependent types in different files and still
- # have them all defined before we parse the funcs & macros
- for func in functions:
- ffi.cdef(func)
- for macro in macros:
- ffi.cdef(macro)
-
- # We include functions here so that if we got any of their definitions
- # wrong, the underlying C compiler will explode. In C you are allowed
- # to re-declare a function if it has the same signature. That is:
- # int foo(int);
- # int foo(int);
- # is legal, but the following will fail to compile:
- # int foo(int);
- # int foo(short);
-
- lib = ffi.verify(
- source="\n".join(
- [_OSX_PRE_INCLUDE] +
- includes +
- [_OSX_POST_INCLUDE] +
- functions +
- customizations
- ),
- libraries=["crypto", "ssl"],
- )
-
- for name in cls._modules:
- module_name = cls._module_prefix + name
- module = sys.modules[module_name]
- for condition, names in module.CONDITIONAL_NAMES.items():
- if not getattr(lib, condition):
- for name in names:
- delattr(lib, name)
-
- cls.ffi = ffi
- cls.lib = lib
+ @classmethod
+ def is_available(cls):
+ return binding_available(cls._ensure_ffi_initialized)
diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py
new file mode 100644
index 0000000..9141c15
--- /dev/null
+++ b/cryptography/hazmat/bindings/utils.py
@@ -0,0 +1,96 @@
+# 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 sys
+
+import cffi
+
+
+def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
+ """
+ Modules listed in ``modules`` should have the following attributes:
+
+ * ``INCLUDES``: A string containing C includes.
+ * ``TYPES``: A string containing C declarations for types.
+ * ``FUNCTIONS``: A string containing C declarations for functions.
+ * ``MACROS``: A string containing C declarations for any macros.
+ * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
+ can be used to do things like test for a define and provide an
+ alternate implementation based on that.
+ * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
+ library to a list of names which will not be present without the
+ condition.
+ """
+ ffi = cffi.FFI()
+ includes = []
+ functions = []
+ macros = []
+ customizations = []
+ for name in modules:
+ module_name = module_prefix + name
+ __import__(module_name)
+ module = sys.modules[module_name]
+
+ ffi.cdef(module.TYPES)
+
+ macros.append(module.MACROS)
+ functions.append(module.FUNCTIONS)
+ includes.append(module.INCLUDES)
+ customizations.append(module.CUSTOMIZATIONS)
+
+ # loop over the functions & macros after declaring all the types
+ # so we can set interdependent types in different files and still
+ # have them all defined before we parse the funcs & macros
+ for func in functions:
+ ffi.cdef(func)
+ for macro in macros:
+ ffi.cdef(macro)
+
+ # We include functions here so that if we got any of their definitions
+ # wrong, the underlying C compiler will explode. In C you are allowed
+ # to re-declare a function if it has the same signature. That is:
+ # int foo(int);
+ # int foo(int);
+ # is legal, but the following will fail to compile:
+ # int foo(int);
+ # int foo(short);
+ lib = ffi.verify(
+ source="\n".join(
+ [pre_include] +
+ includes +
+ [post_include] +
+ functions +
+ customizations
+ ),
+ libraries=libraries
+ )
+
+ for name in modules:
+ module_name = module_prefix + name
+ module = sys.modules[module_name]
+ for condition, names in module.CONDITIONAL_NAMES.items():
+ if not getattr(lib, condition):
+ for name in names:
+ delattr(lib, name)
+
+ return ffi, lib
+
+
+def binding_available(initializer):
+ try:
+ initializer()
+ return True
+ except cffi.VerificationError:
+ return False
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index 1da0802..d366e4c 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -25,6 +25,9 @@
if not isinstance(algorithm, interfaces.CipherAlgorithm):
raise TypeError("Expected interface of interfaces.CipherAlgorithm")
+ if mode is not None:
+ mode.validate_for_algorithm(algorithm)
+
self.algorithm = algorithm
self.mode = mode
self._backend = backend
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index ab8501c..739f23d 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -25,11 +25,20 @@
def __init__(self, initialization_vector):
self.initialization_vector = initialization_vector
+ def validate_for_algorithm(self, algorithm):
+ if len(self.initialization_vector) * 8 != algorithm.block_size:
+ raise ValueError("Invalid iv size ({0}) for {1}".format(
+ len(self.initialization_vector), self.name
+ ))
+
@utils.register_interface(interfaces.Mode)
class ECB(object):
name = "ECB"
+ def validate_for_algorithm(self, algorithm):
+ pass
+
@utils.register_interface(interfaces.Mode)
@utils.register_interface(interfaces.ModeWithInitializationVector)
@@ -39,6 +48,12 @@
def __init__(self, initialization_vector):
self.initialization_vector = initialization_vector
+ def validate_for_algorithm(self, algorithm):
+ if len(self.initialization_vector) * 8 != algorithm.block_size:
+ raise ValueError("Invalid iv size ({0}) for {1}".format(
+ len(self.initialization_vector), self.name
+ ))
+
@utils.register_interface(interfaces.Mode)
@utils.register_interface(interfaces.ModeWithInitializationVector)
@@ -48,6 +63,12 @@
def __init__(self, initialization_vector):
self.initialization_vector = initialization_vector
+ def validate_for_algorithm(self, algorithm):
+ if len(self.initialization_vector) * 8 != algorithm.block_size:
+ raise ValueError("Invalid iv size ({0}) for {1}".format(
+ len(self.initialization_vector), self.name
+ ))
+
@utils.register_interface(interfaces.Mode)
@utils.register_interface(interfaces.ModeWithNonce)
@@ -57,6 +78,12 @@
def __init__(self, nonce):
self.nonce = nonce
+ def validate_for_algorithm(self, algorithm):
+ if len(self.nonce) * 8 != algorithm.block_size:
+ raise ValueError("Invalid nonce size ({0}) for {1}".format(
+ len(self.nonce), self.name
+ ))
+
@utils.register_interface(interfaces.Mode)
@utils.register_interface(interfaces.ModeWithInitializationVector)
@@ -65,6 +92,9 @@
name = "GCM"
def __init__(self, initialization_vector, tag=None):
+ # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
+ # to actually construct a bytes object that large, so we don't check
+ # for it
if tag is not None and len(tag) < 4:
raise ValueError(
"Authentication tag must be 4 bytes or longer"
@@ -72,3 +102,6 @@
self.initialization_vector = initialization_vector
self.tag = tag
+
+ def validate_for_algorithm(self, algorithm):
+ pass
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index e87c9ca..7a6bf3e 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -47,6 +47,13 @@
A string naming this mode (e.g. "ECB", "CBC").
"""
+ @abc.abstractmethod
+ def validate_for_algorithm(self, algorithm):
+ """
+ Checks that all the necessary invariants of this (mode, algorithm)
+ combination are met.
+ """
+
class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)):
@abc.abstractproperty
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 63e0a6c..4421fca 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -2,6 +2,7 @@
========
.. glossary::
+ :sorted:
plaintext
User-readable data you care about.
@@ -35,7 +36,7 @@
symmetric or asymmetric. Authentication is necessary for effective
encryption.
- Ciphertext indistinguishability
+ ciphertext indistinguishability
This is a property of encryption systems whereby two encrypted messages
aren't distinguishable without knowing the encryption key. This is
considered a basic, necessary property for a working encryption system.
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
index 809eddf..e2a1759 100644
--- a/docs/hazmat/bindings/index.rst
+++ b/docs/hazmat/bindings/index.rst
@@ -6,7 +6,7 @@
.. currentmodule:: cryptography.hazmat.bindings
``cryptography`` aims to provide low-level CFFI based bindings to multiple
-native C libraries. These provide no automatic initialisation of the library
+native C libraries. These provide no automatic initialization of the library
and may not provide complete wrappers for its API.
Using these functions directly is likely to require you to be careful in
diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst
index b8f94fd..dc5c54f 100644
--- a/docs/hazmat/primitives/hmac.rst
+++ b/docs/hazmat/primitives/hmac.rst
@@ -74,8 +74,11 @@
.. method:: verify(signature)
- Finalize the current context and securely compare digest to ``signature``.
+ Finalize the current context and securely compare digest to
+ ``signature``.
- :param bytes signature: The bytes of the HMAC signature recieved.
+ :param bytes signature: The bytes to compare the current digest
+ against.
:raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
- :raises cryptography.exceptions.InvalidSignature: If signature does not match digest
+ :raises cryptography.exceptions.InvalidSignature: If signature does not
+ match digest
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 361b723..edb24cd 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -67,6 +67,18 @@
The name may be used by a backend to influence the operation of a
cipher in conjunction with the algorithm's name.
+ .. method:: validate_for_algorithm(algorithm)
+
+ :param CipherAlgorithm algorithm:
+
+ Checks that the combination of this mode with the provided algorithm
+ meets any necessary invariants. This should raise an exception if they
+ are not met.
+
+ For example, the :class:`~cryptography.hazmat.primitives.modes.CBC`
+ mode uses this method to check that the provided initialization
+ vector's length matches the block size of the algorithm.
+
.. class:: ModeWithInitializationVector
diff --git a/setup.py b/setup.py
index 1856cad..3202f84 100644
--- a/setup.py
+++ b/setup.py
@@ -10,12 +10,16 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
+
from setuptools import setup, find_packages
+base_dir = os.path.dirname(__file__)
+
about = {}
-with open("cryptography/__about__.py") as fp:
- exec(fp.read(), about)
+with open(os.path.join(base_dir, "cryptography", "__about__.py")) as f:
+ exec(f.read(), about)
CFFI_DEPENDENCY = "cffi>=0.6"
@@ -30,11 +34,16 @@
CFFI_DEPENDENCY,
]
+with open(os.path.join(base_dir, "README.rst")) as f:
+ long_description = f.read()
+
+
setup(
name=about["__title__"],
version=about["__version__"],
description=about["__summary__"],
+ long_description=long_description,
license=about["__license__"],
url=about["__uri__"],
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 22cfbe7..ad39959 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -27,6 +27,9 @@
class DummyMode(object):
name = "dummy-mode"
+ def validate_for_algorithm(self, algorithm):
+ pass
+
@utils.register_interface(interfaces.CipherAlgorithm)
class DummyCipher(object):
diff --git a/tests/hazmat/bindings/test_bindings.py b/tests/hazmat/bindings/test_bindings.py
new file mode 100644
index 0000000..7af1d58
--- /dev/null
+++ b/tests/hazmat/bindings/test_bindings.py
@@ -0,0 +1,32 @@
+# 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 cffi
+
+from cryptography.hazmat.bindings.utils import binding_available
+from cryptography.hazmat.bindings.openssl.binding import Binding
+
+
+def dummy_initializer():
+ ffi = cffi.FFI()
+ ffi.verify(source="#include <fake_header.h>")
+
+
+def test_binding_available():
+ assert binding_available(Binding._ensure_ffi_initialized) is True
+
+
+def test_binding_unavailable():
+ assert binding_available(dummy_initializer) is False
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 31f736a..d1e8505 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -20,3 +20,6 @@
assert binding
assert binding.lib
assert binding.ffi
+
+ def test_is_available(self):
+ assert Binding.is_available() is True
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 30cf1d6..f758ffa 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -35,6 +35,9 @@
class DummyMode(object):
name = "dummy-mode"
+ def validate_for_algorithm(self, algorithm):
+ pass
+
@utils.register_interface(interfaces.CipherAlgorithm)
class DummyCipher(object):
@@ -152,3 +155,37 @@
algorithms.AES,
modes.GCM,
)
+
+
+class TestModeValidation(object):
+ def test_cbc(self, backend):
+ with pytest.raises(ValueError):
+ Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.CBC(b"abc"),
+ backend,
+ )
+
+ def test_ofb(self, backend):
+ with pytest.raises(ValueError):
+ Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.OFB(b"abc"),
+ backend,
+ )
+
+ def test_cfb(self, backend):
+ with pytest.raises(ValueError):
+ Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.CFB(b"abc"),
+ backend,
+ )
+
+ def test_ctr(self, backend):
+ with pytest.raises(ValueError):
+ Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.CTR(b"abc"),
+ backend,
+ )
diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py
index 13ffc3f..ca97fc1 100644
--- a/tests/hazmat/primitives/test_hash_vectors.py
+++ b/tests/hazmat/primitives/test_hash_vectors.py
@@ -24,7 +24,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA1),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA1()),
skip_message="Does not support SHA1",
)
@pytest.mark.hash
@@ -41,7 +41,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA224),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA224()),
skip_message="Does not support SHA224",
)
@pytest.mark.hash
@@ -58,7 +58,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA256),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA256()),
skip_message="Does not support SHA256",
)
@pytest.mark.hash
@@ -75,7 +75,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA384),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA384()),
skip_message="Does not support SHA384",
)
@pytest.mark.hash
@@ -92,7 +92,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA512),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
skip_message="Does not support SHA512",
)
@pytest.mark.hash
@@ -109,7 +109,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160()),
skip_message="Does not support RIPEMD160",
)
@pytest.mark.hash
@@ -130,7 +130,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.Whirlpool),
+ only_if=lambda backend: backend.hash_supported(hashes.Whirlpool()),
skip_message="Does not support Whirlpool",
)
@pytest.mark.hash
@@ -153,7 +153,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.MD5),
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
skip_message="Does not support MD5",
)
@pytest.mark.hash
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index c907ef6..9ca2fee 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -70,7 +70,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA1),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA1()),
skip_message="Does not support SHA1",
)
@pytest.mark.hash
@@ -83,7 +83,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA224),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA224()),
skip_message="Does not support SHA224",
)
@pytest.mark.hash
@@ -96,7 +96,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA256),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA256()),
skip_message="Does not support SHA256",
)
@pytest.mark.hash
@@ -109,7 +109,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA384),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA384()),
skip_message="Does not support SHA384",
)
@pytest.mark.hash
@@ -122,7 +122,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.SHA512),
+ only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
skip_message="Does not support SHA512",
)
@pytest.mark.hash
@@ -135,7 +135,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160()),
skip_message="Does not support RIPEMD160",
)
@pytest.mark.hash
@@ -148,7 +148,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.Whirlpool),
+ only_if=lambda backend: backend.hash_supported(hashes.Whirlpool()),
skip_message="Does not support Whirlpool",
)
@pytest.mark.hash
@@ -161,7 +161,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hash_supported(hashes.MD5),
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
skip_message="Does not support MD5",
)
@pytest.mark.hash
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 04913af..dd9cdaa 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -34,7 +34,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.MD5),
+ only_if=lambda backend: backend.hmac_supported(hashes.MD5()),
skip_message="Does not support MD5",
)
@pytest.mark.hmac
diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py
index c564445..0792080 100644
--- a/tests/hazmat/primitives/test_hmac_vectors.py
+++ b/tests/hazmat/primitives/test_hmac_vectors.py
@@ -22,7 +22,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.MD5),
+ only_if=lambda backend: backend.hmac_supported(hashes.MD5()),
skip_message="Does not support MD5",
)
@pytest.mark.hmac
@@ -38,7 +38,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.SHA1),
+ only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
skip_message="Does not support SHA1",
)
@pytest.mark.hmac
@@ -54,7 +54,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.SHA224),
+ only_if=lambda backend: backend.hmac_supported(hashes.SHA224()),
skip_message="Does not support SHA224",
)
@pytest.mark.hmac
@@ -70,7 +70,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.SHA256),
+ only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
skip_message="Does not support SHA256",
)
@pytest.mark.hmac
@@ -86,7 +86,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.SHA384),
+ only_if=lambda backend: backend.hmac_supported(hashes.SHA384()),
skip_message="Does not support SHA384",
)
@pytest.mark.hmac
@@ -102,7 +102,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.SHA512),
+ only_if=lambda backend: backend.hmac_supported(hashes.SHA512()),
skip_message="Does not support SHA512",
)
@pytest.mark.hmac
@@ -118,7 +118,7 @@
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.RIPEMD160),
+ only_if=lambda backend: backend.hmac_supported(hashes.RIPEMD160()),
skip_message="Does not support RIPEMD160",
)
@pytest.mark.hmac
diff --git a/tests/test_utils.py b/tests/test_utils.py
index c640367..e3e53d6 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -50,7 +50,7 @@
funcargs={"backend": True})
with pytest.raises(pytest.skip.Exception) as exc_info:
check_backend_support(item)
- assert exc_info.value.args[0] == "Nope"
+ assert exc_info.value.args[0] == "Nope (True)"
def test_check_backend_support_no_skip():
diff --git a/tests/utils.py b/tests/utils.py
index beb2ca5..693a0c8 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -28,7 +28,9 @@
supported = item.keywords.get("supported")
if supported and "backend" in item.funcargs:
if not supported.kwargs["only_if"](item.funcargs["backend"]):
- pytest.skip(supported.kwargs["skip_message"])
+ pytest.skip("{0} ({1})".format(
+ supported.kwargs["skip_message"], item.funcargs["backend"]
+ ))
elif supported:
raise ValueError("This mark is only available on methods that take a "
"backend")