blob: e3859da5196414f51aef1c6b9f202d024e1bce88 [file] [log] [blame]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>SFrame test vector</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
</head>
<body>
<script>
// Tests taken from https://github.com/eomara/sframe/blob/master/test-vectors.json and updated to cope with key/counter length difference.
// Test suite 1 is AES_CM_128_HMAC_SHA256_4, test suite 2 is AES_CM_128_HMAC_SHA256_8.
// Test suites 3 and 4 are GCM and not yet added here since not supported.
const tests = [
{
"cipher_suite": 1,
"base_key": "101112131415161718191a1b1c1d1e1f",
"key": "343d3290f5c0b936415bea9a43c6f5a2",
"salt": "42d662fbad5cd81eb3aad79a",
"plaintext": "46726f6d2068656176656e6c79206861726d6f6e79202f2f205468697320756e6976657273616c206672616d6520626567616e",
"encryptions": [
{
"kid": "7",
"ctr": "0",
"header": "0700",
"nonce": "42d662fbad5cd81eb3aad79a",
"ciphertext": "070065c67c6fb784631a7db1b589ffb62d75b78e28b0899e632fbbee3b944747a6382d75b6bd3788dc7b71b9295c7fb90b5098f7ad92befabb"
},
{
"kid": "7",
"ctr": "1",
"header": "0701",
"nonce": "42d662fbad5cd81eb3aad79b",
"ciphertext": "0701ec742e98d667be810f153ff0d4dad7969f69b310aa7c6b9cb911e83af09b0f0a6d74772d8195c8c9dae3878fd1cb10edb4176dd4a56026"
},
{
"kid": "7",
"ctr": "2",
"header": "0702",
"nonce": "42d662fbad5cd81eb3aad798",
"ciphertext": "0702ac9b495d37a1e48c712ade5cba72df0bf90f24aa022a454cfb92d8b87cd54335fb6b9eeded6a5aa4e2643d7a09946646001d0afd6a2d5f"
},
{
"kid": "15",
"ctr": "170",
"header": "080faa",
"nonce": "42d662fbad5cd81eb3aad730",
"ciphertext": "080faaeaa5adc70cae0d6ebd36805fa87d2351dd02c55c751cd351a7fdb7f0927b474eae3e800033e08100a440002da17579678b36dcafb808b3"
},
{
"kid": "511",
"ctr": "170",
"header": "0901ffaa",
"nonce": "42d662fbad5cd81eb3aad730",
"ciphertext": "0901ffaaeaa5adc70cae0d6ebd36805fa87d2351dd02c55c751cd351a7fdb7f0927b474eae3e800033e08100a440002da17579678b36dcc0a409c5"
},
{
"kid": "511",
"ctr": "543690",
"header": "2901ff084bca",
"nonce": "42d662fbad5cd81eb3a29c50",
"ciphertext": "2901ff084bca99362198463c4739ebe78d4c1158fc7b7e118e8d035130a583744af343a370ab964a76d31aba68939336187bd251a7f63e9ec25a2bed97"
},
{
"kid": "72057594037927935",
"ctr": "72057594037927935",
"header": "6effffffffffffffffffffffffffff",
"nonce": "42d662fbada327e14c552865",
"ciphertext": "6effffffffffffffffffffffffffffdca3655d5117bc838d6f4382ca468a4f992ff77bfd1d2f4391be6b33e8fb638dc48aa82f57fd91430c714def0b2089c8bfb2ac6a36e584"
},
{
"kid": "92057594037927935",
"ctr": "8",
"header": "0f01470de4df81ffff08",
"nonce": "42d662fbad5cd81eb3aad792",
"ciphertext": "0f01470de4df81ffff084db66f48555956af80a014f06670d7771071afc72ad7452fbb835d353d07d16e771b2ca3593a6a87b643e39370b404a2eb898de8114fb9"
}
]
},
{
"cipher_suite": 2,
"base_key": "202122232425262728292a2b2c2d2e2f",
"key": "3fce747d505e46ec9b92d9f58ee7a5d4",
"salt": "77fbf5f1d82c73f6d2b353c9",
"plaintext": "46726f6d2068656176656e6c79206861726d6f6e79202f2f205468697320756e6976657273616c206672616d6520626567616e",
"encryptions": [
{
"kid": "7",
"ctr": "0",
"header": "0700",
"nonce": "77fbf5f1d82c73f6d2b353c900000000",
"ciphertext": "0700647513fce71aab7fed1e904fd9240343d77092c831f0d58fde0985a0f3e5ba4020e87a7b9c870b5f8f7f628d27690cc1e571e4e8b90ec99c582cfa"
},
{
"kid": "7",
"ctr": "1",
"header": "0701",
"nonce": "77fbf5f1d82c73f6d2b353c8",
"ciphertext": "07019e1bdf713b0d4c02f3dbf50a72ea773286e7da38f3872cc734f3e1b1448aab5009b424e05495214f96d02e4e8f8da975cc808fe931237a6ab700e8"
},
{
"kid": "7",
"ctr": "2",
"header": "0702",
"nonce": "77fbf5f1d82c73f6d2b353cb",
"ciphertext": "070220ad36fd9191453ace2d36a175ad8a69c1f16b8613d14b4f7ef30c68bc5609e349df38155cc1544d7dbfa079e3faae3c7883b479fccb144b0c78a5"
},
{
"kid": "15",
"ctr": "170",
"header": "080faa",
"nonce": "77fbf5f1d82c73f6d2b35363",
"ciphertext": "080faadab9b284a4b9e3aea36b9cdcae4a58e141d3f0f52f240ef80a93dbb8d809ede01b05b2cace18a22fb39c032724481c5baa181d081e260067ccd683"
},
{
"kid": "511",
"ctr": "170",
"header": "0901ffaa",
"nonce": "77fbf5f1d82c73f6d2b35363",
"ciphertext": "0901ffaadab9b284a4b9e3aea36b9cdcae4a58e141d3f0f52f240ef80a93dbb8d809ede01b05b2cace18a22fb39c032724481c5baa181dc24facba5e9f7ea5"
},
{
"kid": "511",
"ctr": "43690",
"header": "1901ffaaaa",
"nonce": "77fbf5f1d82c73f6d2b3f963",
"ciphertext": "1901ffaaaae0f2384e4dc472cb92238b5b722159205c4481665484de66985f155071655ca4e9d1c998781f8c7d439f8d1eb6f6071cd80fd2af2cd093aa260618"
},
{
"kid": "72057594037927935",
"ctr": "72057594037927935",
"header": "6effffffffffffffffffffffffffff",
"nonce": "77fbf5f1d8d38c092d4cac36",
"ciphertext": "6effffffffffffffffffffffffffff4b8c7429d7ee83eec5e53808b80555b1f80b1df9d97877575fa1c7fa35b6119c68ed6543020075959dcc4ca6900a7f9cf1d9366dfcb086029e8966"
},
{
"kid": "92057594037927935",
"ctr": "8",
"header": "0f01470de4df81ffff08",
"nonce": "77fbf5f1d82c73f6d2b353c1",
"ciphertext": "0f01470de4df81ffff08aaf4ea538ad99858a76f87b673dd548459dfbf98906fe82ce159ec738363b2af84d39c34418e2c56609d185ef66a3d7ce8d30547c1c9725439ac12"
}
]
}
];
function hexaDecodeToUint8Array(encoded)
{
return new Uint8Array(encoded.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
}));
}
function hexaEncodeUint8Array(buffer)
{
return Array.prototype.map.call(new Uint8Array(buffer), x => {
return ('00' + x.toString(16)).slice(-2)
}).join('');
}
function numberOrBigIntFromString(string)
{
const value = parseInt(string);
if ((''+ value) === string)
return string;
return BigInt(string);
}
async function doAESCMTest(testSuite, authenticationSize)
{
let testCounter = 0;
const key = await crypto.subtle.importKey("raw", hexaDecodeToUint8Array(testSuite.base_key), "HKDF", false, ["deriveBits", "deriveKey"]);
for (const encryption of testSuite.encryptions) {
testCounter++;
promise_test(async () => {
const transform = new SFrameTransform({ role : 'decrypt', authenticationSize : authenticationSize });
transform.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
const reader = transform.readable.getReader();
const writer = transform.writable.getWriter();
const encryptedData = hexaDecodeToUint8Array(encryption.ciphertext);
writer.write(encryptedData.buffer);
const decrypted = await reader.read();
const text = hexaEncodeUint8Array(new Uint8Array(decrypted.value));
assert_equals(text, testSuite.plaintext);
}, "Decryption test " + testCounter + " for ciphersuite " + testSuite.cipher_suite);
const plaintextData = hexaDecodeToUint8Array(testSuite.plaintext);
promise_test(async () => {
const transform1 = new SFrameTransform({ role : 'encrypt', authenticationSize : authenticationSize });
const transform2 = new SFrameTransform({ role : 'decrypt', authenticationSize : authenticationSize });
transform1.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
transform2.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
const reader = transform2.readable.getReader();
const writer = transform1.writable.getWriter();
transform1.readable.pipeTo(transform2.writable);
if (window.internals)
internals.setSFrameCounter(transform1, encryption.ctr);
else {
const counter = numberOrBigIntFromString(encryption.ctr);
if (typeof counter === "bigint")
return;
for (let i = 0; i < counter; ++i) {
await writer.write(new ArrayBuffer());
await reader.read();
}
}
writer.write(plaintextData.buffer);
const decrypted = await reader.read();
const text = hexaEncodeUint8Array(new Uint8Array(decrypted.value));
assert_equals(text, testSuite.plaintext);
}, "Encryption/Decryption test " + testCounter + " for ciphersuite " + testSuite.cipher_suite);
}
}
doAESCMTest(tests[0], 4);
doAESCMTest(tests[1], 8);
</script>
</body>
</html>