Add tests for the encryption
Check that: - Password is not stored in plain text in Redis; - The token returned has the expected format; - The key returned is indeed the decryption key; - API backwards compatibility is maintained: passwords stored in plain text can be retrieved via the original URL token. `test_returned_token_format` superseeds `test_set_password`, which was only validating the key length. f
This commit is contained in:
parent
dc6054f09c
commit
e4f5aed4fa
1 changed files with 38 additions and 5 deletions
43
tests.py
43
tests.py
|
@ -1,7 +1,9 @@
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
import uuid
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
from werkzeug.exceptions import BadRequest
|
from werkzeug.exceptions import BadRequest
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
|
@ -12,11 +14,6 @@ __author__ = 'davedash'
|
||||||
|
|
||||||
class SnapPassTestCase(TestCase):
|
class SnapPassTestCase(TestCase):
|
||||||
|
|
||||||
def test_set_password(self):
|
|
||||||
"""Ensure we return a 32-bit key."""
|
|
||||||
key = snappass.set_password("foo", 30)
|
|
||||||
self.assertEqual(32, len(key))
|
|
||||||
|
|
||||||
def test_get_password(self):
|
def test_get_password(self):
|
||||||
password = "melatonin overdose 1337!$"
|
password = "melatonin overdose 1337!$"
|
||||||
key = snappass.set_password(password, 30)
|
key = snappass.set_password(password, 30)
|
||||||
|
@ -24,6 +21,42 @@ class SnapPassTestCase(TestCase):
|
||||||
# Assert that we can't look this up a second time.
|
# Assert that we can't look this up a second time.
|
||||||
self.assertEqual(None, snappass.get_password(key))
|
self.assertEqual(None, snappass.get_password(key))
|
||||||
|
|
||||||
|
def test_password_is_not_stored_in_plaintext(self):
|
||||||
|
password = "trustno1"
|
||||||
|
token = snappass.set_password(password, 30)
|
||||||
|
redis_key = token.split(snappass.TOKEN_SEPARATOR)[0]
|
||||||
|
stored_password_text = snappass.redis_client.get(redis_key).decode('utf-8')
|
||||||
|
self.assertFalse(password in stored_password_text)
|
||||||
|
|
||||||
|
def test_returned_token_format(self):
|
||||||
|
password = "trustsome1"
|
||||||
|
token = snappass.set_password(password, 30)
|
||||||
|
token_fragments = token.split(snappass.TOKEN_SEPARATOR)
|
||||||
|
self.assertEqual(2, len(token_fragments))
|
||||||
|
redis_key, encryption_key = token_fragments
|
||||||
|
self.assertEqual(32, len(redis_key))
|
||||||
|
try:
|
||||||
|
Fernet(encryption_key.encode('utf-8'))
|
||||||
|
except ValueError:
|
||||||
|
self.fail('the encryption key is not valid')
|
||||||
|
|
||||||
|
def test_encryption_key_is_returned(self):
|
||||||
|
password = "trustany1"
|
||||||
|
token = snappass.set_password(password, 30)
|
||||||
|
token_fragments = token.split(snappass.TOKEN_SEPARATOR)
|
||||||
|
redis_key, encryption_key = token_fragments
|
||||||
|
stored_password = snappass.redis_client.get(redis_key)
|
||||||
|
fernet = Fernet(encryption_key.encode('utf-8'))
|
||||||
|
decrypted_password = fernet.decrypt(stored_password).decode('utf-8')
|
||||||
|
self.assertEqual(password, decrypted_password)
|
||||||
|
|
||||||
|
def test_unencrypted_passwords_still_work(self):
|
||||||
|
unencrypted_password = "trustevery1"
|
||||||
|
storage_key = uuid.uuid4().hex
|
||||||
|
snappass.redis_client.setex(storage_key, 30, unencrypted_password)
|
||||||
|
retrieved_password = snappass.get_password(storage_key)
|
||||||
|
self.assertEqual(unencrypted_password, retrieved_password)
|
||||||
|
|
||||||
def test_password_is_decoded(self):
|
def test_password_is_decoded(self):
|
||||||
password = "correct horse battery staple"
|
password = "correct horse battery staple"
|
||||||
key = snappass.set_password(password, 30)
|
key = snappass.set_password(password, 30)
|
||||||
|
|
Loading…
Reference in a new issue