test_WebCrypto.html (34001B)
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 "Test for presence of WebCrypto API methods", 28 function() { 29 this.complete( 30 exists(window.crypto.subtle) && 31 exists(window.crypto.subtle.encrypt) && 32 exists(window.crypto.subtle.decrypt) && 33 exists(window.crypto.subtle.sign) && 34 exists(window.crypto.subtle.verify) && 35 exists(window.crypto.subtle.digest) && 36 exists(window.crypto.subtle.importKey) && 37 exists(window.crypto.subtle.exportKey) && 38 exists(window.crypto.subtle.generateKey) && 39 exists(window.crypto.subtle.deriveKey) && 40 exists(window.crypto.subtle.deriveBits) 41 ); 42 } 43 ); 44 45 // ----------------------------------------------------------------------------- 46 TestArray.addTest( 47 "Clean failure on a mal-formed algorithm", 48 function() { 49 var that = this; 50 var alg = { 51 get name() { 52 throw new Error("Oh no, no name!"); 53 }, 54 }; 55 56 crypto.subtle.importKey("raw", tv.raw, alg, true, ["encrypt"]) 57 .then( 58 error(that), 59 complete(that, function() { return true; }) 60 ); 61 } 62 ); 63 64 // ----------------------------------------------------------------------------- 65 TestArray.addTest( 66 "Import / export round-trip with 'raw'", 67 function() { 68 var that = this; 69 var alg = "AES-GCM"; 70 71 function doExport(x) { 72 if (!hasKeyFields(x)) { 73 throw new Error("Invalid key; missing field(s)"); 74 } else if ((x.algorithm.name != alg) || 75 (x.algorithm.length != 8 * tv.raw.length) || 76 (x.type != "secret") || 77 (!x.extractable) || 78 (x.usages.length != 1) || 79 (x.usages[0] != "encrypt")) { 80 throw new Error("Invalid key: incorrect key data"); 81 } 82 return crypto.subtle.exportKey("raw", x); 83 } 84 85 crypto.subtle.importKey("raw", tv.raw, alg, true, ["encrypt"]) 86 .then(doExport) 87 .then( 88 memcmp_complete(that, tv.raw), 89 error(that) 90 ); 91 } 92 ); 93 94 // ----------------------------------------------------------------------------- 95 TestArray.addTest( 96 "Import failure with format 'raw'", 97 function() { 98 var that = this; 99 var alg = "AES-GCM"; 100 101 crypto.subtle.importKey("raw", tv.negative_raw, alg, true, ["encrypt"]) 102 .then(error(that), complete(that)); 103 } 104 ); 105 106 // ----------------------------------------------------------------------------- 107 TestArray.addTest( 108 "Proper handling of an ABV representing part of a buffer", 109 function() { 110 var that = this; 111 var alg = "AES-GCM"; 112 113 var u8 = new Uint8Array([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 114 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 115 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 116 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f]); 117 var u32 = new Uint32Array(u8.buffer, 8, 4); 118 var out = u8.subarray(8, 24); 119 120 function doExport(x) { 121 return crypto.subtle.exportKey("raw", x); 122 } 123 124 crypto.subtle.importKey("raw", u32, alg, true, ["encrypt"]) 125 .then(doExport, error(that)) 126 .then(memcmp_complete(that, out), error(that)); 127 } 128 ); 129 130 // ----------------------------------------------------------------------------- 131 TestArray.addTest( 132 "Import / export round-trip with 'pkcs8'", 133 function() { 134 var that = this; 135 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }; 136 137 function doExport(x) { 138 if (!hasKeyFields(x)) { 139 throw new Error("Invalid key; missing field(s)"); 140 } else if ((x.algorithm.name != alg.name) || 141 (x.algorithm.hash.name != alg.hash) || 142 (x.algorithm.modulusLength != 512) || 143 (x.algorithm.publicExponent.byteLength != 3) || 144 (x.type != "private") || 145 (!x.extractable) || 146 (x.usages.length != 1) || 147 (x.usages[0] != "sign")) { 148 throw new Error("Invalid key: incorrect key data"); 149 } 150 return crypto.subtle.exportKey("pkcs8", x); 151 } 152 153 crypto.subtle.importKey("pkcs8", tv.pkcs8, alg, true, ["sign"]) 154 .then(doExport) 155 .then( 156 memcmp_complete(that, tv.pkcs8), 157 error(that) 158 ); 159 } 160 ); 161 162 // ----------------------------------------------------------------------------- 163 TestArray.addTest( 164 "Import failure with format 'pkcs8'", 165 function() { 166 var that = this; 167 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }; 168 169 crypto.subtle.importKey("pkcs8", tv.negative_pkcs8, alg, true, ["encrypt"]) 170 .then(error(that), complete(that)); 171 } 172 ); 173 174 // ----------------------------------------------------------------------------- 175 TestArray.addTest( 176 "Import / export round-trip with 'spki'", 177 function() { 178 var that = this; 179 var alg = { 180 name: "RSASSA-PKCS1-v1_5", 181 hash: "SHA-256", 182 }; 183 184 function doExport(x) { 185 if (!hasKeyFields(x)) { 186 throw new Error("Invalid key; missing field(s)"); 187 } else if ((x.algorithm.name != alg.name) || 188 (x.algorithm.modulusLength != 1024) || 189 (x.algorithm.publicExponent.byteLength != 3) || 190 (x.type != "public") || 191 (!x.extractable) || 192 (x.usages.length != 1) || 193 (x.usages[0] != "verify")) { 194 throw new Error("Invalid key: incorrect key data"); 195 } 196 return crypto.subtle.exportKey("spki", x); 197 } 198 199 crypto.subtle.importKey("spki", tv.spki, alg, true, ["verify"]) 200 .then(doExport, error(that)) 201 .then( 202 memcmp_complete(that, tv.spki), 203 error(that) 204 ); 205 } 206 ); 207 208 // ----------------------------------------------------------------------------- 209 TestArray.addTest( 210 "Import failure with format 'spki'", 211 function() { 212 var that = this; 213 var alg = { 214 name: "RSASSA-PKCS1-v1_5", 215 hash: "SHA-256", 216 }; 217 218 crypto.subtle.importKey("spki", tv.negative_spki, alg, true, ["encrypt"]) 219 .then(error(that), complete(that)); 220 } 221 ); 222 223 // ----------------------------------------------------------------------------- 224 TestArray.addTest( 225 "Importing an ECDSA key as an RSA key should fail", 226 function() { 227 var that = this; 228 var alg = { 229 name: "RSASSA-PKCS1-v1_5", 230 hash: "SHA-256", 231 }; 232 233 crypto.subtle.importKey("spki", tv.ecdh_p256.spki, alg, true, ["verify"]) 234 .then(error(that), complete(that)); 235 } 236 ); 237 238 // ----------------------------------------------------------------------------- 239 TestArray.addTest( 240 "Refuse to export non-extractable key", 241 function() { 242 var that = this; 243 var alg = "AES-GCM"; 244 245 function doExport(x) { 246 return crypto.subtle.exportKey("raw", x); 247 } 248 249 crypto.subtle.importKey("raw", tv.raw, alg, false, ["encrypt"]) 250 .then(doExport, error(that)) 251 .then( 252 error(that), 253 complete(that) 254 ); 255 } 256 ); 257 258 // ----------------------------------------------------------------------------- 259 TestArray.addTest( 260 "IndexedDB store / retrieve round-trip", 261 function() { 262 var that = this; 263 var alg = "AES-GCM"; 264 var importedKey; 265 var dbname = "keyDB"; 266 var dbstore = "keystore"; 267 var dbversion = 1; 268 var dbkey = 0; 269 var db; 270 271 function doIndexedDB(x) { 272 importedKey = x; 273 var req = indexedDB.deleteDatabase(dbname); 274 req.onerror = error(that); 275 req.onsuccess = doCreateDB; 276 } 277 278 function doCreateDB() { 279 var req = indexedDB.open(dbname, dbversion); 280 req.onerror = error(that); 281 req.onupgradeneeded = function(e) { 282 db = e.target.result; 283 db.createObjectStore(dbstore, {keyPath: "id"}); 284 }; 285 286 req.onsuccess = doPut; 287 } 288 289 function doPut() { 290 var req = db.transaction([dbstore], "readwrite") 291 .objectStore(dbstore) 292 .add({id: dbkey, val: importedKey}); 293 req.onerror = error(that); 294 req.onsuccess = doGet; 295 } 296 297 function doGet() { 298 var req = db.transaction([dbstore], "readwrite") 299 .objectStore(dbstore) 300 .get(dbkey); 301 req.onerror = error(that); 302 req.onsuccess = complete(that, function(e) { 303 db.close(); 304 return hasKeyFields(e.target.result.val); 305 }); 306 } 307 308 crypto.subtle.importKey("raw", tv.raw, alg, false, ["encrypt"]) 309 .then(doIndexedDB, error(that)); 310 } 311 ); 312 313 // ----------------------------------------------------------------------------- 314 TestArray.addTest( 315 "Generate a 256-bit HMAC-SHA-256 key", 316 function() { 317 var that = this; 318 var alg = { name: "HMAC", length: 256, hash: {name: "SHA-256"} }; 319 crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then( 320 complete(that, function(x) { 321 return hasKeyFields(x) && x.algorithm.length == 256; 322 }), 323 error(that) 324 ); 325 } 326 ); 327 328 // ----------------------------------------------------------------------------- 329 TestArray.addTest( 330 "Generate a 256-bit HMAC-SHA-256 key without specifying a key length", 331 function() { 332 var that = this; 333 var alg = { name: "HMAC", hash: {name: "SHA-256"} }; 334 crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then( 335 complete(that, function(x) { 336 return hasKeyFields(x) && x.algorithm.length == 512; 337 }), 338 error(that) 339 ); 340 } 341 ); 342 343 // ----------------------------------------------------------------------------- 344 TestArray.addTest( 345 "Generate a 256-bit HMAC-SHA-512 key without specifying a key length", 346 function() { 347 var that = this; 348 var alg = { name: "HMAC", hash: {name: "SHA-512"} }; 349 crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then( 350 complete(that, function(x) { 351 return hasKeyFields(x) && x.algorithm.length == 1024; 352 }), 353 error(that) 354 ); 355 } 356 ); 357 358 // ----------------------------------------------------------------------------- 359 TestArray.addTest( 360 "Fail generating an HMAC key when specifying an invalid hash algorithm", 361 function() { 362 var that = this; 363 var alg = { name: "HMAC", hash: {name: "SHA-123"} }; 364 crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then( 365 error(that), 366 complete(that, function() { return true; }) 367 ); 368 } 369 ); 370 371 // ----------------------------------------------------------------------------- 372 TestArray.addTest( 373 "Fail generating an HMAC key when specifying a zero length", 374 function() { 375 var that = this; 376 var alg = { name: "HMAC", hash: {name: "SHA-256"}, length: 0 }; 377 crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then( 378 error(that), 379 complete(that, function() { return true; }) 380 ); 381 } 382 ); 383 384 // ----------------------------------------------------------------------------- 385 TestArray.addTest( 386 "Generate a 192-bit AES key", 387 function() { 388 var that = this; 389 var alg = { name: "AES-GCM", length: 192 }; 390 crypto.subtle.generateKey(alg, true, ["encrypt"]).then( 391 complete(that, function(x) { 392 return hasKeyFields(x); 393 }), 394 error(that) 395 ); 396 } 397 ); 398 399 // ----------------------------------------------------------------------------- 400 TestArray.addTest( 401 "Fail generating an AES key of wrong length", 402 function() { 403 var that = this; 404 var alg = { name: "AES-CBC", length: 64 }; 405 crypto.subtle.generateKey(alg, false, ["encrypt"]).then( 406 error(that), 407 complete(that, function(e) { 408 return e.name == "OperationError"; 409 }) 410 ); 411 } 412 ); 413 414 // ----------------------------------------------------------------------------- 415 TestArray.addTest( 416 "Fail generating a key with bad algorithm argument", 417 function() { 418 var that = this; 419 var alg = { name: "AES", length: 128 }; 420 crypto.subtle.generateKey(alg, false, ["encrypt"]).then( 421 error(that), 422 complete(that, function(e) { 423 return e.name == "NotSupportedError"; 424 }) 425 ); 426 } 427 ); 428 429 // ----------------------------------------------------------------------------- 430 TestArray.addTest( "Generate a 1024-bit RSA key", 431 function() { 432 var that = this; 433 var alg = { 434 name: "RSASSA-PKCS1-v1_5", 435 hash: "SHA-256", 436 modulusLength: 1024, 437 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), 438 }; 439 crypto.subtle.generateKey(alg, false, ["sign", "verify"]).then( 440 complete(that, function(x) { 441 return exists(x.publicKey) && 442 (x.publicKey.algorithm.name == alg.name) && 443 (x.publicKey.algorithm.modulusLength == alg.modulusLength) && 444 (x.publicKey.type == "public") && 445 x.publicKey.extractable && 446 (x.publicKey.usages.length == 1) && 447 (x.publicKey.usages[0] == "verify") && 448 exists(x.privateKey) && 449 (x.privateKey.algorithm.name == alg.name) && 450 (x.privateKey.algorithm.modulusLength == alg.modulusLength) && 451 (x.privateKey.type == "private") && 452 !x.privateKey.extractable && 453 (x.privateKey.usages.length == 1) && 454 (x.privateKey.usages[0] == "sign"); 455 }), 456 error(that) 457 ); 458 } 459 ); 460 461 // ----------------------------------------------------------------------------- 462 TestArray.addTest( 463 "Fail cleanly when NSS refuses to generate a key pair", 464 function() { 465 var that = this; 466 var alg = { 467 name: "RSASSA-PKCS1-v1_5", 468 hash: "SHA-256", 469 modulusLength: 2299, // NSS does not like this key length 470 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), 471 }; 472 473 crypto.subtle.generateKey(alg, false, ["sign"]) 474 .then( error(that), complete(that) ); 475 } 476 ); 477 478 // ----------------------------------------------------------------------------- 479 TestArray.addTest( 480 "SHA-256 digest", 481 function() { 482 var that = this; 483 crypto.subtle.digest("SHA-256", tv.sha256.data).then( 484 memcmp_complete(that, tv.sha256.result), 485 error(that) 486 ); 487 } 488 ); 489 490 // ----------------------------------------------------------------------------- 491 TestArray.addTest( 492 "Fail cleanly on unknown hash algorithm", 493 function() { 494 var that = this; 495 crypto.subtle.digest("GOST-34_311-95", tv.sha256.data).then( 496 error(that), 497 complete(that, function() { return true; }) 498 ); 499 } 500 ); 501 502 // ----------------------------------------------------------------------------- 503 TestArray.addTest( 504 "AES-CBC encrypt", 505 function() { 506 var that = this; 507 508 function doEncrypt(x) { 509 return crypto.subtle.encrypt( 510 { name: "AES-CBC", iv: tv.aes_cbc_enc.iv }, 511 x, tv.aes_cbc_enc.data); 512 } 513 514 crypto.subtle.importKey("raw", tv.aes_cbc_enc.key, "AES-CBC", false, ["encrypt"]) 515 .then(doEncrypt) 516 .then( 517 memcmp_complete(that, tv.aes_cbc_enc.result), 518 error(that) 519 ); 520 } 521 ); 522 523 // ----------------------------------------------------------------------------- 524 TestArray.addTest( 525 "AES-CBC encrypt with wrong IV size", 526 function() { 527 var that = this; 528 529 function encrypt(x, iv) { 530 return crypto.subtle.encrypt( 531 { name: "AES-CBC", iv }, 532 x, tv.aes_cbc_enc.data); 533 } 534 535 function checkPromises(promises) { 536 for (var promise of promises) { 537 if (promise.status != "rejected") { 538 return false; 539 } 540 if (promise.reason.name != "OperationError") { 541 return false; 542 } 543 } 544 545 return true; 546 } 547 548 crypto.subtle.importKey("raw", tv.aes_cbc_enc.key, "AES-CBC", false, ["encrypt"]) 549 .then(function(key) { 550 var p1 = encrypt(key, new Uint8Array(15)); 551 var p2 = encrypt(key, new Uint8Array(17)); 552 553 Promise.allSettled([p1, p2]) 554 .then(complete(that, checkPromises)); 555 }); 556 } 557 ); 558 559 // ----------------------------------------------------------------------------- 560 TestArray.addTest( 561 "AES-CBC decrypt", 562 function() { 563 var that = this; 564 565 function doDecrypt(x) { 566 return crypto.subtle.decrypt( 567 { name: "AES-CBC", iv: tv.aes_cbc_dec.iv }, 568 x, tv.aes_cbc_dec.data); 569 } 570 571 crypto.subtle.importKey("raw", tv.aes_cbc_dec.key, "AES-CBC", false, ["decrypt"]) 572 .then(doDecrypt) 573 .then( 574 memcmp_complete(that, tv.aes_cbc_dec.result), 575 error(that) 576 ); 577 } 578 ); 579 580 // ----------------------------------------------------------------------------- 581 TestArray.addTest( 582 "AES-CBC decrypt with wrong IV size", 583 function() { 584 var that = this; 585 586 function decrypt(x, iv) { 587 return crypto.subtle.decrypt( 588 { name: "AES-CBC", iv }, 589 x, tv.aes_cbc_dec.data); 590 } 591 592 function checkPromises(promises) { 593 for (var promise of promises) { 594 if (promise.status != "rejected") { 595 return false; 596 } 597 if (promise.reason.name != "OperationError") { 598 return false; 599 } 600 } 601 602 return true; 603 } 604 605 crypto.subtle.importKey("raw", tv.aes_cbc_dec.key, "AES-CBC", false, ["decrypt"]) 606 .then(function(key) { 607 var p1 = decrypt(key, new Uint8Array(15)); 608 var p2 = decrypt(key, new Uint8Array(17)); 609 610 Promise.allSettled([p1, p2]) 611 .then(complete(that, checkPromises)); 612 }); 613 } 614 ); 615 616 // ----------------------------------------------------------------------------- 617 TestArray.addTest( 618 "AES-CTR encryption", 619 function() { 620 var that = this; 621 622 function doEncrypt(x) { 623 return crypto.subtle.encrypt( 624 { name: "AES-CTR", counter: tv.aes_ctr_enc.iv, length: 32 }, 625 x, tv.aes_ctr_enc.data); 626 } 627 628 crypto.subtle.importKey("raw", tv.aes_ctr_enc.key, "AES-CTR", false, ["encrypt"]) 629 .then(doEncrypt) 630 .then( 631 memcmp_complete(that, tv.aes_ctr_enc.result), 632 error(that) 633 ); 634 } 635 ); 636 637 // ----------------------------------------------------------------------------- 638 TestArray.addTest( 639 "AES-CTR encryption with wrong IV size", 640 function() { 641 var that = this; 642 643 function encrypt(x, iv) { 644 return crypto.subtle.encrypt( 645 { name: "AES-CTR", counter: iv, length: 32 }, 646 x, tv.aes_ctr_enc.data); 647 } 648 649 function checkPromises(promises) { 650 for (var promise of promises) { 651 if (promise.status != "rejected") { 652 return false; 653 } 654 if (promise.reason.name != "OperationError") { 655 return false; 656 } 657 } 658 659 return true; 660 } 661 662 crypto.subtle.importKey("raw", tv.aes_ctr_enc.key, "AES-CTR", false, ["encrypt"]) 663 .then(function(key) { 664 var p1 = encrypt(key, new Uint8Array(15)); 665 var p2 = encrypt(key, new Uint8Array(17)); 666 667 Promise.allSettled([p1, p2]) 668 .then(complete(that, checkPromises)); 669 }); 670 } 671 ); 672 673 // ----------------------------------------------------------------------------- 674 TestArray.addTest( 675 "AES-CTR decryption", 676 function() { 677 var that = this; 678 679 function doDecrypt(x) { 680 return crypto.subtle.decrypt( 681 { name: "AES-CTR", counter: tv.aes_ctr_dec.iv, length: 32 }, 682 x, tv.aes_ctr_dec.data); 683 } 684 685 crypto.subtle.importKey("raw", tv.aes_ctr_dec.key, "AES-CTR", false, ["decrypt"]) 686 .then(doDecrypt) 687 .then( 688 memcmp_complete(that, tv.aes_ctr_dec.result), 689 error(that) 690 ); 691 } 692 ); 693 694 // ----------------------------------------------------------------------------- 695 TestArray.addTest( 696 "AES-CTR decryption with wrong IV size", 697 function() { 698 var that = this; 699 700 function decrypt(x, iv) { 701 return crypto.subtle.decrypt( 702 { name: "AES-CTR", counter: iv, length: 32 }, 703 x, tv.aes_ctr_dec.data); 704 } 705 706 function checkPromises(promises) { 707 for (var promise of promises) { 708 if (promise.status != "rejected") { 709 return false; 710 } 711 if (promise.reason.name != "OperationError") { 712 return false; 713 } 714 } 715 716 return true; 717 } 718 719 crypto.subtle.importKey("raw", tv.aes_ctr_dec.key, "AES-CTR", false, ["decrypt"]) 720 .then(function(key) { 721 var p1 = decrypt(key, new Uint8Array(15)); 722 var p2 = decrypt(key, new Uint8Array(17)); 723 724 Promise.allSettled([p1, p2]) 725 .then(complete(that, checkPromises)); 726 }); 727 } 728 ); 729 730 // ----------------------------------------------------------------------------- 731 TestArray.addTest( 732 "AES-GCM encryption", 733 function() { 734 var that = this; 735 736 function doEncrypt(x) { 737 return crypto.subtle.encrypt( 738 { 739 name: "AES-GCM", 740 iv: tv.aes_gcm_enc.iv, 741 additionalData: tv.aes_gcm_enc.adata, 742 tagLength: 128, 743 }, 744 x, tv.aes_gcm_enc.data); 745 } 746 747 crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, "AES-GCM", false, ["encrypt"]) 748 .then(doEncrypt) 749 .then( 750 memcmp_complete(that, tv.aes_gcm_enc.result), 751 error(that) 752 ); 753 } 754 ); 755 756 // ----------------------------------------------------------------------------- 757 TestArray.addTest( 758 "AES-GCM decryption", 759 function() { 760 var that = this; 761 762 function doDecrypt(x) { 763 return crypto.subtle.decrypt( 764 { 765 name: "AES-GCM", 766 iv: tv.aes_gcm_dec.iv, 767 additionalData: tv.aes_gcm_dec.adata, 768 tagLength: 128, 769 }, 770 x, tv.aes_gcm_dec.data); 771 } 772 773 crypto.subtle.importKey("raw", tv.aes_gcm_dec.key, "AES-GCM", false, ["decrypt"]) 774 .then(doDecrypt) 775 .then( 776 memcmp_complete(that, tv.aes_gcm_dec.result), 777 error(that) 778 ); 779 } 780 ); 781 782 // ----------------------------------------------------------------------------- 783 TestArray.addTest( 784 "AES-GCM decryption, failing authentication check", 785 function() { 786 var that = this; 787 788 function doDecrypt(x) { 789 return crypto.subtle.decrypt( 790 { 791 name: "AES-GCM", 792 iv: tv.aes_gcm_dec_fail.iv, 793 additionalData: tv.aes_gcm_dec_fail.adata, 794 tagLength: 128, 795 }, 796 x, tv.aes_gcm_dec_fail.data); 797 } 798 799 crypto.subtle.importKey("raw", tv.aes_gcm_dec_fail.key, "AES-GCM", false, ["decrypt"]) 800 .then(doDecrypt) 801 .then( 802 error(that), 803 complete(that) 804 ); 805 } 806 ); 807 808 // ----------------------------------------------------------------------------- 809 TestArray.addTest( 810 "AES-GCM encryption, fail with a zero-length IV", 811 function() { 812 var that = this; 813 var alg = { 814 name: "AES-GCM", 815 iv: new Uint8Array(), 816 additionalData: tv.aes_gcm_enc.adata, 817 tagLength: 128, 818 }; 819 820 function doEncrypt(x) { 821 return crypto.subtle.encrypt(alg, x, tv.aes_gcm_enc.data); 822 } 823 824 crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, "AES-GCM", false, ["encrypt"]) 825 .then(doEncrypt) 826 .then(error(that), complete(that)); 827 } 828 ); 829 830 // ----------------------------------------------------------------------------- 831 TestArray.addTest( 832 "AES-GCM encryption, accept an all-zero IV (1 byte)", 833 function() { 834 var that = this; 835 var alg = { 836 name: "AES-GCM", 837 iv: new Uint8Array(1), 838 additionalData: tv.aes_gcm_enc.adata, 839 tagLength: 128, 840 }; 841 842 function doEncrypt(x) { 843 return crypto.subtle.encrypt(alg, x, tv.aes_gcm_enc.data); 844 } 845 846 crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, "AES-GCM", false, ["encrypt"]) 847 .then(doEncrypt) 848 .then(complete(that), error(that)); 849 } 850 ); 851 852 // ----------------------------------------------------------------------------- 853 TestArray.addTest( 854 "AES-GCM encryption, accept an all-zero IV (12 bytes)", 855 function() { 856 var that = this; 857 var alg = { 858 name: "AES-GCM", 859 iv: new Uint8Array(12), 860 additionalData: tv.aes_gcm_enc.adata, 861 tagLength: 128, 862 }; 863 864 function doEncrypt(x) { 865 return crypto.subtle.encrypt(alg, x, tv.aes_gcm_enc.data); 866 } 867 868 crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, "AES-GCM", false, ["encrypt"]) 869 .then(doEncrypt) 870 .then(complete(that), error(that)); 871 } 872 ); 873 874 // ----------------------------------------------------------------------------- 875 TestArray.addTest( 876 "AES-GCM encryption, accept an all-zero IV (16 bytes)", 877 function() { 878 var that = this; 879 var alg = { 880 name: "AES-GCM", 881 iv: new Uint8Array(16), 882 additionalData: tv.aes_gcm_enc.adata, 883 tagLength: 128, 884 }; 885 886 function doEncrypt(x) { 887 return crypto.subtle.encrypt(alg, x, tv.aes_gcm_enc.data); 888 } 889 890 crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, "AES-GCM", false, ["encrypt"]) 891 .then(doEncrypt) 892 .then(complete(that), error(that)); 893 } 894 ); 895 896 // ----------------------------------------------------------------------------- 897 TestArray.addTest( 898 "HMAC SHA-256 sign", 899 function() { 900 var that = this; 901 var alg = { 902 name: "HMAC", 903 hash: "SHA-256", 904 }; 905 906 function doSign(x) { 907 return crypto.subtle.sign("HMAC", x, tv.hmac_sign.data); 908 } 909 910 crypto.subtle.importKey("raw", tv.hmac_sign.key, alg, false, ["sign"]) 911 .then(doSign) 912 .then( 913 memcmp_complete(that, tv.hmac_sign.result), 914 error(that) 915 ); 916 } 917 ); 918 919 // ----------------------------------------------------------------------------- 920 TestArray.addTest( 921 "HMAC SHA-256 verify", 922 function() { 923 var that = this; 924 var alg = { 925 name: "HMAC", 926 hash: "SHA-256", 927 }; 928 929 function doVerify(x) { 930 return crypto.subtle.verify("HMAC", x, tv.hmac_verify.sig, tv.hmac_verify.data); 931 } 932 933 crypto.subtle.importKey("raw", tv.hmac_verify.key, alg, false, ["verify"]) 934 .then(doVerify) 935 .then( 936 complete(that, function(x) { return !!x; }), 937 error(that) 938 ); 939 } 940 ); 941 942 // ----------------------------------------------------------------------------- 943 TestArray.addTest( 944 "HMAC SHA-256, failing verification due to bad signature", 945 function() { 946 var that = this; 947 var alg = { 948 name: "HMAC", 949 hash: "SHA-256", 950 }; 951 952 function doVerify(x) { 953 return crypto.subtle.verify("HMAC", x, tv.hmac_verify.sig_fail, 954 tv.hmac_verify.data); 955 } 956 957 crypto.subtle.importKey("raw", tv.hmac_verify.key, alg, false, ["verify"]) 958 .then(doVerify) 959 .then( 960 complete(that, function(x) { return !x; }), 961 error(that) 962 ); 963 } 964 ); 965 966 // ----------------------------------------------------------------------------- 967 TestArray.addTest( 968 "HMAC SHA-256, failing verification due to key usage restriction", 969 function() { 970 var that = this; 971 var alg = { 972 name: "HMAC", 973 hash: "SHA-256", 974 }; 975 976 function doVerify(x) { 977 return crypto.subtle.verify("HMAC", x, tv.hmac_verify.sig, 978 tv.hmac_verify.data); 979 } 980 981 crypto.subtle.importKey("raw", tv.hmac_verify.key, alg, false, ["encrypt"]) 982 .then(doVerify) 983 .then( 984 error(that), 985 complete(that, function() { return true; }) 986 ); 987 } 988 ); 989 990 // ----------------------------------------------------------------------------- 991 TestArray.addTest( 992 "RSASSA/SHA-1 signature", 993 function() { 994 var that = this; 995 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }; 996 997 function doSign(x) { 998 return crypto.subtle.sign(alg.name, x, tv.rsassa.data); 999 } 1000 1001 crypto.subtle.importKey("pkcs8", tv.rsassa.pkcs8, alg, false, ["sign"]) 1002 .then( doSign ) 1003 .then( memcmp_complete(that, tv.rsassa.sig1), error(that) ); 1004 } 1005 ); 1006 1007 // ----------------------------------------------------------------------------- 1008 TestArray.addTest( 1009 "RSASSA verification (SHA-1)", 1010 function() { 1011 var that = this; 1012 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }; 1013 1014 function doVerify(x) { 1015 return crypto.subtle.verify(alg.name, x, tv.rsassa.sig1, tv.rsassa.data); 1016 } 1017 1018 crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ["verify"]) 1019 .then( doVerify ) 1020 .then( 1021 complete(that, function(x) { return x; }), 1022 error(that) 1023 ); 1024 } 1025 ); 1026 1027 // ----------------------------------------------------------------------------- 1028 TestArray.addTest( 1029 "RSASSA verification (SHA-1), failing verification", 1030 function() { 1031 var that = this; 1032 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }; 1033 1034 function doVerify(x) { 1035 return crypto.subtle.verify(alg.name, x, tv.rsassa.sig_fail, tv.rsassa.data); 1036 } 1037 1038 crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ["verify"]) 1039 .then( doVerify ) 1040 .then( 1041 complete(that, function(x) { return !x; }), 1042 error(that) 1043 ); 1044 } 1045 ); 1046 1047 // ----------------------------------------------------------------------------- 1048 TestArray.addTest( 1049 "RSASSA/SHA-256 signature", 1050 function() { 1051 var that = this; 1052 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; 1053 1054 function doSign(x) { 1055 return crypto.subtle.sign(alg.name, x, tv.rsassa.data); 1056 } 1057 1058 crypto.subtle.importKey("pkcs8", tv.rsassa.pkcs8, alg, false, ["sign"]) 1059 .then( doSign ) 1060 .then( memcmp_complete(that, tv.rsassa.sig256), error(that) ); 1061 } 1062 ); 1063 1064 // ----------------------------------------------------------------------------- 1065 TestArray.addTest( 1066 "RSASSA verification (SHA-256)", 1067 function() { 1068 var that = this; 1069 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; 1070 1071 function doVerify(x) { 1072 return crypto.subtle.verify(alg.name, x, tv.rsassa.sig256, tv.rsassa.data); 1073 } 1074 1075 crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ["verify"]) 1076 .then( doVerify ) 1077 .then( 1078 complete(that, function(x) { return x; }), 1079 error(that) 1080 ); 1081 } 1082 ); 1083 1084 // ----------------------------------------------------------------------------- 1085 TestArray.addTest( 1086 "RSASSA verification (SHA-256), failing verification", 1087 function() { 1088 var that = this; 1089 var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; 1090 1091 function doVerify(x) { 1092 return crypto.subtle.verify(alg.name, x, tv.rsassa.sig_fail, tv.rsassa.data); 1093 } 1094 1095 crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ["verify"]) 1096 .then( doVerify ) 1097 .then( 1098 complete(that, function(x) { return !x; }), 1099 error(that) 1100 ); 1101 } 1102 ); 1103 1104 // ----------------------------------------------------------------------------- 1105 TestArray.addTest( 1106 "Test that we return ArrayBuffers not ArrayBufferViews", 1107 function() { 1108 var that = this; 1109 1110 crypto.subtle.digest("SHA-256", tv.sha256.data) 1111 .then(complete(that, function(x) { 1112 return x instanceof ArrayBuffer; 1113 }), error(that)); 1114 } 1115 ); 1116 1117 // ----------------------------------------------------------------------------- 1118 TestArray.addTest( 1119 "Ensure that importing an invalid key doesn't crash", 1120 function() { 1121 var that = this; 1122 var alg = {name: "RSA-OAEP", hash: "SHA-1"}; 1123 1124 crypto.subtle.importKey("pkcs8", tv.broken_pkcs8.rsa, alg, false, ["decrypt"]) 1125 .then(error(that), complete(that)); 1126 } 1127 ); 1128 1129 // ----------------------------------------------------------------------------- 1130 TestArray.addTest( 1131 "Test that we check keys before using them for encryption/signatures", 1132 function() { 1133 var that = this; 1134 1135 function doCheckRSASSA() { 1136 var alg = {name: "HMAC", hash: {name: "SHA-1"}}; 1137 1138 function doSign(x) { 1139 return crypto.subtle.sign("RSASSA-PKCS1-v1_5", x, new Uint8Array()); 1140 } 1141 1142 return crypto.subtle.generateKey(alg, false, ["sign"]).then(doSign); 1143 } 1144 1145 doCheckRSASSA().then(error(that), complete(that)); 1146 } 1147 ); 1148 1149 // ----------------------------------------------------------------------------- 1150 TestArray.addTest( 1151 "Test that we're using the right globals when creating objects", 1152 function() { 1153 // This test isn't supported in workers. 1154 if (window.importScripts) { 1155 return this.complete(true); 1156 } 1157 1158 var that = this; 1159 var data = crypto.getRandomValues(new Uint8Array(10)); 1160 var hmacAlg = {name: "HMAC", length: 256, hash: "SHA-1"}; 1161 1162 var rsaAlg = { 1163 name: "RSA-PSS", 1164 hash: "SHA-1", 1165 modulusLength: 1024, 1166 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), 1167 }; 1168 1169 function checkPrototypes(obj, type) { 1170 return obj.__proto__ != window[type].prototype && 1171 obj.__proto__ == frames[0][type].prototype; 1172 } 1173 1174 var p1 = crypto.subtle.importKey.call( 1175 frames[0].crypto.subtle, "raw", data, hmacAlg, false, ["sign", "verify"]); 1176 var p2 = crypto.subtle.generateKey.call( 1177 frames[0].crypto.subtle, hmacAlg, false, ["sign", "verify"]); 1178 var p3 = crypto.subtle.generateKey.call( 1179 frames[0].crypto.subtle, rsaAlg, false, ["sign", "verify"]); 1180 1181 if (!checkPrototypes(p1, "Promise") || 1182 !checkPrototypes(p2, "Promise") || 1183 !checkPrototypes(p3, "Promise")) { 1184 error(that)(); 1185 } 1186 1187 return Promise.all([p1, p2, p3]).then(complete(that, keys => { 1188 return keys.every(key => { 1189 if (key instanceof frames[0].CryptoKey) { 1190 return checkPrototypes(key, "CryptoKey"); 1191 } 1192 1193 return checkPrototypes(key.publicKey, "CryptoKey") && 1194 checkPrototypes(key.privateKey, "CryptoKey"); 1195 }); 1196 }), error(that)); 1197 } 1198 ); 1199 /* ]]>*/</script> 1200 </head> 1201 1202 <body> 1203 1204 <div id="content"> 1205 <div id="head"> 1206 <b>Web</b>Crypto<br> 1207 </div> 1208 1209 <iframe style="display: none;"></iframe> 1210 <div id="start" onclick="start();">RUN ALL</div> 1211 1212 <div id="resultDiv" class="content"> 1213 Summary: 1214 <span class="pass"><span id="passN">0</span> passed, </span> 1215 <span class="fail"><span id="failN">0</span> failed, </span> 1216 <span class="pending"><span id="pendingN">0</span> pending.</span> 1217 <br/> 1218 <br/> 1219 1220 <table id="results"> 1221 <tr> 1222 <th>Test</th> 1223 <th>Result</th> 1224 <th>Time</th> 1225 </tr> 1226 </table> 1227 1228 </div> 1229 1230 <div id="foot"></div> 1231 </div> 1232 1233 </body> 1234 </html>