diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/BenchTest.mc | 70 | ||||
| -rw-r--r-- | test/TestSupport.mc | 53 | ||||
| -rw-r--r-- | test/crypto/HashHmacTest.mc | 54 | ||||
| -rw-r--r-- | test/crypto/KdfAesTest.mc | 116 | ||||
| -rw-r--r-- | test/crypto/SealedBoxTest.mc | 96 | ||||
| -rw-r--r-- | test/data/Vectors.mc | 256 | ||||
| -rw-r--r-- | test/golden/fr255s.png | bin | 1082 -> 1106 bytes | |||
| -rw-r--r-- | test/golden/fr70.png | bin | 5158 -> 5383 bytes | |||
| -rw-r--r-- | test/golden/fr965.png | bin | 7362 -> 7487 bytes | |||
| -rw-r--r-- | test/golden/venusq2.png | bin | 1653 -> 1684 bytes | |||
| -rw-r--r-- | test/otp/OtpTest.mc | 118 | ||||
| -rw-r--r-- | test/util/UtilTest.mc | 66 |
12 files changed, 829 insertions, 0 deletions
diff --git a/test/BenchTest.mc b/test/BenchTest.mc new file mode 100644 index 0000000..7e1f612 --- /dev/null +++ b/test/BenchTest.mc @@ -0,0 +1,70 @@ +// Author: cirakg & claude ai +// Summary: Benchmarks of the crypto and OTP primitives; logs BENCH lines for docs/PERFORMANCE.md, never fails. +// +// Simulator timings run on the PC's CPU, so they only compare primitives with +// each other (for example how much SHA-512 costs against native SHA-1). +// Watch timings come from the on-watch benchmark in M4. + +import Toybox.Lang; +import Toybox.System; +import Toybox.Test; + +(:test) +module Bench { + // Run fn `times` times and log the average in microseconds. + function measure(logger as Test.Logger, name as String, times as Number, fn as Method() as Void) as Void { + var start = System.getTimer(); + for (var i = 0; i < times; i++) { + fn.invoke(); + } + var elapsed = System.getTimer() - start; + logger.debug("BENCH " + name + " us_per_call=" + (elapsed * 1000 / times)); + } + + class Cases { + var secret20 as ByteArray = new [20]b; + var secret64 as ByteArray = new [64]b; + var keys as SealedBox.Keys = new SealedBox.Keys(new [32]b); + var box as ByteArray = []b; + + function initialize() { + box = SealedBox.seal(keys, []b, new [20]b); + } + + function totpSha1() as Void { + Otp.totp(Hashes.SHA1, secret20, 1700000000l, 30, 6); + } + + function totpSha256() as Void { + Otp.totp(Hashes.SHA256, secret20, 1700000000l, 30, 6); + } + + function totpSha512() as Void { + Otp.totp(Hashes.SHA512, secret64, 1700000000l, 30, 6); + } + + function pbkdf2Thousand() as Void { + Kdf.pbkdf2([1, 2, 3, 4, 5, 6]b, new [16]b, 1000, 32); + } + + function sealOpen() as Void { + SealedBox.open(keys, []b, SealedBox.seal(keys, []b, new [20]b)); + } + + function selfTest() as Void { + SelfTest.run(); + } + } +} + +(:test) +function benchmarkPrimitives(logger as Test.Logger) as Boolean { + var c = new Bench.Cases(); + Bench.measure(logger, "totp_sha1", 20, c.method(:totpSha1)); + Bench.measure(logger, "totp_sha256", 20, c.method(:totpSha256)); + Bench.measure(logger, "totp_sha512", 20, c.method(:totpSha512)); + Bench.measure(logger, "pbkdf2_1000_iterations", 3, c.method(:pbkdf2Thousand)); + Bench.measure(logger, "sealedbox_seal_open", 20, c.method(:sealOpen)); + Bench.measure(logger, "self_test", 3, c.method(:selfTest)); + return true; +} diff --git a/test/TestSupport.mc b/test/TestSupport.mc new file mode 100644 index 0000000..f6fa4b7 --- /dev/null +++ b/test/TestSupport.mc @@ -0,0 +1,53 @@ +// Author: cirakg & claude ai +// Summary: Small helpers shared by the Monkey C unit tests (reading vector rows, reporting mismatches). + +import Toybox.Lang; +import Toybox.Test; + +(:test) +module TestSupport { + + // One row of a TestVectors table. + function row(table as Array, index as Number) as Array { + return table[index] as Array; + } + + function str(r as Array, column as Number) as String { + return r[column] as String; + } + + function bytes(r as Array, column as Number) as ByteArray { + return Bytes.fromHex(r[column] as String); + } + + function num(r as Array, column as Number) as Number { + return r[column] as Number; + } + + // Numbers above 2^31 are stored as Long literals in the tables. + function long(r as Array, column as Number) as Long { + return (r[column] as Number or Long).toLong(); + } + + function alg(r as Array, column as Number) as Hashes.Algorithm { + return r[column] as Hashes.Algorithm; + } + + // Compare bytes; log both sides on mismatch. Returns true when equal. + function sameBytes(logger as Test.Logger, what as String, actual as ByteArray, expected as ByteArray) as Boolean { + if (Bytes.equal(actual, expected)) { + return true; + } + logger.error(what + ": got " + Bytes.toHex(actual) + ", expected " + Bytes.toHex(expected)); + return false; + } + + // Compare strings; log both sides on mismatch. + function sameString(logger as Test.Logger, what as String, actual as String, expected as String) as Boolean { + if (actual.equals(expected)) { + return true; + } + logger.error(what + ": got '" + actual + "', expected '" + expected + "'"); + return false; + } +} diff --git a/test/crypto/HashHmacTest.mc b/test/crypto/HashHmacTest.mc new file mode 100644 index 0000000..15f166c --- /dev/null +++ b/test/crypto/HashHmacTest.mc @@ -0,0 +1,54 @@ +// Author: cirakg & claude ai +// Summary: SHA-1/256/512 and HMAC tests against FIPS 180-4, RFC 2202, RFC 4231 and seeded padding-boundary vectors. + +import Toybox.Lang; +import Toybox.Test; + +// Every hash vector (FIPS 180-4 examples + messages around the padding boundaries). +(:test) +function hashMatchesVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.HASH.size(); i++) { + var r = TestSupport.row(TestVectors.HASH, i); + var actual = Hashes.digest(TestSupport.alg(r, 0), TestSupport.bytes(r, 1)); + ok = TestSupport.sameBytes(logger, "hash vector " + i, actual, TestSupport.bytes(r, 2)) && ok; + } + logger.debug(TestVectors.HASH.size() + " hash vectors"); + return ok; +} + +// Generic RFC 2104 HMAC for all three hashes, and the native HMAC-SHA256. +(:test) +function hmacMatchesRfcVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.HMAC.size(); i++) { + var r = TestVectors.HMAC[i] as Array; + var alg = TestSupport.alg(r, 0); + var key = TestSupport.bytes(r, 1); + var data = TestSupport.bytes(r, 2); + var expected = TestSupport.bytes(r, 3); + ok = TestSupport.sameBytes(logger, "generic HMAC " + i, Hmac.generic(alg, key, data), expected) && ok; + ok = TestSupport.sameBytes(logger, "HMAC " + i, Hmac.compute(alg, key, data), expected) && ok; + } + return ok; +} + +// HMAC must not change the caller's key, even for keys longer than a block. +(:test) +function hmacLeavesKeyUntouched(logger as Test.Logger) as Boolean { + var key = new [131]b; + for (var i = 0; i < key.size(); i++) { + key[i] = 0xaa; + } + var before = Bytes.copy(key); + Hmac.generic(Hashes.SHA512, key, [1, 2, 3]b); + Hmac.generic(Hashes.SHA1, key.slice(0, 20), [1, 2, 3]b); + return Bytes.equal(key, before); +} + +(:test) +function hashSizesAndValidity(logger as Test.Logger) as Boolean { + return Hashes.digestSize(Hashes.SHA1) == 20 && Hashes.digestSize(Hashes.SHA256) == 32 + && Hashes.digestSize(Hashes.SHA512) == 64 && Hashes.blockSize(Hashes.SHA512) == 128 + && Hashes.blockSize(Hashes.SHA1) == 64 && Hashes.isValid(2) && !Hashes.isValid(3) && !Hashes.isValid(-1); +} diff --git a/test/crypto/KdfAesTest.mc b/test/crypto/KdfAesTest.mc new file mode 100644 index 0000000..6587bc9 --- /dev/null +++ b/test/crypto/KdfAesTest.mc @@ -0,0 +1,116 @@ +// Author: cirakg & claude ai +// Summary: PBKDF2, HKDF and AES-CBC tests (RFC 7914, RFC 5869, NIST SP 800-38A) plus padding and job edge cases. + +import Toybox.Lang; +import Toybox.Test; + +(:test) +function pbkdf2MatchesVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.PBKDF2.size(); i++) { + var r = TestSupport.row(TestVectors.PBKDF2, i); + var key = Kdf.pbkdf2(TestSupport.bytes(r, 0), TestSupport.bytes(r, 1), TestSupport.num(r, 2), TestSupport.num(r, 3)); + ok = TestSupport.sameBytes(logger, "PBKDF2 vector " + i, key, TestSupport.bytes(r, 4)) && ok; + } + return ok; +} + +// The result must not depend on how the work is split into steps. +(:test) +function pbkdf2StepSizeDoesNotMatter(logger as Test.Logger) as Boolean { + var password = Bytes.fromUtf8("123456"); + var salt = new [16]b; + var oneByOne = new Kdf.Pbkdf2(password, salt, 37, 40); + var steps = 0; + while (!oneByOne.step(1)) { + steps++; + } + // 2 output blocks x 37 iterations, the last step returns true. + return Bytes.equal(oneByOne.result(), Kdf.pbkdf2(password, salt, 37, 40)) && steps == 73; +} + +(:test) +function pbkdf2RejectsBadParameters(logger as Test.Logger) as Boolean { + var rejected = 0; + var cases = [[0, 32], [1, 0], [1, 255 * 32 + 1]]; + for (var i = 0; i < cases.size(); i++) { + var c = cases[i] as Array<Number>; + try { + new Kdf.Pbkdf2([1]b, [2]b, c[0], c[1]); + } catch (e instanceof Lang.InvalidValueException) { + rejected++; + } + } + return rejected == cases.size(); +} + +(:test) +function pbkdf2CalibrationStaysInBounds(logger as Test.Logger) as Boolean { + var iterations = Kdf.calibrate(1000, 500); + logger.debug("calibrated iterations for 1 s in this simulator: " + iterations); + return iterations >= Kdf.MIN_ITERATIONS && iterations <= Kdf.MAX_ITERATIONS; +} + +(:test) +function hkdfMatchesRfcVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.HKDF.size(); i++) { + var r = TestSupport.row(TestVectors.HKDF, i); + var okm = Kdf.hkdf(TestSupport.bytes(r, 0), TestSupport.bytes(r, 1), TestSupport.bytes(r, 2), TestSupport.num(r, 3)); + ok = TestSupport.sameBytes(logger, "HKDF vector " + i, okm, TestSupport.bytes(r, 4)) && ok; + } + return ok; +} + +(:test) +function aesCbcMatchesNistVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.AES_CBC.size(); i++) { + var r = TestSupport.row(TestVectors.AES_CBC, i); + var key = TestSupport.bytes(r, 0); + var iv = TestSupport.bytes(r, 1); + var plain = TestSupport.bytes(r, 2); + var cipher = TestSupport.bytes(r, 3); + ok = TestSupport.sameBytes(logger, "AES encrypt " + i, Aes.cbcRaw(key, iv, plain, true), cipher) && ok; + ok = TestSupport.sameBytes(logger, "AES decrypt " + i, Aes.cbcRaw(key, iv, cipher, false), plain) && ok; + } + return ok; +} + +// PKCS#7 round trips for every length from 0 to 40 bytes, both key sizes. +(:test) +function aesPaddingRoundTrips(logger as Test.Logger) as Boolean { + var iv = new [16]b; + var keys = [new [16]b, new [32]b]; + for (var k = 0; k < keys.size(); k++) { + for (var length = 0; length <= 40; length++) { + var plain = new [length]b; + for (var i = 0; i < length; i++) { + plain[i] = (i * 7 + length) & 0xFF; + } + var cipher = Aes.cbcEncrypt(keys[k] as ByteArray, iv, plain); + var back = Aes.cbcDecrypt(keys[k] as ByteArray, iv, cipher); + if (cipher.size() != (length / 16 + 1) * 16 || back == null || !Bytes.equal(back, plain)) { + logger.error("padding round trip failed at length " + length); + return false; + } + } + } + return true; +} + +(:test) +function aesRejectsBadPaddingAndLength(logger as Test.Logger) as Boolean { + var key = new [32]b; + var iv = new [16]b; + // A block whose decryption ends in 0x00, which is never valid padding. + var badPadding = Aes.cbcRaw(key, iv, new [16]b, true); + var badKey = false; + try { + Aes.cbcEncrypt(new [24]b, iv, [1]b); + } catch (e instanceof Lang.InvalidValueException) { + badKey = true; + } + return Aes.cbcDecrypt(key, iv, badPadding) == null && Aes.cbcDecrypt(key, iv, new [15]b) == null + && Aes.cbcDecrypt(key, iv, []b) == null && badKey; +} 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; +} diff --git a/test/data/Vectors.mc b/test/data/Vectors.mc new file mode 100644 index 0000000..3fa6418 --- /dev/null +++ b/test/data/Vectors.mc @@ -0,0 +1,256 @@ +// Author: cirakg & claude ai +// Summary: Crypto and OTP test vectors (official RFC/FIPS/NIST values plus seeded cases); generated, do not edit. +// +// Generated by tools/gen_vectors.py. Every published vector was recomputed with +// Python's standard library (or openssl for AES) before being written here. +// Algorithm IDs: 0 = SHA-1, 1 = SHA-256, 2 = SHA-512. All data is fake. + +import Toybox.Lang; + +(:test) +module TestVectors { + + // [alg, message hex, digest hex] + const HASH = [ + [0, "", "da39a3ee5e6b4b0d3255bfef95601890afd80709"], + [0, "616263", "a9993e364706816aba3e25717850c26c9cd0d89d"], + [0, "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071", "84983e441c3bd26ebaae4aa1f95129e5e54670f1"], + [0, "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475", "a49b2446a02c645bf419f995b67091253a04a259"], + [0, "6d0d8c3c1ce808451a34469d6624cd700a4fa6d15b876e7557c8bd17cf5600a9c413a505bc854e507d32a411aa9f551f952cf38009c4c6", "1c869e923c782ee8d9ab2d4f85d9a204be1db7c3"], + [0, "7731b02cd0337ae020f31e9bc4a14517f85c5df2538ea53213e69b948123f9d258d83556eef48e977b6681c5524e18e4bc511f3a5f7622bf", "5cd4a7d0da88584202738e80727c97a26a0c127c"], + [0, "131a46ef9295c0b758a8ebcdadf4daf8835727011ad74bdfedb7cf63e0533ab00b5d8e9eaa2e2dfd37b26a61429eafac75e75626563561e2fd258dc4386354", "2ac31dafc392f987f9651e352d2ceed6a93cd17b"], + [0, "38fdef0b935ff5b7c4829ac4464d7875691b6cdbbb77f5bd444ab3f7073eb944f447affe25ff0324dd7088fa27aa46648b62683c1208d3a6e68d303a848b0c00", "7ed0cc4b1632e258d5523e4cd610e56972148b13"], + [0, "3e9adb68be6a7cfbe04fa0a38f66398d5f13e3968de9025e2c2c0f5e9348f8060eac04c18d270ff9720515e933984c423fc4ecb266f98af0c24a7e6ffaea357438", "c9d2086acb73ac21167d4ada0372e666ef755f03"], + [0, "13f31c99adac92c7f26cd932169db6cfcff78af291b86a3af01e4d5228057a60fd1e1e191fc12ee569b5a54699d0a5f2861e1664cb451614957e9537cb21312c633d6881d83bdad64f51b1e6561efe6c5412fde7e26427da71ed4f7bd57cf37556dcaebd4d95ccf819eca1a215348f", "4c45cc84adbf739241369de057624bfaa504342f"], + [0, "e1763744bd7820171b3ef27d194b5dce4dbf0ea28995979c3a24f97aaba8d06806f78d6af1a0c6f36a691e35d04a4137ee28deb30d256b2d5580b2ea0588f3fad41e4b645514babe5657a00b70fcd883f1d9ff3c1de979eaa6ed08e0fa7ceb6444a0ed409a26d2d4ca9185b51dabaa44", "d8c47c71a062bf583b0f60f1aab90b58306743fe"], + [0, "392d835246b8b7df9e4dfb13bf8b39d061096e22efe3cc006f226a241802930259bfa221a2fa0cada80abef651e3004af4aedf2f196f282687877678118c05b96e1346408829f88e305727cd01406fe5e30a1ca1fc0baeadd04054c4a5cdbe20e569ecd958cc87e055c92d01707e321417a99cf2aa0ee5", "81b8b131a25aa2e7b413c76be0b8a5a8ef8b2bd4"], + [0, "0a59941f0f6248d528970e0d4f7f067486f0d658e00216fc22858e99b5c97d1896e7d4860ce2a330306961bd36fbbd32bb69880eb739b647ea0ee87027d04738b767420e1bb88c27a7e6abc5f0b85b65193f095691b87d6a336d085aff85bb3f6e1c61ed51258b7ed2f2660c7e1ac61e5c5c4355a155c1bb", "9c9243f3dda2afa93394a5301d00a8d1f156cfef"], + [0, "bea111b3d92efc8c75ead3f37878211b487a565b837eb409a96ad2ec0ad622ed85a6578f1863ad3e6d1dbb2224b57ba6937fa97510a2832b28f675551642b33dabda0b67ccc04f9b5114689098ccfc0c31841291ef986966eb6848bbac7e0e26d667083200f3fb42039a9caa8562416af1b991f645263e3984f1850a0fa334", "27ea91250bdb027af68c050b90e56c75eb3cd9d3"], + [0, "27a0b7d68901642b6313f800eee48c21eef8a15c59dd10b6762de05339a542912d41441ff4167dded377c179d3f174dd2266f9c44a2f74ca256e2a840b71215a16d49e47362f518f4feb37fe95034c4916f0ce20d845e2bd513a055aeb967be5519406efc4a26c032a484be2324fd75e06f00ff980c67a33b23dc470fdbdd93f", "6b6ec44a0921c56255c39709ebe4eb6f8fb906c7"], + [0, "fd164b1b27fea36e2c61866648bafa348d9f350e562764b83f84761084a3cb47c4f63c6c1ed6e415871cc0aaba2a6b7cd32f4fa62603bde8f0d6cf6a0d5641616368c908bac82676696a613df52ce0a6f7106e8c93d1f03360afa5e206cd3f9d937de830d015092688bcebc2a33178e921068591bd6cd27232613d888f423c8bca", "fd587b4527835de6de2747a28c6f20462fe379f6"], + [0, "3975342b2653b1eeefa2d13abf192812bc0ca4a64f9974da2eb3692ba049fce011f41b3b0bf5f2afbf35d1838371b7fbe16b2878ac84072e1740be20f9fd0ef9c207bac63c5f9591ab2be34e0a9c01d5da04a59b9a24b2eeca6402267664a7e7cd8e9502132adf3810560bb09d79d9e1bec02e5c6e844323a31d0719f415d2bbf6b422d8bad5f051f92cd421a0c524c4c323ed3bb00ed38073086afe5ef7d72bc0de6cce36a3e657e7e79491c1e9774a49e28783cfa9b9df05906437458b3be9be1641eafa0aa6dd", "7be3138fdf6400ea9fb1419d16a3d312713f862d"], + [0, "c0d0cfea92651a5d920b275142ceb89a75bfcafc58f95b49b838df35a2b1b3820b88ac3dd88fb3ada473cee9fe02335c422082f7e9534e206de970c71bb0e82f54ab3364a68d1c047dcce6e6407ff2cd9f90e8f11fc78784941dad27c21cf0e5adddb3e4e21e39347382be63a73de8da60e6788056edb3c9c1e2cc72dfc7ae7ea3a7b77fa594fa716b3c836acf8fff9667ae9bda70ae0e89fadef31701f1bcf9ce458670af7107099dae8f8a63040058bb2189b3f553fde96fb9cae10a6f4e8ea3c761b8be8c68d0e95f1ca108ab744f285235238626b20a31ae5d797e57f8cd21fd61979e9236a3623c3fae53b0ebc6dd5b7a8c6fe5f94a2c80c50f8c356a", "85c732ab558ea9d468435f1bbb9d7efc85650a33"], + [0, "31c1fb7e167b34c36fda54fe80e078d55c209aeab1c75a48d32223aee136ab1648ebad4448dd7d42a8d3a8c6b9aad8683d818e0d48b0ccfb6c5023cb7dc3bf6f9b8acaa79cc4627b0d983babfa7d3b382016feedc47f588a272844d9095aa08328b6f3bc2bd84dbc3e448a527597ff2828116b5ea11e8fac2eb1f74e90b33e6408df66c03048377e21fc96bcd8b333576650ef8c2ab95eb09494165317bf5636d4281d248d8bbb085373c7fa2f9cc16e422c9e111bebd654d8f4f15dacc084b127412483e5121b1e2df5b655f0d61d76fa8446ca6ad4d4a377d445fcbb985f7234e86751a5ee31cd165e67f6ddd46d571cc49fe9db65f436f4ecf1eb13d4600e", "004a9403ae34d067bc413c0654b47eec220b92aa"], + [1, "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"], + [1, "616263", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"], + [1, "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"], + [1, "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475", "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"], + [1, "6d0d8c3c1ce808451a34469d6624cd700a4fa6d15b876e7557c8bd17cf5600a9c413a505bc854e507d32a411aa9f551f952cf38009c4c6", "cd521b248f7ba3da9d6cc73bc9c6d2e8a03c577093518a4bfbc43d1d3401ecf1"], + [1, "7731b02cd0337ae020f31e9bc4a14517f85c5df2538ea53213e69b948123f9d258d83556eef48e977b6681c5524e18e4bc511f3a5f7622bf", "4b292348851062ae121598d26fca16c3a7720e5dd72f863d5943a014e1de4b38"], + [1, "131a46ef9295c0b758a8ebcdadf4daf8835727011ad74bdfedb7cf63e0533ab00b5d8e9eaa2e2dfd37b26a61429eafac75e75626563561e2fd258dc4386354", "ad45017da98a41870e502895f506b7b0e321dece0cef5c0234c0d0b04859ecd5"], + [1, "38fdef0b935ff5b7c4829ac4464d7875691b6cdbbb77f5bd444ab3f7073eb944f447affe25ff0324dd7088fa27aa46648b62683c1208d3a6e68d303a848b0c00", "a5f6d88d0bff0e0838ebd323396f31f6d173d570306077a48416a266da1024f4"], + [1, "3e9adb68be6a7cfbe04fa0a38f66398d5f13e3968de9025e2c2c0f5e9348f8060eac04c18d270ff9720515e933984c423fc4ecb266f98af0c24a7e6ffaea357438", "7b6c6ccaa8fdbdeeb982cdc88c7d0bb722ae02a7653164870b25c8179d3e2f59"], + [1, "13f31c99adac92c7f26cd932169db6cfcff78af291b86a3af01e4d5228057a60fd1e1e191fc12ee569b5a54699d0a5f2861e1664cb451614957e9537cb21312c633d6881d83bdad64f51b1e6561efe6c5412fde7e26427da71ed4f7bd57cf37556dcaebd4d95ccf819eca1a215348f", "ef25ca1677776a0e141dd7d08a69c14b9ec3c264de52f6cb13bb878b64ea774f"], + [1, "e1763744bd7820171b3ef27d194b5dce4dbf0ea28995979c3a24f97aaba8d06806f78d6af1a0c6f36a691e35d04a4137ee28deb30d256b2d5580b2ea0588f3fad41e4b645514babe5657a00b70fcd883f1d9ff3c1de979eaa6ed08e0fa7ceb6444a0ed409a26d2d4ca9185b51dabaa44", "1ff578a01347102520a62129dfc57880a97ada0daf3a6761a0a38e7f06f29c1d"], + [1, "392d835246b8b7df9e4dfb13bf8b39d061096e22efe3cc006f226a241802930259bfa221a2fa0cada80abef651e3004af4aedf2f196f282687877678118c05b96e1346408829f88e305727cd01406fe5e30a1ca1fc0baeadd04054c4a5cdbe20e569ecd958cc87e055c92d01707e321417a99cf2aa0ee5", "628dd6b90dca5602ab123e01e17147eaa9e22b16f82a6a8793d3ad95c55df233"], + [1, "0a59941f0f6248d528970e0d4f7f067486f0d658e00216fc22858e99b5c97d1896e7d4860ce2a330306961bd36fbbd32bb69880eb739b647ea0ee87027d04738b767420e1bb88c27a7e6abc5f0b85b65193f095691b87d6a336d085aff85bb3f6e1c61ed51258b7ed2f2660c7e1ac61e5c5c4355a155c1bb", "5ddd4e441c0af889afb7776e08d0f0e6b8cc18c121ee816c146be2141384116f"], + [1, "bea111b3d92efc8c75ead3f37878211b487a565b837eb409a96ad2ec0ad622ed85a6578f1863ad3e6d1dbb2224b57ba6937fa97510a2832b28f675551642b33dabda0b67ccc04f9b5114689098ccfc0c31841291ef986966eb6848bbac7e0e26d667083200f3fb42039a9caa8562416af1b991f645263e3984f1850a0fa334", "8ccfa60304794bd9aef2fccbe26a06ba1616170351b1cdab4a45b0ae6e5cbf78"], + [1, "27a0b7d68901642b6313f800eee48c21eef8a15c59dd10b6762de05339a542912d41441ff4167dded377c179d3f174dd2266f9c44a2f74ca256e2a840b71215a16d49e47362f518f4feb37fe95034c4916f0ce20d845e2bd513a055aeb967be5519406efc4a26c032a484be2324fd75e06f00ff980c67a33b23dc470fdbdd93f", "75284fd4f70a41c9a89e0b590942bfac17b54fc4021ea41a2f6bef0cac09d644"], + [1, "fd164b1b27fea36e2c61866648bafa348d9f350e562764b83f84761084a3cb47c4f63c6c1ed6e415871cc0aaba2a6b7cd32f4fa62603bde8f0d6cf6a0d5641616368c908bac82676696a613df52ce0a6f7106e8c93d1f03360afa5e206cd3f9d937de830d015092688bcebc2a33178e921068591bd6cd27232613d888f423c8bca", "f58ba766306d84a4c124289aed4b06e6c42fda8afe5aa3b0a73529ce3311159f"], + [1, "3975342b2653b1eeefa2d13abf192812bc0ca4a64f9974da2eb3692ba049fce011f41b3b0bf5f2afbf35d1838371b7fbe16b2878ac84072e1740be20f9fd0ef9c207bac63c5f9591ab2be34e0a9c01d5da04a59b9a24b2eeca6402267664a7e7cd8e9502132adf3810560bb09d79d9e1bec02e5c6e844323a31d0719f415d2bbf6b422d8bad5f051f92cd421a0c524c4c323ed3bb00ed38073086afe5ef7d72bc0de6cce36a3e657e7e79491c1e9774a49e28783cfa9b9df05906437458b3be9be1641eafa0aa6dd", "7b5ee7140f4426da3849dba94fa129d177ae479928797ae61f72ecfb8922ddf0"], + [1, "c0d0cfea92651a5d920b275142ceb89a75bfcafc58f95b49b838df35a2b1b3820b88ac3dd88fb3ada473cee9fe02335c422082f7e9534e206de970c71bb0e82f54ab3364a68d1c047dcce6e6407ff2cd9f90e8f11fc78784941dad27c21cf0e5adddb3e4e21e39347382be63a73de8da60e6788056edb3c9c1e2cc72dfc7ae7ea3a7b77fa594fa716b3c836acf8fff9667ae9bda70ae0e89fadef31701f1bcf9ce458670af7107099dae8f8a63040058bb2189b3f553fde96fb9cae10a6f4e8ea3c761b8be8c68d0e95f1ca108ab744f285235238626b20a31ae5d797e57f8cd21fd61979e9236a3623c3fae53b0ebc6dd5b7a8c6fe5f94a2c80c50f8c356a", "81692a67280a7c614a0243d3657d5088227a72ddeaee5e51c8ce630c275ec193"], + [1, "31c1fb7e167b34c36fda54fe80e078d55c209aeab1c75a48d32223aee136ab1648ebad4448dd7d42a8d3a8c6b9aad8683d818e0d48b0ccfb6c5023cb7dc3bf6f9b8acaa79cc4627b0d983babfa7d3b382016feedc47f588a272844d9095aa08328b6f3bc2bd84dbc3e448a527597ff2828116b5ea11e8fac2eb1f74e90b33e6408df66c03048377e21fc96bcd8b333576650ef8c2ab95eb09494165317bf5636d4281d248d8bbb085373c7fa2f9cc16e422c9e111bebd654d8f4f15dacc084b127412483e5121b1e2df5b655f0d61d76fa8446ca6ad4d4a377d445fcbb985f7234e86751a5ee31cd165e67f6ddd46d571cc49fe9db65f436f4ecf1eb13d4600e", "b0134708be68019bddb81d1c4b34bab1cec31e51bc2ec2f247c5aa4c4a6d086d"], + [2, "", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"], + [2, "616263", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"], + [2, "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071", "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"], + [2, "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475", "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"], + [2, "6d0d8c3c1ce808451a34469d6624cd700a4fa6d15b876e7557c8bd17cf5600a9c413a505bc854e507d32a411aa9f551f952cf38009c4c6", "34a13900da1e7144741d0435dc36c9493417a6796ce6d2157b6a7d5d90f58facfd981457061e16480a7ce547e61aa3cc6a35d33eb450237dcec7b6d1b371dfdb"], + [2, "7731b02cd0337ae020f31e9bc4a14517f85c5df2538ea53213e69b948123f9d258d83556eef48e977b6681c5524e18e4bc511f3a5f7622bf", "2c25fde731494bd45e9cb0f929616c1d8d6ba93de01067adacd0df6146eff9e809562bdf7662990a851a148a84377936bf0689debd46871e86228524ea74374b"], + [2, "131a46ef9295c0b758a8ebcdadf4daf8835727011ad74bdfedb7cf63e0533ab00b5d8e9eaa2e2dfd37b26a61429eafac75e75626563561e2fd258dc4386354", "50ecb1de97633d82a6247221f277b4f5c3dc65e58a72d64ff0cddc2b8ecc2fd18037ad4dbc0401db0b2db54eecb45f55c993dd697a3621b13f2f64cf249956ea"], + [2, "38fdef0b935ff5b7c4829ac4464d7875691b6cdbbb77f5bd444ab3f7073eb944f447affe25ff0324dd7088fa27aa46648b62683c1208d3a6e68d303a848b0c00", "0fa45233a7a3c90f4a73df2da9223f067c1ed78b6345d43449da482c2bf23529359d9dcdf036b40a945466ad15291ae0f6094e9c97e06be3fc5f8278d7186087"], + [2, "3e9adb68be6a7cfbe04fa0a38f66398d5f13e3968de9025e2c2c0f5e9348f8060eac04c18d270ff9720515e933984c423fc4ecb266f98af0c24a7e6ffaea357438", "2578a20981b007efb3d29bc4b86acdb09b908ae02bec6a5f4cd7b04f9a2ab9718fcea73827e3a54f1d73ab0d7f192d677c415ad94c82b71828fcd364a0baa0f7"], + [2, "13f31c99adac92c7f26cd932169db6cfcff78af291b86a3af01e4d5228057a60fd1e1e191fc12ee569b5a54699d0a5f2861e1664cb451614957e9537cb21312c633d6881d83bdad64f51b1e6561efe6c5412fde7e26427da71ed4f7bd57cf37556dcaebd4d95ccf819eca1a215348f", "c37c880d8075821ddf8e2e983ba92817ab2168a97fe78b60ea6bb5c4213bb643a2bc7f68f8c122f173b5d1fe6ce5ad2c7362466eca58302a0ddb6ff544fe120a"], + [2, "e1763744bd7820171b3ef27d194b5dce4dbf0ea28995979c3a24f97aaba8d06806f78d6af1a0c6f36a691e35d04a4137ee28deb30d256b2d5580b2ea0588f3fad41e4b645514babe5657a00b70fcd883f1d9ff3c1de979eaa6ed08e0fa7ceb6444a0ed409a26d2d4ca9185b51dabaa44", "a2e1380ce72e1a763496614d542975162cdb3eb170b031656d1e4fc94337e6dd01b8816335e54b4c3bff01b78ddd8f17f9c9a1921df9dd7a074e291c4d244ca9"], + [2, "392d835246b8b7df9e4dfb13bf8b39d061096e22efe3cc006f226a241802930259bfa221a2fa0cada80abef651e3004af4aedf2f196f282687877678118c05b96e1346408829f88e305727cd01406fe5e30a1ca1fc0baeadd04054c4a5cdbe20e569ecd958cc87e055c92d01707e321417a99cf2aa0ee5", "ac6299ac16f071485693509e1808f2ee2280ac300bd763e22304b2ab7910a5eb876a6f1c2715f8bfd6fd4aeab6ff3a48346042db99d6424d2a5139e25d55159b"], + [2, "0a59941f0f6248d528970e0d4f7f067486f0d658e00216fc22858e99b5c97d1896e7d4860ce2a330306961bd36fbbd32bb69880eb739b647ea0ee87027d04738b767420e1bb88c27a7e6abc5f0b85b65193f095691b87d6a336d085aff85bb3f6e1c61ed51258b7ed2f2660c7e1ac61e5c5c4355a155c1bb", "e0a3df4be63b3ffe49b4dbc8557ea1ee7c9021e17786f511850d58694cad26011ad8da47d715837d6ea488d7047a827ebc0f1549ff986bfc06571c6ef5a74a6f"], + [2, "bea111b3d92efc8c75ead3f37878211b487a565b837eb409a96ad2ec0ad622ed85a6578f1863ad3e6d1dbb2224b57ba6937fa97510a2832b28f675551642b33dabda0b67ccc04f9b5114689098ccfc0c31841291ef986966eb6848bbac7e0e26d667083200f3fb42039a9caa8562416af1b991f645263e3984f1850a0fa334", "4112bbe7a623cf3e449faa73dbc29383330b53891260a103d29cfd79ee799da5534c61be905e9a0f915c5a98a3e5c3c7be08f007d657f6c494682d845847d68c"], + [2, "27a0b7d68901642b6313f800eee48c21eef8a15c59dd10b6762de05339a542912d41441ff4167dded377c179d3f174dd2266f9c44a2f74ca256e2a840b71215a16d49e47362f518f4feb37fe95034c4916f0ce20d845e2bd513a055aeb967be5519406efc4a26c032a484be2324fd75e06f00ff980c67a33b23dc470fdbdd93f", "160068376630101582bb84b7020606c95c671784d922157047351e942261c668c83e7758fd7ae72144af304371c5610b283bbbe94d9c5042df0c0e635d417a4e"], + [2, "fd164b1b27fea36e2c61866648bafa348d9f350e562764b83f84761084a3cb47c4f63c6c1ed6e415871cc0aaba2a6b7cd32f4fa62603bde8f0d6cf6a0d5641616368c908bac82676696a613df52ce0a6f7106e8c93d1f03360afa5e206cd3f9d937de830d015092688bcebc2a33178e921068591bd6cd27232613d888f423c8bca", "fda0bb148c3a87ca00656afefbbda126a1cdcbf8c16d0cb02183fb8b08566f76931087976ce8328407b9eb1ef11b7ddc6f73bbff6f04e55af1fe157d8f617fd6"], + [2, "3975342b2653b1eeefa2d13abf192812bc0ca4a64f9974da2eb3692ba049fce011f41b3b0bf5f2afbf35d1838371b7fbe16b2878ac84072e1740be20f9fd0ef9c207bac63c5f9591ab2be34e0a9c01d5da04a59b9a24b2eeca6402267664a7e7cd8e9502132adf3810560bb09d79d9e1bec02e5c6e844323a31d0719f415d2bbf6b422d8bad5f051f92cd421a0c524c4c323ed3bb00ed38073086afe5ef7d72bc0de6cce36a3e657e7e79491c1e9774a49e28783cfa9b9df05906437458b3be9be1641eafa0aa6dd", "506d260b0036564100a4854ba8fcdfbc596ea21d331f4bd64bb5981aae2e8245464e550148b6b4851fa9a03aeb29950de4b7b1bd5df714bdc76629e8579d1a5e"], + [2, "c0d0cfea92651a5d920b275142ceb89a75bfcafc58f95b49b838df35a2b1b3820b88ac3dd88fb3ada473cee9fe02335c422082f7e9534e206de970c71bb0e82f54ab3364a68d1c047dcce6e6407ff2cd9f90e8f11fc78784941dad27c21cf0e5adddb3e4e21e39347382be63a73de8da60e6788056edb3c9c1e2cc72dfc7ae7ea3a7b77fa594fa716b3c836acf8fff9667ae9bda70ae0e89fadef31701f1bcf9ce458670af7107099dae8f8a63040058bb2189b3f553fde96fb9cae10a6f4e8ea3c761b8be8c68d0e95f1ca108ab744f285235238626b20a31ae5d797e57f8cd21fd61979e9236a3623c3fae53b0ebc6dd5b7a8c6fe5f94a2c80c50f8c356a", "cc3f30b6e1c87c491abad65e1bb85fcc039d19001f6e5b4f3c0ffa6332cc8f0735e466915dae91b9801a2a9c323c5d609dfaa7283236e9552f121390a1c31d90"], + [2, "31c1fb7e167b34c36fda54fe80e078d55c209aeab1c75a48d32223aee136ab1648ebad4448dd7d42a8d3a8c6b9aad8683d818e0d48b0ccfb6c5023cb7dc3bf6f9b8acaa79cc4627b0d983babfa7d3b382016feedc47f588a272844d9095aa08328b6f3bc2bd84dbc3e448a527597ff2828116b5ea11e8fac2eb1f74e90b33e6408df66c03048377e21fc96bcd8b333576650ef8c2ab95eb09494165317bf5636d4281d248d8bbb085373c7fa2f9cc16e422c9e111bebd654d8f4f15dacc084b127412483e5121b1e2df5b655f0d61d76fa8446ca6ad4d4a377d445fcbb985f7234e86751a5ee31cd165e67f6ddd46d571cc49fe9db65f436f4ecf1eb13d4600e", "70a3d62f90104a4b3c041eb4c80bb215201175ce1f9f52a6e012c8e88b61745967f929ae8775339321ac982f29ff4a5afbf83792180fc7b668762908effd87f2"] + ]; + + // [alg, key hex, data hex, mac hex] (RFC 2202, RFC 4231) + const HMAC = [ + [0, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "b617318655057264e28bc0b6fb378c8ef146be00"], + [0, "4a656665", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"], + [0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "125d7342b9ac11cd91a39af48aa17b4f63f175d3"], + [0, "0102030405060708090a0b0c0d0e0f10111213141516171819", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "4c9007f4026250c6bc8414f9bf50c86c2d7235da"], + [0, "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "546573742057697468205472756e636174696f6e", "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"], + [0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", "aa4ae5e15272d00e95705637ce8a3b55ed402112"], + [0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461", "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"], + [1, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"], + [1, "4a656665", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"], + [1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"], + [1, "0102030405060708090a0b0c0d0e0f10111213141516171819", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"], + [1, "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "546573742057697468205472756e636174696f6e", "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5"], + [1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"], + [1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"], + [2, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"], + [2, "4a656665", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"], + [2, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"], + [2, "0102030405060708090a0b0c0d0e0f10111213141516171819", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"], + [2, "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "546573742057697468205472756e636174696f6e", "415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b"], + [2, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"], + [2, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e", "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"] + ]; + + // [password hex, salt hex, iterations, length, key hex] (RFC 7914 + seeded) + const PBKDF2 = [ + ["706173737764", "73616c74", 1, 64, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"], + ["70617373776f7264", "73616c74", 2, 32, "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"], + ["70617373776f7264", "73616c74", 100, 32, "07e6997180cf7f12904f04100d405d34888fdf62af6d506a0ecc23b196fe99d8"], + ["313233343536", "00000000000000000000000000000000", 1000, 32, "c4b2f911865b1a55abf7deb663563bef104af632bfc246b91581ea0eac11630f"], + ["70617373776f726450415353574f524470617373776f7264", "73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", 300, 40, "d4de84cdb20a7916ca23be9303f66df58d1b2407247b2212263e0589701d86a95fc04e7e893c4d93"] + ]; + + // [ikm hex, salt hex, info hex, length, okm hex] (RFC 5869 A.1-A.3) + const HKDF = [ + ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", 42, "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"], + ["000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 82, "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"], + ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", 42, "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"] + ]; + + // [key hex, iv hex, plaintext hex, ciphertext hex] (SP 800-38A F.2.1, F.2.5) + const AES_CBC = [ + ["2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7"], + ["603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", "f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b"] + ]; + + // [bytes hex, encoded] (RFC 4648 section 10 + seeded) + const BASE32 = [ + ["", ""], + ["66", "MY======"], + ["666f", "MZXQ===="], + ["666f6f", "MZXW6==="], + ["666f6f62", "MZXW6YQ="], + ["666f6f6261", "MZXW6YTB"], + ["666f6f626172", "MZXW6YTBOI======"], + ["a1634835dd01edefddaa", "UFRUQNO5AHW67XNK"], + ["4747f06e580fb0c74d252628124e67a2", "I5D7A3SYB6YMOTJFEYUBETTHUI======"], + ["ebe276b504dbc13cffbe351846f00ded08164c5c", "5PRHNNIE3PATZ756GUMEN4AN5UEBMTC4"], + ["fbcaebfc120620a3b9f6f1b5cbfa090b7d573ee9836db4b8fff9b773d81a94e4", "7PFOX7ASAYQKHOPW6G24X6QJBN6VOPXJQNW3JOH77G3XHWA2STSA===="], + ["a1a74ca6ac9f7d8479009a6380b70af193bfb1a470cbfc7fafe02481559379905890316f66ef402e12a493513c61c0df667e8264f1573a537a293323329ba99f", "UGTUZJVMT56YI6IATJRYBNYK6GJ37MNEODF7Y75P4ASICVMTPGIFREBRN5TO6QBOCKSJGUJ4MHAN6ZT6QJSPCVZ2KN5CSMZDGKN2THY="] + ]; + + // [alg, secret hex, time or counter, period (0 = HOTP), digits, code] + const OTP = [ + [0, "3132333435363738393031323334353637383930", 0, 0, 6, "755224"], + [0, "3132333435363738393031323334353637383930", 1, 0, 6, "287082"], + [0, "3132333435363738393031323334353637383930", 2, 0, 6, "359152"], + [0, "3132333435363738393031323334353637383930", 3, 0, 6, "969429"], + [0, "3132333435363738393031323334353637383930", 4, 0, 6, "338314"], + [0, "3132333435363738393031323334353637383930", 5, 0, 6, "254676"], + [0, "3132333435363738393031323334353637383930", 6, 0, 6, "287922"], + [0, "3132333435363738393031323334353637383930", 7, 0, 6, "162583"], + [0, "3132333435363738393031323334353637383930", 8, 0, 6, "399871"], + [0, "3132333435363738393031323334353637383930", 9, 0, 6, "520489"], + [0, "3132333435363738393031323334353637383930", 59, 30, 8, "94287082"], + [0, "3132333435363738393031323334353637383930", 1111111109, 30, 8, "07081804"], + [0, "3132333435363738393031323334353637383930", 1111111111, 30, 8, "14050471"], + [0, "3132333435363738393031323334353637383930", 1234567890, 30, 8, "89005924"], + [0, "3132333435363738393031323334353637383930", 2000000000, 30, 8, "69279037"], + [0, "3132333435363738393031323334353637383930", 20000000000l, 30, 8, "65353130"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 59, 30, 8, "46119246"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 1111111109, 30, 8, "68084774"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 1111111111, 30, 8, "67062674"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 1234567890, 30, 8, "91819424"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 2000000000, 30, 8, "90698825"], + [1, "3132333435363738393031323334353637383930313233343536373839303132", 20000000000l, 30, 8, "77737706"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 59, 30, 8, "90693936"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 1111111109, 30, 8, "25091201"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 1111111111, 30, 8, "99943326"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 1234567890, 30, 8, "93441116"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 2000000000, 30, 8, "38618901"], + [2, "31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334", 20000000000l, 30, 8, "47863826"], + [0, "a820ea3b711c8b835f197a403826716c", 29, 37, 6, "852264"], + [0, "a820ea3b711c8b835f197a403826716c", 2083839650, 37, 6, "744326"], + [0, "a820ea3b711c8b835f197a403826716c", 29, 15, 7, "6095944"], + [0, "a820ea3b711c8b835f197a403826716c", 2959118287l, 15, 7, "1680553"], + [0, "a820ea3b711c8b835f197a403826716c", 0, 15, 8, "40852264"], + [0, "a820ea3b711c8b835f197a403826716c", 138345305, 15, 8, "20434868"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 30, 30, 6, "454281"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 441580728, 30, 6, "654983"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 30, 30, 7, "8454281"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 3797986681l, 30, 7, "4647824"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 0, 37, 8, "31451272"], + [0, "3a96311d28eb74f2fbdc650ffe66650b443c9ccf661304bfbfe4683b27764d6028b76fd1cc5ae9e46083c2f0a3270b767915a4448ac417ffcad0c177b236e472", 1703416463, 37, 8, "41455495"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 0, 90, 6, "026259"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 1106401343, 90, 6, "175499"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 2147483647, 60, 7, "6973904"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 1927359805, 60, 7, "8420158"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 0, 60, 8, "01026259"], + [0, "80c38fc3aec4671c5aa29614a41ae9676b4077b6", 955574268, 60, 8, "55067388"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 2147483647, 15, 6, "335148"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 1882823122, 15, 6, "176153"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 4102444800l, 37, 7, "8239134"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 46566660, 37, 7, "0305254"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 4102444800l, 37, 8, "38239134"], + [0, "1c112c028b824331c2cacd584e6ec75e44440ae435f9143eb95838b79e7638bd32e1dd08f9635480324894a51d525e0231c51453894de3305f77cd370abc6d06", 681863666, 37, 8, "99992227"], + [1, "519314e78dc41fc39c2f", 2147483647, 90, 6, "679650"], + [1, "519314e78dc41fc39c2f", 1155113653, 90, 6, "848006"], + [1, "519314e78dc41fc39c2f", 0, 37, 7, "6382936"], + [1, "519314e78dc41fc39c2f", 4134525533l, 37, 7, "4817746"], + [1, "519314e78dc41fc39c2f", 4294967295l, 30, 8, "74552574"], + [1, "519314e78dc41fc39c2f", 3560961279l, 30, 8, "41338585"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 30, 30, 6, "452063"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 1051421492, 30, 6, "661571"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 29, 15, 7, "5452063"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 3486007904l, 15, 7, "2258474"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 0, 60, 8, "92054694"], + [1, "4ce06b24ffc273f2d7924adf5f77e4a7ba98781409d3c442c9ef5f89b701ff6a", 794956808, 60, 8, "40048967"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 31, 15, 6, "080620"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 2513780014l, 15, 6, "548759"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 4102444800l, 37, 7, "2460729"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 1610930926, 37, 7, "1892807"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 2147483647, 37, 8, "05015463"], + [1, "a470c80d0501397b0a254487cea5bf7ce09c5063", 922725035, 37, 8, "16504598"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 4294967295l, 15, 6, "175226"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 840189972, 15, 6, "080722"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 29, 15, 7, "5709807"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 1926118406, 15, 7, "7795831"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 4102444800l, 37, 8, "22291178"], + [1, "4712530205347c29d8ac0aba1125b453a7e34ee3282e110771700f6aed8beda4a414a330377ecdf188e9c446f5bf04379a3b0955733c4e65eabb95e99665f8e7", 2909254729l, 37, 8, "43207193"], + [2, "1d2a42826bd81decc2f1", 4102444800l, 30, 6, "392493"], + [2, "1d2a42826bd81decc2f1", 1095680325, 30, 6, "344980"], + [2, "1d2a42826bd81decc2f1", 2147483648l, 90, 7, "7697857"], + [2, "1d2a42826bd81decc2f1", 702510575, 90, 7, "2542324"], + [2, "1d2a42826bd81decc2f1", 2147483648l, 30, 8, "94001313"], + [2, "1d2a42826bd81decc2f1", 895022827, 30, 8, "05212166"], + [2, "2c6f1a4e8c1fb8bf07d7", 2147483648l, 37, 6, "532042"], + [2, "2c6f1a4e8c1fb8bf07d7", 1957071305, 37, 6, "474640"], + [2, "2c6f1a4e8c1fb8bf07d7", 29, 15, 7, "8726799"], + [2, "2c6f1a4e8c1fb8bf07d7", 2962371382l, 15, 7, "0945077"], + [2, "2c6f1a4e8c1fb8bf07d7", 31, 37, 8, "56225279"], + [2, "2c6f1a4e8c1fb8bf07d7", 3377259681l, 37, 8, "34126316"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 30, 90, 6, "463723"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 642771092, 90, 6, "837542"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 4294967295l, 90, 7, "0873390"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 2418690488l, 90, 7, "7218343"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 2147483648l, 15, 8, "63029657"], + [2, "f212e4e1faa7be995420bb3a059b1d6ad8d5dd88", 4294362063l, 15, 8, "57908285"], + [2, "5aa908958300f5fc2100", 2147483647, 37, 6, "038840"], + [2, "5aa908958300f5fc2100", 3153426934l, 37, 6, "577891"], + [2, "5aa908958300f5fc2100", 0, 37, 7, "3308928"], + [2, "5aa908958300f5fc2100", 3886732662l, 37, 7, "9401464"], + [2, "5aa908958300f5fc2100", 30, 90, 8, "23308928"], + [2, "5aa908958300f5fc2100", 3103524056l, 90, 8, "59171280"] + ]; + + // [secret hex, unix time, code] + const STEAM = [ + ["ad14ca150424f2feeba3f5e6ff708c9030b12d5a", 3186721893l, "N5QR5"], + ["31e1ceef26a37ee6640c65942ca8dcb14b55805f", 3883557096l, "YBTGV"], + ["48e12ed5e83e5cf329074cba3f2a9d4fed05653c", 2707715549l, "7F4TV"], + ["157f497ef5067b2a696c7016aaca5af7a7fe5896", 221299866, "33J34"], + ["f1617555c89e90cd41fd73c89c67c2d1467bd31e", 241887401, "Y97TC"], + ["ad56d2d648e76e622f0f0e143a3ed5d1e6266dc2", 2177274001l, "D7MVH"], + ["8bd218cdfc5589f1d5fa819686a1e8c136946d81", 1719254088, "P8KW2"], + ["3fae4a911e0d3e5591e441d6500768cc91cf1cde", 2517674608l, "KTHQH"], + ["b0d1821bb80147d6d5551bbb33a2b69a1bc55617", 3710479172l, "GVTT5"], + ["ce9808f9ff17018a2b67d3f6de83c0574967c124", 2476233033l, "3C7K7"], + ["50bb20b7cdc8ce84436f136163363740a9070d61", 774300921, "7DD2N"], + ["90ff1bdd0cb8e7f8239f51d74485672b2e892301", 1104091982, "JVJ9N"] + ]; +} diff --git a/test/golden/fr255s.png b/test/golden/fr255s.png Binary files differindex 8619268..fa5b0e5 100644 --- a/test/golden/fr255s.png +++ b/test/golden/fr255s.png diff --git a/test/golden/fr70.png b/test/golden/fr70.png Binary files differindex a0e8fb7..f629cf6 100644 --- a/test/golden/fr70.png +++ b/test/golden/fr70.png diff --git a/test/golden/fr965.png b/test/golden/fr965.png Binary files differindex 81423f7..5b49651 100644 --- a/test/golden/fr965.png +++ b/test/golden/fr965.png diff --git a/test/golden/venusq2.png b/test/golden/venusq2.png Binary files differindex 18a2614..028e185 100644 --- a/test/golden/venusq2.png +++ b/test/golden/venusq2.png diff --git a/test/otp/OtpTest.mc b/test/otp/OtpTest.mc new file mode 100644 index 0000000..598dd89 --- /dev/null +++ b/test/otp/OtpTest.mc @@ -0,0 +1,118 @@ +// Author: cirakg & claude ai +// Summary: Base32, HOTP, TOTP and Steam tests (RFC 4648, RFC 4226, RFC 6238, seeded vectors incl. 2038 and 2100). + +import Toybox.Lang; +import Toybox.Test; + +(:test) +function base32MatchesVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.BASE32.size(); i++) { + var r = TestSupport.row(TestVectors.BASE32, i); + var data = TestSupport.bytes(r, 0); + var text = TestSupport.str(r, 1); + ok = TestSupport.sameString(logger, "encode " + i, Base32.encode(data), text) && ok; + var decoded = Base32.decode(text); + if (!(decoded instanceof Lang.ByteArray) || !Bytes.equal(decoded, data)) { + logger.error("decode " + i + " failed"); + ok = false; + } + } + return ok; +} + +// Lower case, spaces, tabs, hyphens and missing padding are all accepted. +(:test) +function base32IsLenient(logger as Test.Logger) as Boolean { + var expected = Bytes.fromUtf8("foobar"); + var inputs = ["mzxw6ytboi", "MZXW 6YTB OI", "mzxw-6ytb-oi======", "MZXW6YTB\tOI"]; + for (var i = 0; i < inputs.size(); i++) { + var decoded = Base32.decode(inputs[i] as String); + if (!(decoded instanceof Lang.ByteArray) || !Bytes.equal(decoded, expected)) { + logger.error("lenient input " + i + " rejected"); + return false; + } + } + return true; +} + +// Errors name the right position (1-based) or say it's a length problem (0). +(:test) +function base32ReportsErrors(logger as Test.Logger) as Boolean { + var cases = [["MZX1W6", 4], ["MZ X0", 5], ["MZ=X", 4], ["M", 0], ["MZX", 0], ["MY=", 0], ["MZÄW", 3]]; + for (var i = 0; i < cases.size(); i++) { + var c = cases[i] as Array; + var input = c[0] as String; + var result = Base32.decode(input); + if (!(result instanceof Base32.DecodeError) || result.position != (c[1] as Number)) { + logger.error("case " + i + " (" + input + ") not reported as expected"); + return false; + } + logger.debug(input + " -> " + result.message); + } + return true; +} + +// RFC 4226, RFC 6238 and seeded HOTP/TOTP vectors (period 0 means HOTP). +(:test) +function otpMatchesVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.OTP.size(); i++) { + var r = TestSupport.row(TestVectors.OTP, i); + var alg = TestSupport.alg(r, 0); + var secret = TestSupport.bytes(r, 1); + var time = TestSupport.long(r, 2); + var period = TestSupport.num(r, 3); + var digits = TestSupport.num(r, 4); + var code = period == 0 ? Otp.hotp(alg, secret, time, digits) : Otp.totp(alg, secret, time, period, digits); + ok = TestSupport.sameString(logger, "OTP vector " + i, code, TestSupport.str(r, 5)) && ok; + } + logger.debug(TestVectors.OTP.size() + " OTP vectors"); + return ok; +} + +(:test) +function steamMatchesVectors(logger as Test.Logger) as Boolean { + var ok = true; + for (var i = 0; i < TestVectors.STEAM.size(); i++) { + var r = TestSupport.row(TestVectors.STEAM, i); + var code = Otp.steam(TestSupport.bytes(r, 0), TestSupport.long(r, 1)); + ok = TestSupport.sameString(logger, "Steam vector " + i, code, TestSupport.str(r, 2)) && ok; + } + return ok; +} + +// Period boundaries: the counter changes exactly at k * period. +(:test) +function totpPeriodBoundaries(logger as Test.Logger) as Boolean { + return Otp.totpCounter(29l, 30) == 0l && Otp.totpCounter(30l, 30) == 1l && Otp.totpCounter(31l, 30) == 1l + && Otp.secondsRemaining(29l, 30) == 1 && Otp.secondsRemaining(30l, 30) == 30 + && Otp.totpCounter(-5l, 30) == 0l && Otp.secondsRemaining(-5l, 30) == 30 + && Otp.totpCounter(4294967295l, 30) == 143165576l; +} + +(:test) +function otpRejectsBadParameters(logger as Test.Logger) as Boolean { + var rejected = 0; + try { + Otp.hotp(Hashes.SHA1, [1]b, 0l, 5); + } catch (e instanceof Lang.InvalidValueException) { + rejected++; + } + try { + Otp.hotp(Hashes.SHA1, [1]b, 0l, 9); + } catch (e instanceof Lang.InvalidValueException) { + rejected++; + } + try { + Otp.totp(Hashes.SHA1, [1]b, 0l, 0, 6); + } catch (e instanceof Lang.InvalidValueException) { + rejected++; + } + try { + Otp.totp(Hashes.SHA1, [1]b, 0l, 301, 6); + } catch (e instanceof Lang.InvalidValueException) { + rejected++; + } + return rejected == 4; +} diff --git a/test/util/UtilTest.mc b/test/util/UtilTest.mc new file mode 100644 index 0000000..ea689a6 --- /dev/null +++ b/test/util/UtilTest.mc @@ -0,0 +1,66 @@ +// Author: cirakg & claude ai +// Summary: Tests for the byte helpers, the 2038-safe clock widening and the job runner. + +import Toybox.Lang; +import Toybox.Test; + +(:test) +function bytesConversions(logger as Test.Logger) as Boolean { + return Bytes.toHex(Bytes.fromHex("00FFa5")).equals("00ffa5") + && Bytes.equal(Bytes.fromUtf8("é"), [0xc3, 0xa9]b) + && Bytes.fromHex("").size() == 0 && Bytes.toHex([]b).equals("") + && Bytes.equal(Bytes.concat([1]b, [2, 3]b), [1, 2, 3]b) + && Bytes.equal(Bytes.uint64BigEndian(1l), [0, 0, 0, 0, 0, 0, 0, 1]b) + && Bytes.equal(Bytes.uint64BigEndian(-1l), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]b) + && Bytes.equal(Bytes.uint64BigEndian(20000000000l / 30), [0, 0, 0, 0, 0x27, 0xbc, 0x86, 0xaa]b) + && Bytes.equal(Bytes.uint32BigEndian(0x01020304), [1, 2, 3, 4]b); +} + +(:test) +function bytesEqualWipeAndXor(logger as Test.Logger) as Boolean { + var a = [1, 2, 3]b; + var copy = Bytes.copy(a); + Bytes.xorInto(copy, [1, 2, 3]b); + var wiped = [5, 6]b; + Bytes.wipe(wiped); + Bytes.wipe(null); + return Bytes.equal(a, [1, 2, 3]b) && !Bytes.equal(a, [1, 2]b) && !Bytes.equal(a, [1, 2, 4]b) + && Bytes.equal(copy, [0, 0, 0]b) && Bytes.equal(wiped, [0, 0]b); +} + +// After 2038-01-19 the watch's 32-bit clock value is negative; read as +// unsigned it keeps counting up to 2106. +(:test) +function clockWidensTo64Bits(logger as Test.Logger) as Boolean { + return Clock.toUnsigned(0x7FFFFFFF) == 2147483647l + && Clock.toUnsigned(0x7FFFFFFF + 1) == 2147483648l + && Clock.toUnsigned(-1) == 4294967295l + && Clock.toUnsigned(0) == 0l + && Clock.nowUnix(0) > 1700000000l + && Clock.nowUnix(60) - Clock.nowUnix(0) >= 59l; +} + +(:test) +module JobFixtures { + class CountingJob extends Jobs.Job { + var done as Number = 0; + var calls as Number = 0; + + function initialize() { + Job.initialize(); + } + + function step(budget as Number) as Boolean { + calls++; + done += budget; + return done >= 10; + } + } +} + +(:test) +function jobsRunToCompletion(logger as Test.Logger) as Boolean { + var job = new JobFixtures.CountingJob(); + Jobs.runToCompletion(job, 3); + return job.calls == 4 && job.done == 12; +} |
