test_crypto.py 2.1 KB

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