test_crypto.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from math import log
  2. import time
  3. from django.test import TestCase
  4. from desecapi import crypto
  5. class CryptoTestCase(TestCase):
  6. context = 'desecapi.tests.test_crypto'
  7. def test_retrieved_key_is_reproducible(self):
  8. keys = (crypto.retrieve_key(label='test', context=self.context) for _ in range(2))
  9. self.assertEqual(*keys)
  10. def test_retrieved_key_depends_on_secret(self):
  11. keys = []
  12. for secret in ['abcdefgh', 'hgfedcba']:
  13. with self.settings(SECRET_KEY=secret):
  14. keys.append(crypto.retrieve_key(label='test', context=self.context))
  15. self.assertNotEqual(*keys)
  16. def test_retrieved_key_depends_on_label(self):
  17. keys = (crypto.retrieve_key(label=f'test_{i}', context=self.context) for i in range(2))
  18. self.assertNotEqual(*keys)
  19. def test_retrieved_key_depends_on_context(self):
  20. keys = (crypto.retrieve_key(label='test', context=f'{self.context}_{i}') for i in range(2))
  21. self.assertNotEqual(*keys)
  22. def test_encrypt_has_high_entropy(self):
  23. def entropy(value: str):
  24. result = 0
  25. counts = [value.count(char) for char in set(value)]
  26. for count in counts:
  27. count /= len(value)
  28. result -= count * log(count, 2)
  29. return result * len(value)
  30. ciphertext = crypto.encrypt(b'test', context=self.context)
  31. self.assertGreater(entropy(ciphertext), 100) # arbitrary
  32. def test_encrypt_decrypt(self):
  33. plain = b'test'
  34. ciphertext = crypto.encrypt(plain, context=self.context)
  35. timestamp, decrypted = crypto.decrypt(ciphertext, context=self.context)
  36. self.assertEqual(plain, decrypted)
  37. self.assertTrue(0 <= time.time() - timestamp <= 1)
  38. def test_encrypt_decrypt_raises_on_tampering(self):
  39. ciphertext = crypto.encrypt(b'test', context=self.context)
  40. with self.assertRaises(ValueError):
  41. ciphertext_decoded = ciphertext.decode()
  42. ciphertext_tampered = (ciphertext_decoded[:30] + 'TAMPERBEEF' + ciphertext_decoded[40:]).encode()
  43. crypto.decrypt(ciphertext_tampered, context=self.context)
  44. with self.assertRaises(ValueError):
  45. crypto.decrypt(ciphertext, context=f'{self.context}2')