aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_fernet.py
diff options
context:
space:
mode:
authorChris Wolfe <chriswwolfe@gmail.com>2017-10-18 14:23:53 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2017-10-19 03:23:53 +0800
commitaf6f9900647c36224130270dab385d323ff7534d (patch)
tree68fae22e5533ed8c5fe00b34076f2beaf74e67f5 /tests/test_fernet.py
parenta0022ead7b986def1d01b8e8b468bcb3b5785c82 (diff)
downloadcryptography-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/test_fernet.py')
-rw-r--r--tests/test_fernet.py53
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"))