infrasynth-backend-kit/tests/test_shared/test_crypto.py
2026-08-28 14:38:47 -05:00

92 lines
3.2 KiB
Python

import pytest
from cryptography.fernet import Fernet
from infrasynth.shared.crypto import decrypt, encrypt, generate_key, rotate_keys
class TestEncryptDecrypt:
def test_roundtrip(self):
token = encrypt("hello-world")
assert decrypt(token) == "hello-world"
def test_different_plaintexts(self):
for text in ["a", "hello", "data with spaces", "12345", ""]:
assert decrypt(encrypt(text)) == text
def test_encrypted_values_differ(self):
t1 = encrypt("same")
t2 = encrypt("same")
assert t1 != t2
def test_decrypt_invalid_token(self):
with pytest.raises(ValueError, match="Invalid Fernet token"):
decrypt("invalid-token-here")
def test_decrypt_garbage(self):
with pytest.raises(ValueError, match="Invalid Fernet token"):
decrypt("AAAA")
def test_decrypt_empty_string(self):
with pytest.raises(ValueError, match="Invalid Fernet token"):
decrypt("")
class TestGenerateKey:
def test_generates_string(self):
key = generate_key()
assert isinstance(key, str)
assert len(key) > 0
def test_keys_are_unique(self):
keys = {generate_key() for _ in range(10)}
assert len(keys) == 10
def test_key_is_valid_fernet_key(self):
key = generate_key()
Fernet(key.encode())
class TestRotateKeys:
def _encrypt_with_key(self, key: str, value: str) -> str:
f = Fernet(key.encode())
return f.encrypt(value.encode()).decode()
def test_rotate_single_token(self):
old_key = generate_key()
new_key = generate_key()
token = self._encrypt_with_key(old_key, "secret-value")
rotated = rotate_keys(old_key, new_key, [token])
assert len(rotated) == 1
assert rotated[0] != token
f = Fernet(new_key.encode())
assert f.decrypt(rotated[0].encode()).decode() == "secret-value"
def test_rotate_multiple_tokens(self):
old_key = generate_key()
new_key = generate_key()
values = [f"value-{i}" for i in range(5)]
tokens = [self._encrypt_with_key(old_key, v) for v in values]
rotated = rotate_keys(old_key, new_key, tokens)
assert len(rotated) == 5
f = Fernet(new_key.encode())
for plaintext, cipher in zip(values, rotated):
assert f.decrypt(cipher.encode()).decode() == plaintext
def test_rotate_with_same_key(self):
key = generate_key()
token = self._encrypt_with_key(key, "persistent")
rotated = rotate_keys(key, key, [token])
assert len(rotated) == 1
assert rotated[0] != token
f = Fernet(key.encode())
assert f.decrypt(rotated[0].encode()).decode() == "persistent"
def test_rotate_preserves_all_values(self):
old_key = generate_key()
new_key = generate_key()
values = ["keep-me-safe", "another-value", "123"]
tokens = [self._encrypt_with_key(old_key, v) for v in values]
rotated = rotate_keys(old_key, new_key, tokens)
f = Fernet(new_key.encode())
for original, cipher in zip(values, rotated):
assert f.decrypt(cipher.encode()).decode() == original