From df8e11b95d479bf64e224bf73e4b7ac6743bc471 Mon Sep 17 00:00:00 2001 From: maxmelamed <50888194+maxmelamed@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:42:35 -0400 Subject: [PATCH] Add support for extract_timestamp in MultiFernet (#11427) Co-authored-by: Max Melamed --- CHANGELOG.rst | 2 ++ src/cryptography/fernet.py | 8 ++++++++ tests/test_fernet.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9c7119c23..9110fb78a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,8 @@ Changelog * Enforce the :rfc:`5280` requirement that extended key usage extensions must not be empty. +* Added support for timestamp extraction to the + :class:`~cryptography.fernet.MultiFernet` class. .. _v43-0-0: diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index 35ce1131a..868ecb277 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -213,3 +213,11 @@ class MultiFernet: except InvalidToken: pass raise InvalidToken + + def extract_timestamp(self, msg: bytes | str) -> int: + for f in self._fernets: + try: + return f.extract_timestamp(msg) + except InvalidToken: + pass + raise InvalidToken diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 7ebab3e59..9e8b71f35 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -277,3 +277,34 @@ class TestMultiFernet: with pytest.raises(InvalidToken): mf2.rotate(mf1.encrypt(b"abc")) + + def test_extract_timestamp_first_fernet_valid_token(self, backend): + f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + mf1 = MultiFernet([f1]) + current_time = 1526138327 + token = mf1.encrypt_at_time(b"encrypt me", current_time) + assert mf1.extract_timestamp(token) == current_time + + def test_extract_timestamp_second_fernet_valid_token(self, backend): + f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + f2 = Fernet(base64.urlsafe_b64encode(b"\x01" * 32), backend=backend) + mf1 = MultiFernet([f1, f2]) + current_time = 1526138327 + token = f2.encrypt_at_time(b"encrypt me", current_time) + assert mf1.extract_timestamp(token) == current_time + + def test_extract_timestamp_invalid_token(self, backend): + f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + mf1 = MultiFernet([f1]) + with pytest.raises(InvalidToken): + mf1.extract_timestamp(b"nonsensetoken") + with pytest.raises(InvalidToken): + mf1.extract_timestamp(b"\x80abc") + with pytest.raises(InvalidToken): + mf1.extract_timestamp(b"\x00") + with pytest.raises(InvalidToken): + mf1.extract_timestamp("nonsensetoken") + with pytest.raises(InvalidToken): + mf1.extract_timestamp("abc") + with pytest.raises(InvalidToken): + mf1.extract_timestamp("")