tor-browser

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

test_WebCrypto_RSA_PSS.html (11836B)


      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 // Generating 2048-bit keys takes some time.
     26 SimpleTest.requestLongerTimeout(2);
     27 
     28 // -----------------------------------------------------------------------------
     29 TestArray.addTest(
     30  "RSA-PSS key generation (SHA-1, 1024-bit)",
     31  function() {
     32    var that = this;
     33    var alg = {
     34      name: "RSA-PSS",
     35      hash: "SHA-1",
     36      modulusLength: 1024,
     37      publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
     38    };
     39 
     40    crypto.subtle.generateKey(alg, false, ["sign", "verify"])
     41      .then(complete(that), error(that));
     42  }
     43 );
     44 
     45 // -----------------------------------------------------------------------------
     46 TestArray.addTest(
     47  "RSA-PSS key generation and sign/verify round-trip (SHA-256, 2048-bit)",
     48  function() {
     49    var that = this;
     50    var alg = {
     51      name: "RSA-PSS",
     52      hash: "SHA-256",
     53      modulusLength: 2048,
     54      publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
     55    };
     56 
     57    var privKey, pubKey;
     58    var data = crypto.getRandomValues(new Uint8Array(128));
     59    function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
     60    function doSign() {
     61      return crypto.subtle.sign({name: "RSA-PSS", saltLength: 32}, privKey, data);
     62    }
     63    function doVerify(x) {
     64      return crypto.subtle.verify({name: "RSA-PSS", saltLength: 32}, pubKey, x, data);
     65    }
     66 
     67    crypto.subtle.generateKey(alg, false, ["sign", "verify"])
     68      .then(setKey, error(that))
     69      .then(doSign, error(that))
     70      .then(doVerify, error(that))
     71      .then(complete(that, x => x), error(that));
     72  }
     73 );
     74 
     75 // -----------------------------------------------------------------------------
     76 TestArray.addTest(
     77  "RSA-PSS verify known signature (SHA-1, 1024-bit)",
     78  function() {
     79    var that = this;
     80    var alg = {name: "RSA-PSS", hash: "SHA-1"};
     81    var vec = tv.rsapss;
     82 
     83    function doVerify(x) {
     84      return crypto.subtle.verify({name: "RSA-PSS", saltLength: vec.saltLength}, x, vec.sig, vec.data);
     85    }
     86 
     87    crypto.subtle.importKey("spki", vec.spki, alg, false, ["verify"])
     88      .then(doVerify, error(that))
     89      .then(complete(that, x => x), error(that));
     90  }
     91 );
     92 
     93 // -----------------------------------------------------------------------------
     94 TestArray.addTest(
     95  "Test invalid RSA-PSS signatures",
     96  function() {
     97    var that = this;
     98    var alg = {name: "RSA-PSS", hash: "SHA-1"};
     99    var vec = tv.rsapss;
    100 
    101    function doVerify(x) {
    102      var algo = {name: "RSA-PSS", saltLength: vec.saltLength};
    103      var clone1 = new Uint8Array(vec.data);
    104      var clone2 = new Uint8Array(vec.data);
    105      clone1[clone1.byteLength - 1] ^= 1;
    106      clone2[0] ^= 1;
    107 
    108      return Promise.all([
    109        crypto.subtle.verify(algo, x, vec.sig, clone1),
    110        crypto.subtle.verify(algo, x, vec.sig, clone2),
    111        crypto.subtle.verify(algo, x, vec.sig, vec.data.slice(1)),
    112        crypto.subtle.verify(algo, x, vec.sig, vec.data.slice(0, vec.data.byteLength - 1)),
    113      ]);
    114    }
    115 
    116    crypto.subtle.importKey("spki", vec.spki, alg, false, ["verify"])
    117      .then(doVerify, error(that))
    118      .then(results => results.every(x => !x))
    119      .then(complete(that, x => x), error(that));
    120  }
    121 );
    122 
    123 // -----------------------------------------------------------------------------
    124 TestArray.addTest(
    125  "RSA-PSS verify known signature (SHA-1, 1024-bit, JWK)",
    126  function() {
    127    var that = this;
    128    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    129 
    130    function doVerify(x) {
    131      return crypto.subtle.verify({name: "RSA-PSS", saltLength: tv.rsapss.saltLength}, x, tv.rsapss.sig, tv.rsapss.data);
    132    }
    133 
    134    crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"])
    135      .then(doVerify, error(that))
    136      .then(complete(that, x => x), error(that));
    137  }
    138 );
    139 
    140 // -----------------------------------------------------------------------------
    141 TestArray.addTest(
    142  "RSA-PSS verify known signatures (SHA-1 to SHA-512, 1024-bit)",
    143  function() {
    144    var that = this;
    145 
    146    function verifyCase(hash, tv) {
    147      var alg = {name: "RSA-PSS", hash, saltLength: tv.saltLength};
    148      return crypto.subtle.importKey("spki", tv.spki, alg, false, ["verify"])
    149        .then(x => crypto.subtle.verify(alg, x, tv.sig, tv.data));
    150    }
    151 
    152    Promise.all([
    153      verifyCase("SHA-1", tv.rsapss2),
    154      verifyCase("SHA-256", tv.rsapss3),
    155      verifyCase("SHA-384", tv.rsapss4),
    156      verifyCase("SHA-512", tv.rsapss5),
    157    ]).then(complete(that, x => x.every(y => y)), error(that));
    158  }
    159 );
    160 
    161 // -----------------------------------------------------------------------------
    162 TestArray.addTest(
    163  "RSA-PSS import SPKI/PKCS#8 keys and sign/verify (SHA-1, 1024-bit)",
    164  function() {
    165    var that = this;
    166    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    167 
    168    var privKey, pubKey;
    169    function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
    170    function doSign() {
    171      return crypto.subtle.sign({name: "RSA-PSS", saltLength: tv.rsapss.saltLength}, privKey, tv.rsapss.data);
    172    }
    173    function doVerify(x) {
    174      return crypto.subtle.verify({name: "RSA-PSS", saltLength: tv.rsapss.saltLength}, pubKey, x, tv.rsapss.data);
    175    }
    176 
    177    var spki =
    178      crypto.subtle.importKey("spki", tv.rsapss.spki, alg, false, ["verify"]);
    179    var pkcs8 =
    180      crypto.subtle.importKey("pkcs8", tv.rsapss.pkcs8, alg, false, ["sign"]);
    181 
    182    Promise.all([spki, pkcs8])
    183      .then(setKeys, error(that))
    184      .then(doSign, error(that))
    185      .then(doVerify, error(that))
    186      .then(complete(that, x => x), error(that));
    187  }
    188 );
    189 
    190 // -----------------------------------------------------------------------------
    191 TestArray.addTest(
    192  "RSA-PSS import JWK keys and sign/verify (SHA-1, 1024-bit)",
    193  function() {
    194    var that = this;
    195    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    196 
    197    var privKey, pubKey;
    198    function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
    199    function doSign() {
    200      return crypto.subtle.sign({name: "RSA-PSS", saltLength: tv.rsapss.saltLength}, privKey, tv.rsapss.data);
    201    }
    202    function doVerify(x) {
    203      return crypto.subtle.verify({name: "RSA-PSS", saltLength: tv.rsapss.saltLength}, pubKey, x, tv.rsapss.data);
    204    }
    205 
    206    var spki =
    207      crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"]);
    208    var pkcs8 =
    209      crypto.subtle.importKey("jwk", tv.rsapss.jwk_priv, alg, false, ["sign"]);
    210 
    211    Promise.all([spki, pkcs8])
    212      .then(setKeys, error(that))
    213      .then(doSign, error(that))
    214      .then(doVerify, error(that))
    215      .then(complete(that, x => x), error(that));
    216  }
    217 );
    218 
    219 // -----------------------------------------------------------------------------
    220 TestArray.addTest(
    221  "RSA-PSS SPKI import/export (SHA-1, 1024-bit)",
    222  function() {
    223    var that = this;
    224    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    225 
    226    function doExport(x) {
    227      return crypto.subtle.exportKey("spki", x);
    228    }
    229 
    230    crypto.subtle.importKey("spki", tv.rsapss.spki, alg, true, ["verify"])
    231      .then(doExport, error(that))
    232      .then(memcmp_complete(that, tv.rsapss.spki), error(that));
    233  }
    234 );
    235 
    236 // -----------------------------------------------------------------------------
    237 TestArray.addTest(
    238  "RSA-PSS PKCS#8 import/export (SHA-1, 1024-bit)",
    239  function() {
    240    var that = this;
    241    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    242 
    243    function doExport(x) {
    244      return crypto.subtle.exportKey("pkcs8", x);
    245    }
    246 
    247    crypto.subtle.importKey("pkcs8", tv.rsapss.pkcs8, alg, true, ["sign"])
    248      .then(doExport, error(that))
    249      .then(memcmp_complete(that, tv.rsapss.pkcs8), error(that));
    250  }
    251 );
    252 
    253 // -----------------------------------------------------------------------------
    254 TestArray.addTest(
    255  "RSA-PSS JWK export a public key",
    256  function() {
    257    var that = this;
    258    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    259    var jwk = tv.rsapss.jwk_pub;
    260 
    261    function doExport(x) {
    262      return crypto.subtle.exportKey("jwk", x);
    263    }
    264 
    265    crypto.subtle.importKey("jwk", jwk, alg, true, ["verify"])
    266      .then(doExport)
    267      .then(
    268        complete(that, function(x) {
    269          return hasBaseJwkFields(x) &&
    270                 hasFields(x, ["n", "e"]) &&
    271                 x.kty == "RSA" &&
    272                 x.alg == "PS1" &&
    273                 x.ext &&
    274                 shallowArrayEquals(x.key_ops, ["verify"]) &&
    275                 x.n == jwk.n &&
    276                 x.e == jwk.e;
    277          }),
    278        error(that)
    279      );
    280  }
    281 );
    282 
    283 // -----------------------------------------------------------------------------
    284 TestArray.addTest(
    285  "RSA-PSS JWK export a private key",
    286  function() {
    287    var that = this;
    288    var alg = {name: "RSA-PSS", hash: "SHA-1"};
    289    var jwk = tv.rsapss.jwk_priv;
    290 
    291    function doExport(x) {
    292      return crypto.subtle.exportKey("jwk", x);
    293    }
    294 
    295    crypto.subtle.importKey("jwk", jwk, alg, true, ["sign"])
    296      .then(doExport)
    297      .then(
    298        complete(that, function(x) {
    299          return hasBaseJwkFields(x) &&
    300                 hasFields(x, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]) &&
    301                 x.kty == "RSA" &&
    302                 x.alg == "PS1" &&
    303                 x.ext &&
    304                 shallowArrayEquals(x.key_ops, ["sign"]) &&
    305                 x.n == jwk.n &&
    306                 x.e == jwk.e &&
    307                 x.d == jwk.d &&
    308                 x.p == jwk.p &&
    309                 x.q == jwk.q &&
    310                 x.dp == jwk.dp &&
    311                 x.dq == jwk.dq &&
    312                 x.qi == jwk.qi;
    313          }),
    314        error(that)
    315      );
    316  }
    317 );
    318 
    319 // -----------------------------------------------------------------------------
    320 TestArray.addTest(
    321  "Deterministic RSA-PSS signatures with saltLength=0 (SHA-256, 2048-bit)",
    322  function() {
    323    var that = this;
    324    var alg = {
    325      name: "RSA-PSS",
    326      hash: "SHA-256",
    327      modulusLength: 2048,
    328      publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    329    };
    330 
    331    var privKey, pubKey;
    332    var data = crypto.getRandomValues(new Uint8Array(128));
    333    function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
    334 
    335    function doSignTwice() {
    336      return Promise.all([
    337        crypto.subtle.sign({name: "RSA-PSS", saltLength: 0}, privKey, data),
    338        crypto.subtle.sign({name: "RSA-PSS", saltLength: 0}, privKey, data),
    339      ]);
    340    }
    341 
    342    function doVerify(x) {
    343      return crypto.subtle.verify({name: "RSA-PSS", saltLength: 0}, pubKey, x, data);
    344    }
    345 
    346    crypto.subtle.generateKey(alg, false, ["sign", "verify"])
    347      .then(setKey, error(that))
    348      .then(doSignTwice, error(that))
    349      .then(([sig1, sig2]) => {
    350        if (!util.memcmp(sig1, sig2)) {
    351          throw new Error("sig1 must be equal to sig2");
    352        }
    353 
    354        return sig1;
    355      }, error(that))
    356      .then(doVerify, error(that))
    357      .then(complete(that, x => x), error(that));
    358  }
    359 );
    360 /* ]]>*/</script>
    361 </head>
    362 
    363 <body>
    364 
    365 <div id="content">
    366 <div id="head">
    367 	<b>Web</b>Crypto<br>
    368 </div>
    369 
    370    <div id="start" onclick="start();">RUN ALL</div>
    371 
    372    <div id="resultDiv" class="content">
    373    Summary:
    374    <span class="pass"><span id="passN">0</span> passed, </span>
    375    <span class="fail"><span id="failN">0</span> failed, </span>
    376    <span class="pending"><span id="pendingN">0</span> pending.</span>
    377    <br/>
    378    <br/>
    379 
    380    <table id="results">
    381        <tr>
    382            <th>Test</th>
    383            <th>Result</th>
    384            <th>Time</th>
    385        </tr>
    386    </table>
    387 
    388    </div>
    389 
    390    <div id="foot"></div>
    391 </div>
    392 
    393 </body>
    394 </html>