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>