test(core): adjust chacha20poly1305 python unit tests
What changed, and why it matters
This commit only changes Python unit tests for the ChaCha20-Poly1305 encryption code in the Trezor firmware test suite. It does not modify the actual cryptographic implementation, device firmware, or any production code. The changes add test cases to verify that decryption correctly requires and validates the authentication tag (MAC). There is no security vulnerability in this commit itself.
No action required. This is a routine test-quality commit. Reviewers may optionally verify that the new tests pass and that the underlying `chacha20poly1305` implementation already enforces the behaviors being tested.
Security signals we found
No production code modified
Test-only change
Adds defensive test coverage for MAC validation during decryption
Fixes an incorrect test method that was encrypting ciphertext instead of decrypting
Evidence from the diff
The diff updates core/tests/test_trezor.crypto.chacha20poly1305.py. It refactors existing tests to apply unhexlify to all vector fields at once, fixes a copy-paste bug in test_chacha20_decrypt (was calling encrypt instead of decrypt), and adds three new test cases: missing expected MAC raises RuntimeError, invalid MAC length raises ValueError, and an incorrect 16-byte MAC raises RuntimeError with ‘Authentication failed.’ These tests exercise the existing chacha20poly1305 wrapper’s behavior but do not change it.
Changed components
core/tests/test_trezor.crypto.chacha20poly1305.pyInspect captured patch +74 / −21
diff --git a/core/tests/test_trezor.crypto.chacha20poly1305.py b/core/tests/test_trezor.crypto.chacha20poly1305.py
index 754f61fd..c1a8f7a2 100644
--- a/core/tests/test_trezor.crypto.chacha20poly1305.py
+++ b/core/tests/test_trezor.crypto.chacha20poly1305.py
@@ -28,34 +28,87 @@ class TestCryptoChaCha20Poly1305(unittest.TestCase):
]
def test_chacha20_encrypt(self):
- for plaintext, _, key, nonce, ciphertext, _ in self.vectors:
- ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
- out = ctx.encrypt(unhexlify(plaintext))
- self.assertEqual(out, unhexlify(ciphertext))
+ for vector in self.vectors:
+ plaintext, _, key, nonce, ciphertext, _ = map(unhexlify, vector)
+
+ ctx = chacha20poly1305(key, nonce)
+ out = ctx.encrypt(plaintext)
+ self.assertEqual(out, ciphertext)
def test_chacha20_decrypt(self):
- for plaintext, _, key, nonce, ciphertext, _ in self.vectors:
- ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
- out = ctx.encrypt(unhexlify(ciphertext))
- self.assertEqual(out, unhexlify(plaintext))
+ for vector in self.vectors:
+ plaintext, _, key, nonce, ciphertext, _ = map(unhexlify, vector)
+ ctx = chacha20poly1305(key, nonce)
+ out = ctx.decrypt(ciphertext)
+ self.assertEqual(out, plaintext)
def test_chacha20poly1305_encrypt_mac(self):
- for plaintext, aad, key, nonce, ciphertext, tag in self.vectors:
- ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
- ctx.auth(unhexlify(aad))
- out = ctx.encrypt(unhexlify(plaintext))
- self.assertEqual(out, unhexlify(ciphertext))
+ for vector in self.vectors:
+ plaintext, aad, key, nonce, ciphertext, tag = map(unhexlify, vector)
+
+ ctx = chacha20poly1305(key, nonce)
+ ctx.auth(aad)
+ out = ctx.encrypt(plaintext)
+ self.assertEqual(out, ciphertext)
out = ctx.finish()
- self.assertEqual(out, unhexlify(tag))
+ self.assertEqual(out, tag)
def test_chacha20poly1305_decrypt_mac(self):
- for plaintext, aad, key, nonce, ciphertext, tag in self.vectors:
- ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
- ctx.auth(unhexlify(aad))
- out = ctx.decrypt(unhexlify(ciphertext))
- self.assertEqual(out, unhexlify(plaintext))
- out = ctx.finish()
- self.assertEqual(out, unhexlify(tag))
+ for vector in self.vectors:
+ plaintext, aad, key, nonce, ciphertext, tag = map(unhexlify, vector)
+
+ ctx = chacha20poly1305(key, nonce)
+ ctx.auth(aad)
+ out = ctx.decrypt(ciphertext)
+ self.assertEqual(out, plaintext)
+ out = ctx.finish(tag)
+ self.assertEqual(out, tag)
+
+ def test_chacha20poly1305_missing_expected_mac(self):
+ for vector in self.vectors:
+ _, aad, key, nonce, ciphertext, _ = map(unhexlify, vector)
+
+ ctx = chacha20poly1305(key, nonce)
+ ctx.auth(aad)
+ ctx.decrypt(ciphertext)
+ with self.assertRaises(RuntimeError) as e:
+ ctx.finish()
+ self.assertEqual(
+ e.value.value, "Argument `expected_mac` is required when decrypting."
+ )
+
+ def test_chacha20poly1305_invalid_mac_len(self):
+ for vector in self.vectors:
+ _, aad, key, nonce, ciphertext, _mac = map(unhexlify, vector)
+ invalid_macs = [
+ b"",
+ b"\x00",
+ _mac[:15],
+ b"\x00" + _mac,
+ _mac + _mac,
+ ]
+ for mac in invalid_macs:
+ ctx = chacha20poly1305(key, nonce)
+ ctx.auth(aad)
+ ctx.decrypt(ciphertext)
+ with self.assertRaises(ValueError) as e:
+ ctx.finish(mac)
+ self.assertEqual(
+ e.value.value,
+ "Invalid length of the expected mac. It has to be 16 bytes.",
+ )
+
+ def test_chacha20poly1305_invalid_mac(self):
+ invalid_mac = b"\xab" * 16
+ for vector in self.vectors:
+ _, aad, key, nonce, ciphertext, _ = map(unhexlify, vector)
+
+ ctx = chacha20poly1305(key, nonce)
+ ctx.auth(aad)
+ ctx.decrypt(ciphertext)
+ with self.assertRaises(RuntimeError) as e:
+ ctx.finish(invalid_mac)
+ self.assertEqual(e.value.value, "Authentication failed.")
if __name__ == "__main__":
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.