summaryrefslogtreecommitdiffstats
path: root/dom/crypto/test/test_WebCrypto_JWK.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/crypto/test/test_WebCrypto_JWK.html')
-rw-r--r--dom/crypto/test/test_WebCrypto_JWK.html369
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 000000000..f9916f5f2
--- /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>