diff options
Diffstat (limited to '')
-rw-r--r-- | dom/crypto/test/test_WebCrypto_JWK.html | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/dom/crypto/test/test_WebCrypto_JWK.html b/dom/crypto/test/test_WebCrypto_JWK.html new file mode 100644 index 0000000000..6e83a73d8d --- /dev/null +++ b/dom/crypto/test/test_WebCrypto_JWK.html @@ -0,0 +1,369 @@ +<!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( + "JWK import and use of an AES-GCM key", + function() { + var that = this; + + function doEncrypt(x) { + return crypto.subtle.encrypt( + { + name: "AES-GCM", + iv: tv.aes_gcm_enc.iv, + additionalData: tv.aes_gcm_enc.adata, + tagLength: 128, + }, + x, tv.aes_gcm_enc.data); + } + + crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, "AES-GCM", false, ["encrypt"]) + .then(doEncrypt) + .then( + memcmp_complete(that, tv.aes_gcm_enc.result), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import and use of an RSASSA-PKCS1-v1_5 private key", + function() { + var that = this; + var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; + + function doSign(x) { + return crypto.subtle.sign(alg.name, x, tv.rsassa.data); + } + function fail(x) { console.log(x); error(that); } + + crypto.subtle.importKey("jwk", tv.rsassa.jwk_priv, alg, false, ["sign"]) + .then( doSign, fail ) + .then( memcmp_complete(that, tv.rsassa.sig256), fail ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import and use of an RSASSA-PKCS1-v1_5 public key", + function() { + var that = this; + var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; + + function doVerify(x) { + return crypto.subtle.verify(alg.name, x, tv.rsassa.sig256, tv.rsassa.data); + } + function fail(x) { error(that); } + + crypto.subtle.importKey("jwk", tv.rsassa.jwk_pub, alg, false, ["verify"]) + .then( doVerify, fail ) + .then( + complete(that, function(x) { return x; }), + fail + ); + }); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import failure on incomplete RSA private key (missing 'qi')", + function() { + var that = this; + var alg = { name: "RSA-OAEP", hash: "SHA-256" }; + var jwk = { + kty: "RSA", + n: tv.rsassa.jwk_priv.n, + e: tv.rsassa.jwk_priv.e, + d: tv.rsassa.jwk_priv.d, + p: tv.rsassa.jwk_priv.p, + q: tv.rsassa.jwk_priv.q, + dp: tv.rsassa.jwk_priv.dp, + dq: tv.rsassa.jwk_priv.dq, + }; + + crypto.subtle.importKey("jwk", jwk, alg, true, ["encrypt", "decrypt"]) + .then( error(that), complete(that) ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import failure on algorithm mismatch", + function() { + var that = this; + var alg = "AES-GCM"; + var jwk = { k: "c2l4dGVlbiBieXRlIGtleQ", alg: "A256GCM" }; + + crypto.subtle.importKey("jwk", jwk, alg, true, ["encrypt", "decrypt"]) + .then( error(that), complete(that) ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import failure on usages mismatch", + function() { + var that = this; + var alg = "AES-GCM"; + var jwk = { k: "c2l4dGVlbiBieXRlIGtleQ", key_ops: ["encrypt"] }; + + crypto.subtle.importKey("jwk", jwk, alg, true, ["encrypt", "decrypt"]) + .then( error(that), complete(that) ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import failure on extractable mismatch", + function() { + var that = this; + var alg = "AES-GCM"; + var jwk = { k: "c2l4dGVlbiBieXRlIGtleQ", ext: false }; + + crypto.subtle.importKey("jwk", jwk, alg, true, ["encrypt"]) + .then( error(that), complete(that) ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK export of a symmetric key", + function() { + var that = this; + var alg = "AES-GCM"; + var jwk = { k: "c2l4dGVlbiBieXRlIGtleQ", kty: "oct" }; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + + crypto.subtle.importKey("jwk", jwk, alg, true, ["encrypt", "decrypt"]) + .then(doExport) + .then( + complete(that, function(x) { + return hasBaseJwkFields(x) && + hasFields(x, ["k"]) && + x.kty == "oct" && + x.alg == "A128GCM" && + x.ext && + shallowArrayEquals(x.key_ops, ["encrypt", "decrypt"]) && + x.k == jwk.k; + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import/export of an RSA private key", + function() { + var jwk = tv.rsassa.jwk_priv; + + var that = this; + var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + + crypto.subtle.importKey("jwk", jwk, alg, true, ["sign"]) + .then(doExport) + .then( + complete(that, function(x) { + return hasBaseJwkFields(x) && + hasFields(x, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]) && + x.kty == "RSA" && + x.alg == "RS256" && + x.ext && + shallowArrayEquals(x.key_ops, ["sign"]) && + x.n == jwk.n && + x.e == jwk.e && + x.d == jwk.d && + x.p == jwk.p && + x.q == jwk.q && + x.dp == jwk.dp && + x.dq == jwk.dq && + x.qi == jwk.qi; + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK import/export of an RSA private key where p < q", + function() { + var jwk = tv.rsassa.jwk_priv_pLTq; + + var that = this; + var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + + crypto.subtle.importKey("jwk", jwk, alg, true, ["sign"]) + .then(doExport) + .then( + complete(that, function(x) { + return hasBaseJwkFields(x) && + hasFields(x, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]) && + x.kty == "RSA" && + x.alg == "RS256" && + x.ext && + shallowArrayEquals(x.key_ops, ["sign"]) && + x.n == jwk.n && + x.e == jwk.e && + x.d == jwk.d && + x.p == jwk.p && + x.q == jwk.q && + x.dp == jwk.dp && + x.dq == jwk.dq && + x.qi == jwk.qi; + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK export of an RSA public key", + function() { + var that = this; + var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }; + var jwk = tv.rsassa.jwk_pub; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + + crypto.subtle.importKey("jwk", jwk, alg, true, ["verify"]) + .then(doExport) + .then( + complete(that, function(x) { + window.jwk_pub = x; + return hasBaseJwkFields(x) && + hasFields(x, ["n", "e"]) && + x.kty == "RSA" && + x.alg == "RS256" && + x.ext && + shallowArrayEquals(x.key_ops, ["verify"]) && + x.n == jwk.n && + x.e == jwk.e; + }), + error(that) + ); + } +); + +// -------- +TestArray.addTest( + "Check JWK parameters on generated ECDSA key pair", + function() { + crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]) + .then(pair => Promise.all([ + crypto.subtle.exportKey("jwk", pair.privateKey), + crypto.subtle.exportKey("jwk", pair.publicKey), + ])) + .then( + complete(this, function(x) { + var priv = x[0]; + var pub = x[1]; + var pubIsSubsetOfPriv = Object.keys(pub) + .filter(k => k !== "key_ops") // key_ops is the only complex attr + .reduce((all, k) => all && pub[k] === priv[k], true); + // Can't use hasBaseJwkFields() because EC keys don't get "alg": + // "alg" matches curve to hash, but WebCrypto keys are more flexible. + return hasFields(pub, ["kty", "crv", "key_ops", "ext"]) && + pub.kty === "EC" && + pub.crv === "P-256" && + pub.ext && + typeof(pub.x) === "string" && + typeof(pub.y) === "string" && + shallowArrayEquals(pub.key_ops, ["verify"]) && + pubIsSubsetOfPriv && + shallowArrayEquals(priv.key_ops, ["sign"]) && + typeof(priv.d) === "string"; + }), + error(this)); + } +); + +// -------- +TestArray.addTest( + "Check key_ops parameter on an unusable RSA public key", + function() { + var parameters = { + name: "RSASSA-PKCS1-v1_5", + modulusLength: 1024, + publicExponent: new Uint8Array([1, 0, 1]), + hash: "SHA-256", + }; + // The public key generated here will have no usages and will therefore + // have an empty key_ops list. + crypto.subtle.generateKey(parameters, true, ["sign"]) + .then(pair => crypto.subtle.exportKey("jwk", pair.publicKey)) + .then(complete(this, x => x.key_ops.length === 0), + error(this)); + } +); +/* ]]>*/</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> |