diff options
author | Chris Wolfe <chriswwolfe@gmail.com> | 2017-10-18 14:23:53 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2017-10-19 03:23:53 +0800 |
commit | af6f9900647c36224130270dab385d323ff7534d (patch) | |
tree | 68fae22e5533ed8c5fe00b34076f2beaf74e67f5 /tests | |
parent | a0022ead7b986def1d01b8e8b468bcb3b5785c82 (diff) | |
download | cryptography-af6f9900647c36224130270dab385d323ff7534d.tar.gz cryptography-af6f9900647c36224130270dab385d323ff7534d.tar.bz2 cryptography-af6f9900647c36224130270dab385d323ff7534d.zip |
Add Multifernet.rotate method (#3979)
* add rotate method
* add some more tests for the failure modes
* start adding some documentation for the rotate method
* operate on a single token at a time, leave lists to the caller
* add versionadded
add versionadded, drop rotate from class doctest
* give rotate a doctest
* single level, not aligned
* add changelog for mf.rotate
* show that, once rotated, the old fernet instance can no longer decrypt the token
* add the instead of just the how
* update docs to reflect removal of ttl from rotate
* update tests
* refactor internal methods so that we can extract the timestamp
* implement rotate
* update wordlist (case sensitive?)
* lints
* consistent naming
* get_token_data/get_unverified_token_data -> better name
* doc changes
* use the static method, do not treat as imethod
* move up to MultiFernet docs
* add to authors
* alter wording
* monkeypatch time to make it less possible for the test to pass simply due to calls occuring in less than one second
* set the time after encryption to make sure that the time is preserved as part of re-encryption
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_fernet.py | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/tests/test_fernet.py b/tests/test_fernet.py index dbce44fb..6558d11b 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -6,6 +6,7 @@ from __future__ import absolute_import, division, print_function import base64 import calendar +import datetime import json import os import time @@ -156,3 +157,55 @@ 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" + mf1_ciphertext = mf1.encrypt(plaintext) + + later = datetime.datetime.now() + datetime.timedelta(minutes=5) + later_time = time.mktime(later.timetuple()) + monkeypatch.setattr(time, "time", lambda: later_time) + + original_time, _ = Fernet._get_unverified_token_data(mf1_ciphertext) + rotated_time, _ = Fernet._get_unverified_token_data( + mf2.rotate(mf1_ciphertext) + ) + + assert later_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")) |