-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ENH: Order
_generate_notebooks
output by datetime (#33)
* ENH: Order `generate_*` output by timestamp * TST: Make `TestGenerateNotebooks` strict on yielded order * ENH: Incorporate memoization into `single_password_crypto_factory` * TST: Add `memoized_single_arg` test
- Loading branch information
1 parent
495ab66
commit 99b8455
Showing
4 changed files
with
174 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,83 @@ | ||
""" | ||
Tests for notebook encryption utilities. | ||
""" | ||
from unittest import TestCase | ||
|
||
from cryptography.fernet import Fernet | ||
|
||
from ..crypto import ( | ||
derive_fallback_fernet_keys, | ||
FallbackCrypto, | ||
FernetEncryption, | ||
memoize_single_arg, | ||
NoEncryption, | ||
single_password_crypto_factory, | ||
) | ||
|
||
|
||
def test_fernet_derivation(): | ||
pws = [u'currentpassword', u'oldpassword', None] | ||
class TestEncryption(TestCase): | ||
|
||
def test_fernet_derivation(self): | ||
pws = [u'currentpassword', u'oldpassword', None] | ||
|
||
# This must be Unicode, so we use the `u` prefix to support py2. | ||
user_id = u'4e322fa200fffd0001000001' | ||
|
||
current_crypto = single_password_crypto_factory(pws[0])(user_id) | ||
old_crypto = single_password_crypto_factory(pws[1])(user_id) | ||
|
||
def make_single_key_crypto(key): | ||
if key is None: | ||
return NoEncryption() | ||
return FernetEncryption(Fernet(key.encode('ascii'))) | ||
|
||
multi_fernet_crypto = FallbackCrypto( | ||
[make_single_key_crypto(k) | ||
for k in derive_fallback_fernet_keys(pws, user_id)] | ||
) | ||
|
||
# This must be Unicode, so we use the `u` prefix to support py2. | ||
user_id = u'4e322fa200fffd0001000001' | ||
data = b'ayy lmao' | ||
|
||
current_crypto = single_password_crypto_factory(pws[0])(user_id) | ||
old_crypto = single_password_crypto_factory(pws[1])(user_id) | ||
# Data encrypted with the current key. | ||
encrypted_data_current = current_crypto.encrypt(data) | ||
self.assertNotEqual(encrypted_data_current, data) | ||
self.assertEqual(current_crypto.decrypt(encrypted_data_current), data) | ||
|
||
def make_single_key_crypto(key): | ||
if key is None: | ||
return NoEncryption() | ||
return FernetEncryption(Fernet(key.encode('ascii'))) | ||
# Data encrypted with the old key. | ||
encrypted_data_old = old_crypto.encrypt(data) | ||
self.assertNotEqual(encrypted_data_current, data) | ||
self.assertEqual(old_crypto.decrypt(encrypted_data_old), data) | ||
|
||
multi_fernet_crypto = FallbackCrypto( | ||
[make_single_key_crypto(k) | ||
for k in derive_fallback_fernet_keys(pws, user_id)] | ||
) | ||
# The single fernet with the first key should be able to decrypt the | ||
# multi-fernet's encrypted data. | ||
self.assertEqual( | ||
current_crypto.decrypt(multi_fernet_crypto.encrypt(data)), | ||
data | ||
) | ||
|
||
data = b'ayy lmao' | ||
# Multi should be able decrypt anything encrypted with either key. | ||
self.assertEqual(multi_fernet_crypto.decrypt(encrypted_data_current), | ||
data) | ||
self.assertEqual(multi_fernet_crypto.decrypt(encrypted_data_old), data) | ||
|
||
# Data encrypted with the current key. | ||
encrypted_data_current = current_crypto.encrypt(data) | ||
assert encrypted_data_current != data | ||
assert current_crypto.decrypt(encrypted_data_current) == data | ||
# Unencrypted data should be returned unchanged. | ||
self.assertEqual(multi_fernet_crypto.decrypt(data), data) | ||
|
||
# Data encrypted with the old key. | ||
encrypted_data_old = old_crypto.encrypt(data) | ||
assert encrypted_data_current != data | ||
assert old_crypto.decrypt(encrypted_data_old) == data | ||
def test_memoize_single_arg(self): | ||
full_calls = [] | ||
|
||
# The single fernet with the first key should be able to decrypt the | ||
# multi-fernet's encrypted data. | ||
@memoize_single_arg | ||
def mock_factory(user_id): | ||
full_calls.append(user_id) | ||
return u'crypto' + user_id | ||
|
||
assert current_crypto.decrypt(multi_fernet_crypto.encrypt(data)) == data | ||
calls_to_make = [u'1', u'2', u'3', u'2', u'1'] | ||
expected_results = [u'crypto' + user_id for user_id in calls_to_make] | ||
expected_full_calls = [u'1', u'2', u'3'] | ||
|
||
# Multi should be able decrypt anything encrypted with either key. | ||
assert multi_fernet_crypto.decrypt(encrypted_data_current) == data | ||
assert multi_fernet_crypto.decrypt(encrypted_data_old) == data | ||
results = [] | ||
for user_id in calls_to_make: | ||
results.append(mock_factory(user_id)) | ||
|
||
# Unencrypted data should be returned unchanged. | ||
assert multi_fernet_crypto.decrypt(data) == data | ||
self.assertEqual(results, expected_results) | ||
self.assertEqual(full_calls, expected_full_calls) |
Oops, something went wrong.