summaryrefslogtreecommitdiff
path: root/test/crypto/SealedBoxTest.mc
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-18 23:44:18 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-18 23:44:18 +0200
commit93aa7e3aa291f3328cf34a5a2f86172f41d0affd (patch)
treeac44438e7340fde609ad6458e31e122612cf35d1 /test/crypto/SealedBoxTest.mc
parent5646ae7f40dc53c9ebed0b3b6e907cc85fcd5993 (diff)
test: add cross-checked crypto/OTP vectors, unit tests and stricter screenshots
- gen_vectors.py: RFC/FIPS/NIST vectors recomputed with Python's stdlib (openssl for AES) before use, plus seeded cases around SHA padding boundaries, 2038 and 2100; generates test/data/Vectors.mc. - 31 Monkey C tests (hashes, HMAC, PBKDF2, HKDF, AES, sealed records incl. every-byte tamper detection, Base32 errors, 100 OTP and 12 Steam vectors, clock, jobs) and a benchmark; pass on all four test devices. - Screenshot tolerance 0.01 %: one changed character no longer passes. - Golden images updated for version 0.2.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'test/crypto/SealedBoxTest.mc')
-rw-r--r--test/crypto/SealedBoxTest.mc96
1 files changed, 96 insertions, 0 deletions
diff --git a/test/crypto/SealedBoxTest.mc b/test/crypto/SealedBoxTest.mc
new file mode 100644
index 0000000..810e512
--- /dev/null
+++ b/test/crypto/SealedBoxTest.mc
@@ -0,0 +1,96 @@
+// Author: cirakg & claude ai
+// Summary: Tests for SealedBox (encrypt-then-MAC records): round trips, tamper detection, wrong key or aad, and the self-test.
+
+import Toybox.Lang;
+import Toybox.Test;
+
+(:test)
+module SealedBoxFixtures {
+ function keys(seed as Number) as SealedBox.Keys {
+ var master = new [32]b;
+ for (var i = 0; i < 32; i++) {
+ master[i] = (i * 13 + seed) & 0xFF;
+ }
+ return new SealedBox.Keys(master);
+ }
+}
+
+(:test)
+function sealedBoxRoundTrips(logger as Test.Logger) as Boolean {
+ var keys = SealedBoxFixtures.keys(1);
+ var aad = Bytes.fromUtf8("K7F2|header");
+ for (var length = 0; length <= 70; length += 7) {
+ var plain = new [length]b;
+ for (var i = 0; i < length; i++) {
+ plain[i] = (i * 31) & 0xFF;
+ }
+ var box = SealedBox.seal(keys, aad, plain);
+ var back = SealedBox.open(keys, aad, box);
+ if (back == null || !Bytes.equal(back, plain) || box[0] != SealedBox.VERSION) {
+ logger.error("round trip failed at length " + length);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Flipping any single byte of the box (version, IV, ciphertext or tag) must
+// make open() return null.
+(:test)
+function sealedBoxDetectsEveryTamperedByte(logger as Test.Logger) as Boolean {
+ var keys = SealedBoxFixtures.keys(2);
+ var aad = [9, 9]b;
+ var box = SealedBox.seal(keys, aad, Bytes.fromUtf8("JBSWY3DPEHPK3PXP fake secret"));
+ for (var i = 0; i < box.size(); i++) {
+ var tampered = Bytes.copy(box);
+ tampered[i] = tampered[i] ^ 0x01;
+ if (SealedBox.open(keys, aad, tampered) != null) {
+ logger.error("tampering byte " + i + " was not detected");
+ return false;
+ }
+ }
+ return true;
+}
+
+(:test)
+function sealedBoxRejectsWrongKeyAadAndTruncation(logger as Test.Logger) as Boolean {
+ var keys = SealedBoxFixtures.keys(3);
+ var aad = [1, 2, 3]b;
+ var box = SealedBox.seal(keys, aad, [42]b);
+ // Moving a byte from the aad into the box must not verify either.
+ var shifted = Bytes.concat([3]b, box);
+ return SealedBox.open(SealedBoxFixtures.keys(4), aad, box) == null
+ && SealedBox.open(keys, [1, 2]b, box) == null
+ && SealedBox.open(keys, [1, 2]b, shifted) == null
+ && SealedBox.open(keys, aad, box.slice(0, box.size() - 1)) == null
+ && SealedBox.open(keys, aad, []b) == null
+ && SealedBox.open(keys, aad, box) != null;
+}
+
+// The same IV gives the same box; random IVs make every seal different.
+(:test)
+function sealedBoxIvHandling(logger as Test.Logger) as Boolean {
+ var keys = SealedBoxFixtures.keys(5);
+ var iv = new [16]b;
+ var a = SealedBox.sealWithIv(keys, []b, [7]b, iv);
+ var b = SealedBox.sealWithIv(keys, []b, [7]b, iv);
+ var c = SealedBox.seal(keys, []b, [7]b);
+ var d = SealedBox.seal(keys, []b, [7]b);
+ return Bytes.equal(a, b) && !Bytes.equal(c, d);
+}
+
+(:test)
+function sealedBoxKeysWipe(logger as Test.Logger) as Boolean {
+ var keys = SealedBoxFixtures.keys(6);
+ keys.wipe();
+ return Bytes.equal(keys.encKey, new [32]b) && Bytes.equal(keys.macKey, new [32]b);
+}
+
+(:test)
+function selfTestPasses(logger as Test.Logger) as Boolean {
+ var failed = SelfTest.run();
+ if (failed != null) {
+ logger.error("self-test failed: " + failed);
+ }
+ return failed == null;
+}