diff options
Diffstat (limited to 'tests/test_fernet.py')
| -rw-r--r-- | tests/test_fernet.py | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 0b93f017..da2096fb 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -45,7 +45,7 @@ def test_default_backend(): @pytest.mark.requires_backend_interface(interface=HMACBackend) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( - algorithms.AES("\x00" * 32), modes.CBC("\x00" * 16) + algorithms.AES(b"\x00" * 32), modes.CBC(b"\x00" * 16) ), skip_message="Does not support AES CBC", ) @@ -69,6 +69,10 @@ class TestFernet(object): monkeypatch): f = Fernet(secret.encode("ascii"), backend=backend) current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple()) + payload = f.decrypt_at_time( + token.encode("ascii"), ttl=ttl_sec, current_time=current_time, + ) + assert payload == src.encode("ascii") monkeypatch.setattr(time, "time", lambda: current_time) payload = f.decrypt(token.encode("ascii"), ttl=ttl_sec) assert payload == src.encode("ascii") @@ -77,6 +81,10 @@ class TestFernet(object): def test_invalid(self, secret, token, now, ttl_sec, backend, monkeypatch): f = Fernet(secret.encode("ascii"), backend=backend) current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple()) + with pytest.raises(InvalidToken): + f.decrypt_at_time( + token.encode("ascii"), ttl=ttl_sec, current_time=current_time, + ) monkeypatch.setattr(time, "time", lambda: current_time) with pytest.raises(InvalidToken): f.decrypt(token.encode("ascii"), ttl=ttl_sec) @@ -103,6 +111,17 @@ class TestFernet(object): with pytest.raises(TypeError): f.decrypt(u"") + def test_timestamp_ignored_no_ttl(self, monkeypatch, backend): + f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + pt = b"encrypt me" + token = f.encrypt(pt) + ts = "1985-10-26T01:20:01-07:00" + current_time = calendar.timegm(iso8601.parse_date(ts).utctimetuple()) + assert f.decrypt_at_time( + token, ttl=None, current_time=current_time) == pt + monkeypatch.setattr(time, "time", lambda: current_time) + assert f.decrypt(token, ttl=None) == pt + @pytest.mark.parametrize("message", [b"", b"Abc!", b"\x00\xFF\x00\x80"]) def test_roundtrips(self, message, backend): f = Fernet(Fernet.generate_key(), backend=backend) @@ -112,12 +131,20 @@ class TestFernet(object): with pytest.raises(ValueError): Fernet(base64.urlsafe_b64encode(b"abc"), backend=backend) + def test_extract_timestamp(self, monkeypatch, backend): + f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + current_time = 1526138327 + token = f.encrypt_at_time(b'encrypt me', current_time) + assert f.extract_timestamp(token) == current_time + with pytest.raises(InvalidToken): + f.extract_timestamp(b"nonsensetoken") + @pytest.mark.requires_backend_interface(interface=CipherBackend) @pytest.mark.requires_backend_interface(interface=HMACBackend) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( - algorithms.AES("\x00" * 32), modes.CBC("\x00" * 16) + algorithms.AES(b"\x00" * 32), modes.CBC(b"\x00" * 16) ), skip_message="Does not support AES CBC", ) @@ -147,3 +174,51 @@ class TestMultiFernet(object): def test_non_iterable_argument(self, backend): with pytest.raises(TypeError): MultiFernet(None) + + def test_rotate(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]) + mf2 = MultiFernet([f2, f1]) + + plaintext = b"abc" + mf1_ciphertext = mf1.encrypt(plaintext) + + assert mf2.decrypt(mf1_ciphertext) == plaintext + + rotated = mf2.rotate(mf1_ciphertext) + + assert rotated != mf1_ciphertext + assert mf2.decrypt(rotated) == plaintext + + with pytest.raises(InvalidToken): + mf1.decrypt(rotated) + + def test_rotate_preserves_timestamp(self, backend, monkeypatch): + f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) + f2 = Fernet(base64.urlsafe_b64encode(b"\x01" * 32), backend=backend) + + mf1 = MultiFernet([f1]) + mf2 = MultiFernet([f2, f1]) + + plaintext = b"abc" + original_time = int(time.time()) - 5 * 60 + mf1_ciphertext = mf1.encrypt_at_time(plaintext, original_time) + + rotated_time, _ = Fernet._get_unverified_token_data( + mf2.rotate(mf1_ciphertext) + ) + + assert int(time.time()) != rotated_time + assert original_time == rotated_time + + def test_rotate_decrypt_no_shared_keys(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]) + mf2 = MultiFernet([f2]) + + with pytest.raises(InvalidToken): + mf2.rotate(mf1.encrypt(b"abc")) |
