Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android' OR appname == 'thunderbird' && !nightly_build
- Manifest: services/fxaccounts/tests/xpcshell/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { FxAccountsKeys } = ChromeUtils.importESModule(
"resource://gre/modules/FxAccountsKeys.sys.mjs"
);
// of these test vectors.
add_task(async function test_derive_scoped_key_test_vector() {
const keys = new FxAccountsKeys(null);
const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
const kB = "8b2e1303e21eee06a945683b8d495b9bf079ca30baa37eb8392d9ffa4767be45";
const scopedKeyMetadata = {
identifier: "app_key:https%3A//example.com",
keyRotationTimestamp: 1510726317000,
keyRotationSecret:
"517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
};
const scopedKey = await keys._deriveScopedKey(
uid,
CommonUtils.hexToBytes(kB),
"app_key",
scopedKeyMetadata
);
Assert.deepEqual(scopedKey, {
kty: "oct",
kid: "1510726317-Voc-Eb9IpoTINuo9ll7bjA",
k: "Kkbk1_Q0oCcTmggeDH6880bQrxin2RLu5D00NcJazdQ",
});
});
add_task(async function test_derive_legacy_sync_key_test_vector() {
const keys = new FxAccountsKeys(null);
const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
const kB = "eaf9570b7219a4187d3d6bf3cec2770c2e0719b7cc0dfbb38243d6f1881675e9";
const scopedKeyMetadata = {
identifier: SCOPE_APP_SYNC,
keyRotationTimestamp: 1510726317123,
keyRotationSecret:
"0000000000000000000000000000000000000000000000000000000000000000",
};
const scopedKey = await keys._deriveLegacyScopedKey(
uid,
CommonUtils.hexToBytes(kB),
SCOPE_APP_SYNC,
scopedKeyMetadata
);
Assert.deepEqual(scopedKey, {
kty: "oct",
kid: "1510726317123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
});
});
add_task(async function test_derive_multiple_keys_at_once() {
const keys = new FxAccountsKeys(null);
const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
const kB = "eaf9570b7219a4187d3d6bf3cec2770c2e0719b7cc0dfbb38243d6f1881675e9";
const scopedKeysMetadata = {
app_key: {
identifier: "app_key:https%3A//example.com",
keyRotationTimestamp: 1510726317000,
keyRotationSecret:
"517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
},
[SCOPE_APP_SYNC]: {
identifier: SCOPE_APP_SYNC,
keyRotationTimestamp: 1510726318123,
keyRotationSecret:
"0000000000000000000000000000000000000000000000000000000000000000",
},
};
const scopedKeys = await keys._deriveScopedKeys(
uid,
CommonUtils.hexToBytes(kB),
scopedKeysMetadata
);
Assert.deepEqual(scopedKeys, {
app_key: {
kty: "oct",
kid: "1510726317-tUkxiR1lTlFrTgkF0tJidA",
k: "TYK6Hmj86PfKiqsk9DZmX61nxk9VsExGrwo94HP-0wU",
},
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
},
});
});
add_task(function test_check_valid_scoped_keys() {
const keys = new FxAccountsKeys(null);
add_task(function test_missing_key_data() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_unexpected_scope() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: "UnexpectedScope",
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_not_oct_key() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
// Should be "oct"!
kty: "EC",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_invalid_kid_not_timestamp() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
// Does not have the timestamp!
kid: "IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_invalid_kid_not_valid_timestamp() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
// foo is not a valid timestamp!
kid: "foo-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_invalid_kid_not_b64_fingerprint() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
// fingerprint not a valid base64 encoded string.
kid: "1510726318123-notvalidb64][",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_invalid_k_not_base64() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "notavalidb64[]",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_multiple_scoped_keys_one_invalid() {
const scopedKeys = {
// Valid
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
},
// Invalid
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "notavalidb64[]",
scope: SCOPE_APP_SYNC,
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), false);
});
add_task(function test_valid_scopedkeys() {
const scopedKeys = {
[SCOPE_APP_SYNC]: {
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
scope: SCOPE_APP_SYNC,
},
kty: "oct",
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), true);
});
add_task(function test_valid_kid_with_dash() {
const scopedKeys = {
kty: "oct",
// kid contains another dash. The fingerprint must not be truncated.
kid: "1510726318123-I-Qv4onc7VcVE1kTQkyyOw",
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
},
};
Assert.equal(keys.validScopedKeys(scopedKeys), true);
});
});
add_task(async function test_rejects_bad_scoped_key_data() {
const keys = new FxAccountsKeys(null);
const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
const kB = "8b2e1303e21eee06a945683b8d495b9bf079ca30baa37eb8392d9ffa4767be45";
const scopedKeyMetadata = {
identifier: "app_key:https%3A//example.com",
keyRotationTimestamp: 1510726317000,
keyRotationSecret:
"517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
};
await Assert.rejects(
keys._deriveScopedKey(
uid.slice(0, -1),
CommonUtils.hexToBytes(kB),
"app_key",
scopedKeyMetadata
),
/uid must be a 32-character hex string/
);
await Assert.rejects(
keys._deriveScopedKey(
uid.slice(0, -1) + "Q",
CommonUtils.hexToBytes(kB),
"app_key",
scopedKeyMetadata
),
/uid must be a 32-character hex string/
);
await Assert.rejects(
keys._deriveScopedKey(
uid,
CommonUtils.hexToBytes(kB).slice(0, -1),
"app_key",
scopedKeyMetadata
),
/kBbytes must be exactly 32 bytes/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
identifier: "foo",
}),
/identifier must be a string of length >= 10/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
identifier: {},
}),
/identifier must be a string of length >= 10/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
keyRotationTimestamp: "xyz",
}),
/keyRotationTimestamp must be a number/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
keyRotationTimestamp: 12345,
}),
/keyRotationTimestamp must round to a 10-digit number/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
keyRotationSecret: scopedKeyMetadata.keyRotationSecret.slice(0, -1),
}),
/keyRotationSecret must be a 64-character hex string/
);
await Assert.rejects(
keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
...scopedKeyMetadata,
keyRotationSecret: scopedKeyMetadata.keyRotationSecret.slice(0, -1) + "z",
}),
/keyRotationSecret must be a 64-character hex string/
);
});