/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict" ;
const { FxAccountsKeys } = ChromeUtils.importESModule(
"resource://gre/modules/FxAccountsKeys.sys.mjs"
);
// Ref https://github.com/mozilla/fxa-crypto-relier/ for the details
// 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
"https://identity.mozilla.com/apps/otherscope ": {
kty:
"oct" ,
kid:
"1510726318123-IqQv4onc7VcVE1kTQkyyOw" ,
k:
"DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang" ,
scope:
"https://identity.mozilla.com/apps/otherscope ",
},
// 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,
},
"https://identity.mozilla.com/apps/otherscope ": {
kty:
"oct" ,
kid:
"1510726318123-IqQv4onc7VcVE1kTQkyyOw" ,
k:
"DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang" ,
scope:
"https://identity.mozilla.com/apps/otherscope ",
},
};
Assert .equal(keys.validScopedKeys(scopedKeys),
true );
});
add_task(
function test_valid_kid_with_dash() {
const scopedKeys = {
"https://identity.mozilla.com/apps/oldsync ": {
kty:
"oct" ,
// kid contains another dash. The fingerprint must not be truncated.
kid:
"1510726318123-I-Qv4onc7VcVE1kTQkyyOw" ,
k:
"DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang" ,
scope:
"https://identity.mozilla.com/apps/oldsync ",
},
};
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/
);
});
Messung V0.5 in Prozent C=94 H=95 G=94
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland