<!DOCTYPE html> <html> <head> <title>WebCrypto Test Suite</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <link rel="stylesheet" href="./test_WebCrypto.css"/> <script src="/tests/SimpleTest/SimpleTest.js"></script> <!-- Utilities for manipulating ABVs --> <script src="util.js"></script> <!-- A simple wrapper around IndexedDB --> <script src="simpledb.js"></script> <!-- Test vectors drawn from the literature --> <script src="./test-vectors.js"></script> <!-- General testing framework --> <script src="./test-array.js"></script> <script>/*<![CDATA[*/ "use strict"; // ----------------------------------------------------------------------------- TestArray.addTest( "Key wrap known answer, using AES-GCM", function () { var that = this; var alg = { name: "AES-GCM", iv: tv.key_wrap_known_answer.wrapping_iv, tagLength: 128 }; var key, wrappingKey; function doImport(k) { wrappingKey = k; return crypto.subtle.importKey("raw", tv.key_wrap_known_answer.key, alg, true, ['encrypt', 'decrypt']); } function doWrap(k) { key = k; return crypto.subtle.wrapKey("raw", key, wrappingKey, alg); } crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, alg, false, ['wrapKey']) .then(doImport, error(that)) .then(doWrap, error(that)) .then( memcmp_complete(that, tv.key_wrap_known_answer.wrapped_key), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "Key wrap failing on non-extractable key", function () { var that = this; var alg = { name: "AES-GCM", iv: tv.key_wrap_known_answer.wrapping_iv, tagLength: 128 }; var key, wrappingKey; function doImport(k) { wrappingKey = k; return crypto.subtle.importKey("raw", tv.key_wrap_known_answer.key, alg, false, ['encrypt', 'decrypt']); } function doWrap(k) { key = k; return crypto.subtle.wrapKey("raw", key, wrappingKey, alg); } crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, alg, false, ['wrapKey']) .then(doImport, error(that)) .then(doWrap, error(that)) .then( error(that), complete(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "Key unwrap known answer, using AES-GCM", function () { var that = this; var alg = { name: "AES-GCM", iv: tv.key_wrap_known_answer.wrapping_iv, tagLength: 128 }; var key, wrappingKey; function doUnwrap(k) { wrappingKey = k; return crypto.subtle.unwrapKey( "raw", tv.key_wrap_known_answer.wrapped_key, wrappingKey, alg, "AES-GCM", true, ['encrypt', 'decrypt'] ); } function doExport(k) { return crypto.subtle.exportKey("raw", k); } crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, alg, false, ['unwrapKey']) .then(doUnwrap, error(that)) .then(doExport, error(that)) .then( memcmp_complete(that, tv.key_wrap_known_answer.key), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "Key wrap/unwrap round-trip, using RSA-OAEP", function () { var that = this; var oaep = { name: "RSA-OAEP", hash: "SHA-256" }; var gcm = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv, additionalData: tv.aes_gcm_enc.adata, tagLength: 128 }; var unwrapKey; function doWrap(keys) { var originalKey = keys[0]; var wrapKey = keys[1]; unwrapKey = keys[2]; return crypto.subtle.wrapKey("raw", originalKey, wrapKey, oaep); } function doUnwrap(wrappedKey) { return crypto.subtle.unwrapKey("raw", wrappedKey, unwrapKey, oaep, gcm, false, ['encrypt']); } function doEncrypt(aesKey) { return crypto.subtle.encrypt(gcm, aesKey, tv.aes_gcm_enc.data); } // 1.Import: // -> HMAC key // -> OAEP wrap key (public) // -> OAEP unwrap key (private) // 2. Wrap the HMAC key // 3. Unwrap it // 4. Compute HMAC // 5. Check HMAC value Promise.all([ crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, gcm, true, ['encrypt']), crypto.subtle.importKey("spki", tv.rsaoaep.spki, oaep, true, ['wrapKey']), crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, oaep, false, ['unwrapKey']) ]) .then(doWrap, error(that)) .then(doUnwrap, error(that)) .then(doEncrypt, error(that)) .then( memcmp_complete(that, tv.aes_gcm_enc.result), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "JWK wrap/unwrap round-trip, with AES-GCM", function () { var that = this; var genAlg = { name: "HMAC", hash: "SHA-384", length: 512 }; var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv }; var wrapKey, originalKey, originalKeyJwk; function doExport(k) { return crypto.subtle.exportKey("jwk", k); } function doWrap() { return crypto.subtle.wrapKey("jwk", originalKey, wrapKey, wrapAlg); } function doUnwrap(wrappedKey) { return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg, { name: "HMAC", hash: "SHA-384"}, true, ['sign', 'verify']); } Promise.all([ crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, "AES-GCM", false, ['wrapKey','unwrapKey']) .then(function(x) { wrapKey = x; }), crypto.subtle.generateKey(genAlg, true, ['sign', 'verify']) .then(function(x) { originalKey = x; return x; }) .then(doExport) .then(function(x) { originalKeyJwk = x; }) ]) .then(doWrap) .then(doUnwrap) .then(doExport) .then( complete(that, function(x) { return exists(x.k) && x.k == originalKeyJwk.k; }), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "AES-KW known answer", function () { var that = this; function doWrap(keys) { var wrapKey = keys[0]; var originalKey = keys[1]; return crypto.subtle.wrapKey("raw", originalKey, wrapKey, "AES-KW"); } Promise.all([ crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, "AES-KW", false, ['wrapKey']), crypto.subtle.importKey("jwk", tv.aes_kw.key, "AES-GCM", true, ['encrypt']) ]) .then(doWrap) .then( memcmp_complete(that, tv.aes_kw.wrapped_key), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "AES-KW unwrap failure on tampered key data", function () { var that = this; var tamperedWrappedKey = new Uint8Array(tv.aes_kw.wrapped_key); tamperedWrappedKey[5] ^= 0xFF; function doUnwrap(wrapKey) { return crypto.subtle.unwrapKey("raw", tamperedWrappedKey, wrapKey, "AES-KW", "AES-GCM", true, ['encrypt', 'decrypt']); } crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, "AES-KW", false, ['unwrapKey']) .then(doUnwrap) .then(error(that), complete(that)); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "AES-KW wrap/unwrap round-trip", function () { var that = this; var genAlg = { name: "HMAC", hash: "SHA-384", length: 512 }; var wrapKey, originalKey, originalKeyJwk; function doExport(k) { return crypto.subtle.exportKey("jwk", k); } function doWrap() { return crypto.subtle.wrapKey("raw", originalKey, wrapKey, "AES-KW"); } function doUnwrap(wrappedKey) { return crypto.subtle.unwrapKey("raw", wrappedKey, wrapKey, "AES-KW", { name: "HMAC", hash: "SHA-384"}, true, ['sign', 'verify']); } Promise.all([ crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, "AES-KW", false, ['wrapKey','unwrapKey']) .then(function(x) { wrapKey = x; }), crypto.subtle.generateKey(genAlg, true, ['sign']) .then(function(x) { originalKey = x; return x; }) .then(doExport) .then(function(x) { originalKeyJwk = x; }) ]) .then(doWrap) .then(doUnwrap) .then(doExport) .then( complete(that, function(x) { return exists(x.k) && x.k == originalKeyJwk.k; }), error(that) ); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "JWK unwrap attempt on bogus data should error out", function () { // Largely cribbed from the "JWK wrap/unwrap round-trip, with AES-GCM" test var that = this; var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv }; var wrapKey; function doBogusWrap() { var abv = new TextEncoder("utf-8").encode("I am so not JSON"); return crypto.subtle.encrypt(wrapAlg, wrapKey, abv); } function doUnwrap(wrappedKey) { return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg, {name: "HMAC", hash: "SHA-384"}, true, ['sign', 'verify']); } crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, "AES-GCM", false, ['encrypt','unwrapKey']) .then(function(x) { wrapKey = x; }) .then(doBogusWrap, error(that)) .then(doUnwrap, error(that)) .then( error(that), complete(that) ); } ); /*]]>*/</script> </head> <body> <div id="content"> <div id="head"> <b>Web</b>Crypto<br> </div> <div id="start" onclick="start();">RUN ALL</div> <div id="resultDiv" class="content"> Summary: <span class="pass"><span id="passN">0</span> passed, </span> <span class="fail"><span id="failN">0</span> failed, </span> <span class="pending"><span id="pendingN">0</span> pending.</span> <br/> <br/> <table id="results"> <tr> <th>Test</th> <th>Result</th> <th>Time</th> </tr> </table> </div> <div id="foot"></div> </div> </body> </html>