From d79c74ac6b56e7802f3e3ead948cd3454f55ab95 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 27 Oct 2018 01:14:35 +0200 Subject: [PATCH] Added SHA-512 fallback by default --- CHANGES.rst | 1 + src/itsdangerous/serializer.py | 13 +++++++++++-- src/itsdangerous/timed.py | 5 +++++ tests/test_itsdangerous/test_serializer.py | 4 ++-- tox.ini | 2 +- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4f151a8..ade84c8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Version 1.1.0 Released 2018-10-26 - Change default signing algorithm back to SHA-1. (`#113`_) +- Added a default SHA-512 fallback. - Add support for fallback algorithms during deserialization to support changing the default in the future without breaking existing signatures. (`#113`_) diff --git a/src/itsdangerous/serializer.py b/src/itsdangerous/serializer.py index 42641c4..e8f2e72 100644 --- a/src/itsdangerous/serializer.py +++ b/src/itsdangerous/serializer.py @@ -1,3 +1,5 @@ +import hashlib + from ._compat import text_type from ._json import json from .encoding import want_bytes @@ -57,7 +59,9 @@ class to the constructor as well as keyword arguments as a dict that the constructor. .. versionchanged:: 1.1: - Added support for ``fallback_signers``. + Added support for ``fallback_signers`` and configured a default + SHA-512 fallback. This fallback is for users who used the 1.0 + release which was yanked which had SHA-512 support in it. """ #: If a serializer module or class is not passed to the constructor @@ -70,6 +74,9 @@ class to the constructor as well as keyword arguments as a dict that #: .. versionadded:: 0.14 default_signer = Signer + #: The default fallback signers. + default_fallback_signers = [{"digest_method": hashlib.sha512}] + def __init__( self, secret_key, @@ -90,7 +97,9 @@ def __init__( signer = self.default_signer self.signer = signer self.signer_kwargs = signer_kwargs or {} - self.fallback_signers = fallback_signers or () + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers or ()) + self.fallback_signers = fallback_signers self.serializer_kwargs = serializer_kwargs or {} def load_payload(self, payload, serializer=None): diff --git a/src/itsdangerous/timed.py b/src/itsdangerous/timed.py index b106c5a..4c117e4 100644 --- a/src/itsdangerous/timed.py +++ b/src/itsdangerous/timed.py @@ -132,6 +132,11 @@ def loads(self, s, max_age=None, return_timestamp=False, salt=None): if return_timestamp: return payload, timestamp return payload + # If we get a signature expired it means we could read the + # signature but it's invalid. In that case we do not want to + # try the next signer. + except SignatureExpired: + raise except BadSignature as err: last_exception = err raise last_exception diff --git a/tests/test_itsdangerous/test_serializer.py b/tests/test_itsdangerous/test_serializer.py index 6d7b20a..bbd1ce2 100644 --- a/tests/test_itsdangerous/test_serializer.py +++ b/tests/test_itsdangerous/test_serializer.py @@ -134,12 +134,12 @@ def test_serializer_kwargs(self, serializer_factory): assert serializer.loads(serializer.dumps({(): 1})) == {} def test_fallback_signers(self, serializer_factory, value): - serializer = serializer_factory(signer_kwargs={"digest_method": hashlib.sha512}) + serializer = serializer_factory(signer_kwargs={"digest_method": hashlib.sha256}) signed = serializer.dumps(value) fallback_serializer = serializer_factory( signer_kwargs={"digest_method": hashlib.sha1}, - fallback_signers=[{"digest_method": hashlib.sha512}], + fallback_signers=[{"digest_method": hashlib.sha256}], ) assert fallback_serializer.loads(signed) == value diff --git a/tox.ini b/tox.ini index d64c2c9..48f007f 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ setenv = deps = pytest-cov freezegun -commands = pytest --cov --cov-report= {posargs} +commands = pytest --tb=short --cov --cov-report= {posargs} [testenv:stylecheck] deps = pre-commit