tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_keys.js (10216B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { FxAccountsKeys } = ChromeUtils.importESModule(
      7  "resource://gre/modules/FxAccountsKeys.sys.mjs"
      8 );
      9 
     10 // Ref https://github.com/mozilla/fxa-crypto-relier/ for the details
     11 // of these test vectors.
     12 
     13 add_task(async function test_derive_scoped_key_test_vector() {
     14  const keys = new FxAccountsKeys(null);
     15  const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
     16  const kB = "8b2e1303e21eee06a945683b8d495b9bf079ca30baa37eb8392d9ffa4767be45";
     17  const scopedKeyMetadata = {
     18    identifier: "app_key:https%3A//example.com",
     19    keyRotationTimestamp: 1510726317000,
     20    keyRotationSecret:
     21      "517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
     22  };
     23 
     24  const scopedKey = await keys._deriveScopedKey(
     25    uid,
     26    CommonUtils.hexToBytes(kB),
     27    "app_key",
     28    scopedKeyMetadata
     29  );
     30 
     31  Assert.deepEqual(scopedKey, {
     32    kty: "oct",
     33    kid: "1510726317-Voc-Eb9IpoTINuo9ll7bjA",
     34    k: "Kkbk1_Q0oCcTmggeDH6880bQrxin2RLu5D00NcJazdQ",
     35  });
     36 });
     37 
     38 add_task(async function test_derive_legacy_sync_key_test_vector() {
     39  const keys = new FxAccountsKeys(null);
     40  const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
     41  const kB = "eaf9570b7219a4187d3d6bf3cec2770c2e0719b7cc0dfbb38243d6f1881675e9";
     42  const scopedKeyMetadata = {
     43    identifier: SCOPE_APP_SYNC,
     44    keyRotationTimestamp: 1510726317123,
     45    keyRotationSecret:
     46      "0000000000000000000000000000000000000000000000000000000000000000",
     47  };
     48 
     49  const scopedKey = await keys._deriveLegacyScopedKey(
     50    uid,
     51    CommonUtils.hexToBytes(kB),
     52    SCOPE_APP_SYNC,
     53    scopedKeyMetadata
     54  );
     55 
     56  Assert.deepEqual(scopedKey, {
     57    kty: "oct",
     58    kid: "1510726317123-IqQv4onc7VcVE1kTQkyyOw",
     59    k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
     60  });
     61 });
     62 
     63 add_task(async function test_derive_multiple_keys_at_once() {
     64  const keys = new FxAccountsKeys(null);
     65  const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
     66  const kB = "eaf9570b7219a4187d3d6bf3cec2770c2e0719b7cc0dfbb38243d6f1881675e9";
     67  const scopedKeysMetadata = {
     68    app_key: {
     69      identifier: "app_key:https%3A//example.com",
     70      keyRotationTimestamp: 1510726317000,
     71      keyRotationSecret:
     72        "517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
     73    },
     74    [SCOPE_APP_SYNC]: {
     75      identifier: SCOPE_APP_SYNC,
     76      keyRotationTimestamp: 1510726318123,
     77      keyRotationSecret:
     78        "0000000000000000000000000000000000000000000000000000000000000000",
     79    },
     80  };
     81 
     82  const scopedKeys = await keys._deriveScopedKeys(
     83    uid,
     84    CommonUtils.hexToBytes(kB),
     85    scopedKeysMetadata
     86  );
     87 
     88  Assert.deepEqual(scopedKeys, {
     89    app_key: {
     90      kty: "oct",
     91      kid: "1510726317-tUkxiR1lTlFrTgkF0tJidA",
     92      k: "TYK6Hmj86PfKiqsk9DZmX61nxk9VsExGrwo94HP-0wU",
     93    },
     94    [SCOPE_APP_SYNC]: {
     95      kty: "oct",
     96      kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
     97      k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
     98    },
     99  });
    100 });
    101 
    102 add_task(function test_check_valid_scoped_keys() {
    103  const keys = new FxAccountsKeys(null);
    104  add_task(function test_missing_key_data() {
    105    const scopedKeys = {
    106      [SCOPE_APP_SYNC]: {
    107        kty: "oct",
    108        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    109        scope: SCOPE_APP_SYNC,
    110      },
    111    };
    112    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    113  });
    114  add_task(function test_unexpected_scope() {
    115    const scopedKeys = {
    116      [SCOPE_APP_SYNC]: {
    117        kty: "oct",
    118        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    119        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    120        scope: "UnexpectedScope",
    121      },
    122    };
    123    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    124  });
    125  add_task(function test_not_oct_key() {
    126    const scopedKeys = {
    127      [SCOPE_APP_SYNC]: {
    128        // Should be "oct"!
    129        kty: "EC",
    130        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    131        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    132        scope: SCOPE_APP_SYNC,
    133      },
    134    };
    135    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    136  });
    137  add_task(function test_invalid_kid_not_timestamp() {
    138    const scopedKeys = {
    139      [SCOPE_APP_SYNC]: {
    140        kty: "oct",
    141        // Does not have the timestamp!
    142        kid: "IqQv4onc7VcVE1kTQkyyOw",
    143        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    144        scope: SCOPE_APP_SYNC,
    145      },
    146    };
    147    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    148  });
    149  add_task(function test_invalid_kid_not_valid_timestamp() {
    150    const scopedKeys = {
    151      [SCOPE_APP_SYNC]: {
    152        kty: "oct",
    153        // foo is not a valid timestamp!
    154        kid: "foo-IqQv4onc7VcVE1kTQkyyOw",
    155        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    156        scope: SCOPE_APP_SYNC,
    157      },
    158    };
    159    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    160  });
    161  add_task(function test_invalid_kid_not_b64_fingerprint() {
    162    const scopedKeys = {
    163      [SCOPE_APP_SYNC]: {
    164        kty: "oct",
    165        // fingerprint not a valid base64 encoded string.
    166        kid: "1510726318123-notvalidb64][",
    167        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    168        scope: SCOPE_APP_SYNC,
    169      },
    170    };
    171    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    172  });
    173  add_task(function test_invalid_k_not_base64() {
    174    const scopedKeys = {
    175      [SCOPE_APP_SYNC]: {
    176        kty: "oct",
    177        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    178        k: "notavalidb64[]",
    179        scope: SCOPE_APP_SYNC,
    180      },
    181    };
    182    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    183  });
    184 
    185  add_task(function test_multiple_scoped_keys_one_invalid() {
    186    const scopedKeys = {
    187      // Valid
    188      "https://identity.mozilla.com/apps/otherscope": {
    189        kty: "oct",
    190        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    191        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    192        scope: "https://identity.mozilla.com/apps/otherscope",
    193      },
    194      // Invalid
    195      [SCOPE_APP_SYNC]: {
    196        kty: "oct",
    197        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    198        k: "notavalidb64[]",
    199        scope: SCOPE_APP_SYNC,
    200      },
    201    };
    202    Assert.equal(keys.validScopedKeys(scopedKeys), false);
    203  });
    204 
    205  add_task(function test_valid_scopedkeys() {
    206    const scopedKeys = {
    207      [SCOPE_APP_SYNC]: {
    208        kty: "oct",
    209        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    210        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    211        scope: SCOPE_APP_SYNC,
    212      },
    213      "https://identity.mozilla.com/apps/otherscope": {
    214        kty: "oct",
    215        kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
    216        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    217        scope: "https://identity.mozilla.com/apps/otherscope",
    218      },
    219    };
    220    Assert.equal(keys.validScopedKeys(scopedKeys), true);
    221  });
    222  add_task(function test_valid_kid_with_dash() {
    223    const scopedKeys = {
    224      "https://identity.mozilla.com/apps/oldsync": {
    225        kty: "oct",
    226        // kid contains another dash. The fingerprint must not be truncated.
    227        kid: "1510726318123-I-Qv4onc7VcVE1kTQkyyOw",
    228        k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
    229        scope: "https://identity.mozilla.com/apps/oldsync",
    230      },
    231    };
    232    Assert.equal(keys.validScopedKeys(scopedKeys), true);
    233  });
    234 });
    235 
    236 add_task(async function test_rejects_bad_scoped_key_data() {
    237  const keys = new FxAccountsKeys(null);
    238  const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
    239  const kB = "8b2e1303e21eee06a945683b8d495b9bf079ca30baa37eb8392d9ffa4767be45";
    240  const scopedKeyMetadata = {
    241    identifier: "app_key:https%3A//example.com",
    242    keyRotationTimestamp: 1510726317000,
    243    keyRotationSecret:
    244      "517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
    245  };
    246 
    247  await Assert.rejects(
    248    keys._deriveScopedKey(
    249      uid.slice(0, -1),
    250      CommonUtils.hexToBytes(kB),
    251      "app_key",
    252      scopedKeyMetadata
    253    ),
    254    /uid must be a 32-character hex string/
    255  );
    256  await Assert.rejects(
    257    keys._deriveScopedKey(
    258      uid.slice(0, -1) + "Q",
    259      CommonUtils.hexToBytes(kB),
    260      "app_key",
    261      scopedKeyMetadata
    262    ),
    263    /uid must be a 32-character hex string/
    264  );
    265  await Assert.rejects(
    266    keys._deriveScopedKey(
    267      uid,
    268      CommonUtils.hexToBytes(kB).slice(0, -1),
    269      "app_key",
    270      scopedKeyMetadata
    271    ),
    272    /kBbytes must be exactly 32 bytes/
    273  );
    274  await Assert.rejects(
    275    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    276      ...scopedKeyMetadata,
    277      identifier: "foo",
    278    }),
    279    /identifier must be a string of length >= 10/
    280  );
    281  await Assert.rejects(
    282    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    283      ...scopedKeyMetadata,
    284      identifier: {},
    285    }),
    286    /identifier must be a string of length >= 10/
    287  );
    288  await Assert.rejects(
    289    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    290      ...scopedKeyMetadata,
    291      keyRotationTimestamp: "xyz",
    292    }),
    293    /keyRotationTimestamp must be a number/
    294  );
    295  await Assert.rejects(
    296    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    297      ...scopedKeyMetadata,
    298      keyRotationTimestamp: 12345,
    299    }),
    300    /keyRotationTimestamp must round to a 10-digit number/
    301  );
    302  await Assert.rejects(
    303    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    304      ...scopedKeyMetadata,
    305      keyRotationSecret: scopedKeyMetadata.keyRotationSecret.slice(0, -1),
    306    }),
    307    /keyRotationSecret must be a 64-character hex string/
    308  );
    309  await Assert.rejects(
    310    keys._deriveScopedKey(uid, CommonUtils.hexToBytes(kB), "app_key", {
    311      ...scopedKeyMetadata,
    312      keyRotationSecret: scopedKeyMetadata.keyRotationSecret.slice(0, -1) + "z",
    313    }),
    314    /keyRotationSecret must be a 64-character hex string/
    315  );
    316 });