Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
// This is a kinto-specific test...
Services.prefs.setBoolPref("webextensions.storage.sync.kinto", true);
const {
KintoStorageTestUtils: { EncryptionRemoteTransformer },
} = ChromeUtils.importESModule(
"resource://gre/modules/ExtensionStorageSyncKinto.sys.mjs"
);
const { CryptoUtils } = ChromeUtils.importESModule(
);
const { Utils } = ChromeUtils.importESModule(
);
/**
* Like Assert.throws, but for generators.
*
* @param {string | object | Function} constraint
* What to use to check the exception.
* @param {Function} f
* The function to call.
*/
async function throwsGen(constraint, f) {
let threw = false;
let exception;
try {
await f();
} catch (e) {
threw = true;
exception = e;
}
ok(threw, "did not throw an exception");
const debuggingMessage = `got ${exception}, expected ${constraint}`;
if (typeof constraint === "function") {
ok(constraint(exception), debuggingMessage);
} else {
let message = exception;
if (typeof exception === "object") {
message = exception.message;
}
Assert.strictEqual(constraint, message, debuggingMessage);
}
}
/**
* An EncryptionRemoteTransformer that uses a fixed key bundle,
* suitable for testing.
*/
class StaticKeyEncryptionRemoteTransformer extends EncryptionRemoteTransformer {
constructor(keyBundle) {
super();
this.keyBundle = keyBundle;
}
getKeys() {
return Promise.resolve(this.keyBundle);
}
}
const BORING_KB =
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
let transformer;
add_task(async function setup() {
const STRETCHED_KEY = await CryptoUtils.hkdfLegacy(
BORING_KB,
undefined,
`testing storage.sync encryption`,
2 * 32
);
const KEY_BUNDLE = {
hmacKey: STRETCHED_KEY.slice(0, 32),
encryptionKeyB64: btoa(STRETCHED_KEY.slice(32, 64)),
};
transformer = new StaticKeyEncryptionRemoteTransformer(KEY_BUNDLE);
});
add_task(async function test_encryption_transformer_roundtrip() {
const POSSIBLE_DATAS = [
"string",
2, // number
[1, 2, 3], // array
{ key: "value" }, // object
];
for (let data of POSSIBLE_DATAS) {
const record = { data, id: "key-some_2D_key", key: "some-key" };
deepEqual(
record,
await transformer.decode(await transformer.encode(record))
);
}
});
add_task(async function test_refuses_to_decrypt_tampered() {
const encryptedRecord = await transformer.encode({
data: [1, 2, 3],
id: "key-some_2D_key",
key: "some-key",
});
const tamperedHMAC = Object.assign({}, encryptedRecord, {
hmac: "0000000000000000000000000000000000000000000000000000000000000001",
});
await throwsGen(Utils.isHMACMismatch, async function () {
await transformer.decode(tamperedHMAC);
});
const tamperedIV = Object.assign({}, encryptedRecord, {
IV: "aaaaaaaaaaaaaaaaaaaaaa==",
});
await throwsGen(Utils.isHMACMismatch, async function () {
await transformer.decode(tamperedIV);
});
});