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>