"""Tests for the real X25519 + AES-GCM crypto implementation.""" import pytest from neotalk.infra.crypto.x25519_crypto import X25519Crypto def test_two_parties_derive_the_same_shared_key(): # Given two independent key pairs alice = X25519Crypto() bob = X25519Crypto() # When each derives the shared key from the other's public key alice_key = alice.derive_shared_key(bob.public_key_bytes()) bob_key = bob.derive_shared_key(alice.public_key_bytes()) # Then both reach the same 256-bit key assert alice_key == bob_key assert len(alice_key) == 32 def test_encrypt_then_decrypt_round_trips(): # Given a shared key between two parties alice = X25519Crypto() bob = X25519Crypto() key = alice.derive_shared_key(bob.public_key_bytes()) # When Alice encrypts and Bob decrypts ciphertext = alice.encrypt(key, b"secret message") plaintext = bob.decrypt(bob.derive_shared_key(alice.public_key_bytes()), ciphertext) # Then the plaintext is recovered assert plaintext == b"secret message" def test_ciphertext_differs_each_time(): # Given a key and a message crypto = X25519Crypto() peer = X25519Crypto() key = crypto.derive_shared_key(peer.public_key_bytes()) # When encrypting the same plaintext twice first = crypto.encrypt(key, b"same") second = crypto.encrypt(key, b"same") # Then the random nonce makes the ciphertexts differ assert first != second def test_tampered_ciphertext_is_rejected(): # Given a valid ciphertext crypto = X25519Crypto() peer = X25519Crypto() key = crypto.derive_shared_key(peer.public_key_bytes()) ciphertext = bytearray(crypto.encrypt(key, b"secret")) # When a byte is flipped ciphertext[-1] ^= 0x01 # Then AES-GCM authentication fails with pytest.raises(Exception): # noqa: B017 - InvalidTag from cryptography crypto.decrypt(key, bytes(ciphertext))