tor-browser

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

test_WebCrypto_PBKDF2.html (11988B)


      1 <!DOCTYPE html>
      2 <html>
      3 
      4 <head>
      5 <title>WebCrypto Test Suite</title>
      6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      7 <link rel="stylesheet" href="./test_WebCrypto.css"/>
      8 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      9 
     10 <!-- Utilities for manipulating ABVs -->
     11 <script src="util.js"></script>
     12 
     13 <!-- A simple wrapper around IndexedDB -->
     14 <script src="simpledb.js"></script>
     15 
     16 <!-- Test vectors drawn from the literature -->
     17 <script src="./test-vectors.js"></script>
     18 
     19 <!-- General testing framework -->
     20 <script src="./test-array.js"></script>
     21 
     22 <script>/* <![CDATA[*/
     23 "use strict";
     24 
     25 // -----------------------------------------------------------------------------
     26 TestArray.addTest(
     27  "Import raw PBKDF2 key",
     28  function() {
     29    var that = this;
     30    var alg = "PBKDF2";
     31    var key = new TextEncoder().encode("password");
     32 
     33    crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"]).then(
     34      complete(that, hasKeyFields),
     35      error(that)
     36    );
     37  }
     38 );
     39 
     40 // -----------------------------------------------------------------------------
     41 TestArray.addTest(
     42  "Unwrapping a PBKDF2 key in PKCS8 format should fail",
     43  function() {
     44    var that = this;
     45    var pbkdf2Key = new TextEncoder().encode("password");
     46    var alg = {name: "AES-GCM", length: 256, iv: new Uint8Array(16)};
     47    var wrappingKey;
     48 
     49    function wrap(x) {
     50      wrappingKey = x;
     51      return crypto.subtle.encrypt(alg, wrappingKey, pbkdf2Key);
     52    }
     53 
     54    function unwrap(x) {
     55      return crypto.subtle.unwrapKey(
     56        "pkcs8", x, wrappingKey, alg, "PBKDF2", false, ["deriveBits"]);
     57    }
     58 
     59    crypto.subtle.generateKey(alg, false, ["encrypt", "unwrapKey"])
     60      .then(wrap, error(that))
     61      .then(unwrap, error(that))
     62      .then(error(that), complete(that));
     63  }
     64 );
     65 
     66 // -----------------------------------------------------------------------------
     67 TestArray.addTest(
     68  "Import raw PBKDF2 key and derive bits using HMAC-SHA-1",
     69  function() {
     70    var that = this;
     71    var alg = "PBKDF2";
     72    var key = tv.pbkdf2_sha1.password;
     73 
     74    function doDerive(x) {
     75      if (!hasKeyFields(x)) {
     76        throw new Error("Invalid key; missing field(s)");
     77      }
     78 
     79      var algo = {
     80        name: "PBKDF2",
     81        hash: "SHA-1",
     82        salt: tv.pbkdf2_sha1.salt,
     83        iterations: tv.pbkdf2_sha1.iterations,
     84      };
     85      return crypto.subtle.deriveBits(algo, x, tv.pbkdf2_sha1.length);
     86    }
     87    function fail(x) { console.log("failing"); error(that)(x); }
     88 
     89    crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
     90      .then( doDerive, fail )
     91      .then( memcmp_complete(that, tv.pbkdf2_sha1.derived), fail );
     92  }
     93 );
     94 
     95 // -----------------------------------------------------------------------------
     96 TestArray.addTest(
     97  "Import a PBKDF2 key in JWK format and derive bits using HMAC-SHA-1",
     98  function() {
     99    var that = this;
    100    var alg = "PBKDF2";
    101 
    102    function doDerive(x) {
    103      if (!hasKeyFields(x)) {
    104        throw new Error("Invalid key; missing field(s)");
    105      }
    106 
    107      var algo = {
    108        name: "PBKDF2",
    109        hash: "SHA-1",
    110        salt: tv.pbkdf2_sha1.salt,
    111        iterations: tv.pbkdf2_sha1.iterations,
    112      };
    113      return crypto.subtle.deriveBits(algo, x, tv.pbkdf2_sha1.length);
    114    }
    115    function fail(x) { console.log("failing"); error(that)(x); }
    116 
    117    crypto.subtle.importKey("jwk", tv.pbkdf2_sha1.jwk, alg, false, ["deriveBits"])
    118      .then( doDerive, fail )
    119      .then( memcmp_complete(that, tv.pbkdf2_sha1.derived), fail );
    120  }
    121 );
    122 
    123 // -----------------------------------------------------------------------------
    124 TestArray.addTest(
    125  "Import raw PBKDF2 key and derive a new key using HMAC-SHA-1",
    126  function() {
    127    var that = this;
    128    var alg = "PBKDF2";
    129    var key = tv.pbkdf2_sha1.password;
    130 
    131    function doDerive(x) {
    132      if (!hasKeyFields(x)) {
    133        throw new Error("Invalid key; missing field(s)");
    134      }
    135 
    136      var algo = {
    137        name: "PBKDF2",
    138        hash: "SHA-1",
    139        salt: tv.pbkdf2_sha1.salt,
    140        iterations: tv.pbkdf2_sha1.iterations,
    141      };
    142 
    143      var algDerived = {
    144        name: "HMAC",
    145        hash: {name: "SHA-1"},
    146      };
    147 
    148      return crypto.subtle.deriveKey(algo, x, algDerived, false, ["sign", "verify"])
    149        .then(function(y) {
    150          if (!hasKeyFields(y)) {
    151            throw new Error("Invalid key; missing field(s)");
    152          }
    153 
    154          if (y.algorithm.length != 512) {
    155            throw new Error("Invalid key; incorrect length");
    156          }
    157 
    158          return y;
    159        });
    160    }
    161 
    162    function doSignAndVerify(x) {
    163      var data = new Uint8Array(1024);
    164 
    165      return crypto.subtle.sign("HMAC", x, data)
    166        .then(function(sig) {
    167          return crypto.subtle.verify("HMAC", x, sig, data);
    168        });
    169    }
    170 
    171    function fail(x) { console.log("failing"); error(that)(x); }
    172 
    173    crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"])
    174      .then( doDerive, fail )
    175      .then( doSignAndVerify, fail )
    176      .then( complete(that, x => x), fail );
    177  }
    178 );
    179 
    180 // -----------------------------------------------------------------------------
    181 TestArray.addTest(
    182  "Import raw PBKDF2 key and derive a new key using HMAC-SHA-1 with custom length",
    183  function() {
    184    var that = this;
    185 
    186    function doDerive(x) {
    187      var alg = {
    188        name: "PBKDF2",
    189        hash: "SHA-1",
    190        salt: tv.pbkdf2_sha1.salt,
    191        iterations: tv.pbkdf2_sha1.iterations,
    192      };
    193 
    194      var algDerived = {name: "HMAC", hash: "SHA-1", length: 128};
    195      return crypto.subtle.deriveKey(alg, x, algDerived, false, ["sign"]);
    196    }
    197 
    198    var password = crypto.getRandomValues(new Uint8Array(8));
    199    crypto.subtle.importKey("raw", password, "PBKDF2", false, ["deriveKey"])
    200      .then(doDerive)
    201      .then(complete(that, function(x) {
    202        return hasKeyFields(x) && x.algorithm.length == 128;
    203      }), error(that));
    204  }
    205 );
    206 
    207 // -----------------------------------------------------------------------------
    208 TestArray.addTest(
    209  "Import raw PBKDF2 key and derive bits using HMAC-SHA-256",
    210  function() {
    211    var that = this;
    212    var alg = "PBKDF2";
    213    var key = tv.pbkdf2_sha256.password;
    214 
    215    function doDerive(x) {
    216      if (!hasKeyFields(x)) {
    217        throw new Error("Invalid key; missing field(s)");
    218      }
    219 
    220      var algo = {
    221        name: "PBKDF2",
    222        hash: "SHA-256",
    223        salt: tv.pbkdf2_sha256.salt,
    224        iterations: tv.pbkdf2_sha256.iterations,
    225      };
    226      return crypto.subtle.deriveBits(algo, x, tv.pbkdf2_sha256.length);
    227    }
    228    function fail(x) { console.log("failing"); error(that)(x); }
    229 
    230    crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
    231      .then( doDerive, fail )
    232      .then( memcmp_complete(that, tv.pbkdf2_sha256.derived), fail );
    233  }
    234 );
    235 
    236 // -----------------------------------------------------------------------------
    237 TestArray.addTest(
    238  "Import raw PBKDF2 zero-length key and derive bits using HMAC-SHA-256",
    239  function() {
    240    var that = this;
    241    var alg = "PBKDF2";
    242    var key = tv.pbkdf2_sha256_no_pwd.password;
    243 
    244    function doDerive(x) {
    245      if (!hasKeyFields(x)) {
    246        throw new Error("Invalid key; missing field(s)");
    247      }
    248 
    249      var algo = {
    250        name: "PBKDF2",
    251        hash: "SHA-256",
    252        salt: tv.pbkdf2_sha256_no_pwd.salt,
    253        iterations: tv.pbkdf2_sha256_no_pwd.iterations,
    254      };
    255      return crypto.subtle.deriveBits(algo, x, tv.pbkdf2_sha256_no_pwd.length);
    256    }
    257    function fail(x) { console.log("failing"); error(that)(x); }
    258 
    259    crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
    260      .then( doDerive, fail )
    261      .then( memcmp_complete(that, tv.pbkdf2_sha256_no_pwd.derived), fail );
    262  }
    263 );
    264 
    265 // -----------------------------------------------------------------------------
    266 TestArray.addTest(
    267  "Import raw PBKDF2 key and derive bits using HMAC-SHA-256 with zero-length salt",
    268  function() {
    269    var that = this;
    270    var importAlg = { name: "PBKDF2", hash: "SHA-256" };
    271    var key = tv.pbkdf2_sha256_no_salt.password;
    272 
    273    function doDerive(x) {
    274      if (!hasKeyFields(x)) {
    275        throw new Error("Invalid key; missing field(s)");
    276      }
    277 
    278      var deriveAlg = {
    279        name: "PBKDF2",
    280        hash: "SHA-256",
    281        salt: new Uint8Array(0),
    282        iterations: tv.pbkdf2_sha256_no_salt.iterations,
    283      };
    284      return crypto.subtle.deriveBits(deriveAlg, x, tv.pbkdf2_sha256_no_salt.length);
    285    }
    286    function fail(x) { console.log("failing"); error(that)(x); }
    287 
    288    crypto.subtle.importKey("raw", key, importAlg, false, ["deriveBits"])
    289      .then( doDerive, fail )
    290      .then( memcmp_complete(that, tv.pbkdf2_sha256_no_salt.derived), fail );
    291  }
    292 );
    293 
    294 // -----------------------------------------------------------------------------
    295 TestArray.addTest(
    296  "Fail while deriving key with bad hash name",
    297  function() {
    298    var that = this;
    299    var alg = "PBKDF2";
    300    var key = tv.pbkdf2_sha256.password;
    301 
    302    function doDerive(x) {
    303      if (!hasKeyFields(x)) {
    304        throw new Error("Invalid key; missing field(s)");
    305      }
    306 
    307      var algo = {
    308        name: "PBKDF2",
    309        hash: "SHA256",
    310        salt: tv.pbkdf2_sha256.salt,
    311        iterations: tv.pbkdf2_sha256.iterations,
    312      };
    313      return crypto.subtle.deriveBits(algo, x, 32).then(
    314        error(that),
    315        complete(that, function(e) {
    316          return e.name == "NotSupportedError";
    317        })
    318      );
    319    }
    320    function fail(x) { console.log("failing"); error(that)(x); }
    321 
    322    crypto.subtle.importKey("raw", key, alg, false, ["deriveKey", "deriveBits"])
    323      .then( doDerive, fail );
    324  }
    325 );
    326 
    327 // -----------------------------------------------------------------------------
    328 TestArray.addTest(
    329  "Fail while deriving bits given null length",
    330  function() {
    331    var that = this;
    332    var alg = "PBKDF2";
    333    var key = tv.pbkdf2_sha256.password;
    334 
    335    function doDerive(x) {
    336      if (!hasKeyFields(x)) {
    337        throw new Error("Invalid key; missing field(s)");
    338      }
    339 
    340      var algo = {
    341        name: "PBKDF2",
    342        hash: "SHA-256",
    343        salt: tv.pbkdf2_sha256.salt,
    344        iterations: tv.pbkdf2_sha256.iterations,
    345      };
    346      return crypto.subtle.deriveBits(algo, x, null).then(
    347        error(that),
    348        complete(that, function(e) {
    349          return e.name == "OperationError";
    350        })
    351      );
    352    }
    353    function fail(x) { console.log("failing"); error(that)(x); }
    354 
    355    crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
    356      .then( doDerive, fail );
    357  }
    358 );
    359 
    360 // -----------------------------------------------------------------------------
    361 TestArray.addTest(
    362  "Fail while deriving key of null length",
    363  function() {
    364    var that = this;
    365    var alg = "PBKDF2";
    366    var key = tv.pbkdf2_sha256.password;
    367 
    368    function doDerive(x) {
    369      if (!hasKeyFields(x)) {
    370        throw new Error("Invalid key; missing field(s)");
    371      }
    372 
    373      var algo = {
    374        name: "PBKDF2",
    375        hash: "SHA-256",
    376        salt: tv.pbkdf2_sha256.salt,
    377        iterations: tv.pbkdf2_sha256.iterations,
    378      };
    379      return crypto.subtle.deriveKey(algo, x, {name: "AES-GCM", length: null}, true, ["encrypt"]).then(
    380        error(that),
    381        complete(that, function(e) {
    382          return e.name == "OperationError";
    383        })
    384      );
    385    }
    386    function fail(x) { console.log("failing"); error(that)(x); }
    387 
    388    crypto.subtle.importKey("raw", key, alg, false, ["deriveKey", "deriveBits"])
    389      .then( doDerive, fail );
    390  }
    391 );
    392 /* ]]>*/</script>
    393 </head>
    394 
    395 <body>
    396 
    397 <div id="content">
    398 <div id="head">
    399 	<b>Web</b>Crypto<br>
    400 </div>
    401 
    402    <div id="start" onclick="start();">RUN ALL</div>
    403 
    404    <div id="resultDiv" class="content">
    405    Summary:
    406    <span class="pass"><span id="passN">0</span> passed, </span>
    407    <span class="fail"><span id="failN">0</span> failed, </span>
    408    <span class="pending"><span id="pendingN">0</span> pending.</span>
    409    <br/>
    410    <br/>
    411 
    412    <table id="results">
    413        <tr>
    414            <th>Test</th>
    415            <th>Result</th>
    416            <th>Time</th>
    417        </tr>
    418    </table>
    419 
    420    </div>
    421 
    422    <div id="foot"></div>
    423 </div>
    424 
    425 </body>
    426 </html>