| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f56e628 commit 3cf7cfb
15 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -274,6 +274,14 @@ async function cfrgImportKey( | |||
| 274 | 274 | 'DataError'); | |
| 275 | 275 | } | |
| 276 | 276 | ||
| 277 | + if (keyData.alg !== undefined && (name === 'Ed25519' || name === 'Ed448')) { | ||
| 278 | + if (keyData.alg !== name && keyData.alg !== 'EdDSA') { | ||
| 279 | + throw lazyDOMException( | ||
| 280 | + 'JWK "alg" does not match the requested algorithm', | ||
| 281 | + 'DataError'); | ||
| 282 | + } | ||
| 283 | + } | ||
| 284 | + | ||
| 277 | 285 | if (!isPublic && typeof keyData.x !== 'string') { | |
| 278 | 286 | throw lazyDOMException('Invalid JWK', 'DataError'); | |
| 279 | 287 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -475,6 +475,7 @@ async function exportKeyJWK(key) { | |||
| 475 | 475 | // Fall through | |
| 476 | 476 | case 'Ed448': | |
| 477 | 477 | jwk.crv ||= key.algorithm.name; | |
| 478 | + jwk.alg = key.algorithm.name; | ||
| 478 | 479 | return jwk; | |
| 479 | 480 | case 'AES-CTR': | |
| 480 | 481 | // Fall through | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,7 +31,7 @@ Last update: | |||
| 31 | 31 | - user-timing: https://github.com/web-platform-tests/wpt/tree/5ae85bf826/user-timing | |
| 32 | 32 | - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi | |
| 33 | 33 | - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi | |
| 34 | - - WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/b81831169b/WebCryptoAPI | ||
| 34 | + - WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/edd42c005c/WebCryptoAPI | ||
| 35 | 35 | - webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions | |
| 36 | 36 | - webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/e97fac4791/webmessaging/broadcastchannel | |
| 37 | 37 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,44 @@ | |||
| 1 | + // META: title=WebCryptoAPI: CryptoKey cached ECMAScript objects | ||
| 2 | + | ||
| 3 | + // https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm | ||
| 4 | + // https://github.com/servo/servo/issues/33908 | ||
| 5 | + | ||
| 6 | + promise_test(function() { | ||
| 7 | + return self.crypto.subtle.generateKey( | ||
| 8 | + { | ||
| 9 | + name: "AES-CTR", | ||
| 10 | + length: 256, | ||
| 11 | + }, | ||
| 12 | + true, | ||
| 13 | + ["encrypt"], | ||
| 14 | + ).then( | ||
| 15 | + function(key) { | ||
| 16 | + let a = key.algorithm; | ||
| 17 | + let b = key.algorithm; | ||
| 18 | + assert_true(a === b); | ||
| 19 | + }, | ||
| 20 | + function(err) { | ||
| 21 | + assert_unreached("generateKey threw an unexpected error: " + err.toString()); | ||
| 22 | + } | ||
| 23 | + ); | ||
| 24 | + }, "CryptoKey.algorithm getter returns cached object"); | ||
| 25 | + | ||
| 26 | + promise_test(function() { | ||
| 27 | + return self.crypto.subtle.generateKey( | ||
| 28 | + { | ||
| 29 | + name: "AES-CTR", | ||
| 30 | + length: 256, | ||
| 31 | + }, | ||
| 32 | + true, | ||
| 33 | + ["encrypt"], | ||
| 34 | + ).then( | ||
| 35 | + function(key) { | ||
| 36 | + let a = key.usages; | ||
| 37 | + let b = key.usages; | ||
| 38 | + assert_true(a === b); | ||
| 39 | + }, | ||
| 40 | + function(err) { | ||
| 41 | + assert_unreached("generateKey threw an unexpected error: " + err.toString()); | ||
| 42 | + } | ||
| 43 | + ); | ||
| 44 | + }, "CryptoKey.usages getter returns cached object"); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -118,6 +118,20 @@ | |||
| 118 | 118 | }); | |
| 119 | 119 | }); | |
| 120 | 120 | ||
| 121 | + // Call digest() with empty algorithm object | ||
| 122 | + Object.keys(sourceData).forEach(function(size) { | ||
| 123 | + promise_test(function(test) { | ||
| 124 | + var promise = subtle.digest({}, sourceData[size]) | ||
| 125 | + .then(function(result) { | ||
| 126 | + assert_unreached("digest() with missing algorithm name should have thrown a TypeError"); | ||
| 127 | + }, function(err) { | ||
| 128 | + assert_equals(err.name, "TypeError", "Missing algorithm name should cause TypeError") | ||
| 129 | + }); | ||
| 130 | + | ||
| 131 | + return promise; | ||
| 132 | + }, "empty algorithm object with " + size); | ||
| 133 | + }); | ||
| 134 | + | ||
| 121 | 135 | ||
| 122 | 136 | done(); | |
| 123 | 137 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -166,6 +166,14 @@ function run_test(algorithmNames) { | |||
| 166 | 166 | }); | |
| 167 | 167 | }); | |
| 168 | 168 | ||
| 169 | + // Empty algorithm should fail with TypeError | ||
| 170 | + allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used | ||
| 171 | + .forEach(function(usages) { | ||
| 172 | + [false, true, "RED", 7].forEach(function(extractable){ | ||
| 173 | + testError({}, extractable, usages, "TypeError", "Empty algorithm"); | ||
| 174 | + }); | ||
| 175 | + }); | ||
| 176 | + | ||
| 169 | 177 | ||
| 170 | 178 | // Algorithms normalize okay, but usages bad (though not empty). | |
| 171 | 179 | // It shouldn't matter what other extractable is. Should fail | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,6 +19,14 @@ function getMismatchedJWKKeyData(algorithm) { | |||
| 19 | 19 | return []; | |
| 20 | 20 | } | |
| 21 | 21 | ||
| 22 | + function getMismatchedKtyField(algorithm) { | ||
| 23 | + return mismatchedKtyField[algorithm.name]; | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + function getMismatchedCrvField(algorithm) { | ||
| 27 | + return mismatchedCrvField[algorithm.name]; | ||
| 28 | + } | ||
| 29 | + | ||
| 22 | 30 | var validKeyData = { | |
| 23 | 31 | "P-521": [ | |
| 24 | 32 | { | |
@@ -201,3 +209,17 @@ var missingJWKFieldKeyData = { | |||
| 201 | 209 | } | |
| 202 | 210 | ] | |
| 203 | 211 | }; | |
| 212 | + | ||
| 213 | + // The 'kty' field doesn't match the key algorithm. | ||
| 214 | + var mismatchedKtyField = { | ||
| 215 | + "P-521": "OKP", | ||
| 216 | + "P-256": "OKP", | ||
| 217 | + "P-384": "OKP", | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + // The 'kty' field doesn't match the key algorithm. | ||
| 221 | + var mismatchedCrvField = { | ||
| 222 | + "P-521": "P-256", | ||
| 223 | + "P-256": "P-384", | ||
| 224 | + "P-384": "P-521", | ||
| 225 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -192,4 +192,79 @@ function run_test(algorithmNames) { | |||
| 192 | 192 | }); | |
| 193 | 193 | }); | |
| 194 | 194 | }); | |
| 195 | + | ||
| 196 | + // Missing mandatory "name" field on algorithm | ||
| 197 | + testVectors.forEach(function(vector) { | ||
| 198 | + var name = vector.name; | ||
| 199 | + // We just need *some* valid keydata, so pick the first available algorithm. | ||
| 200 | + var algorithm = allAlgorithmSpecifiersFor(name)[0]; | ||
| 201 | + getValidKeyData(algorithm).forEach(function(test) { | ||
| 202 | + validUsages(vector, test.format, test.data).forEach(function(usages) { | ||
| 203 | + [true, false].forEach(function(extractable) { | ||
| 204 | + testError(test.format, {}, test.data, name, usages, extractable, "TypeError", "Missing algorithm name"); | ||
| 205 | + }); | ||
| 206 | + }); | ||
| 207 | + }); | ||
| 208 | + }); | ||
| 209 | + | ||
| 210 | + // The 'kty' field is not correct. | ||
| 211 | + testVectors.forEach(function(vector) { | ||
| 212 | + var name = vector.name; | ||
| 213 | + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { | ||
| 214 | + getValidKeyData(algorithm).forEach(function(test) { | ||
| 215 | + if (test.format === "jwk") { | ||
| 216 | + var data = {crv: test.data.crv, kty: test.data.kty, d: test.data.d, x: test.data.x, d: test.data.d}; | ||
| 217 | + data.kty = getMismatchedKtyField(algorithm); | ||
| 218 | + var usages = validUsages(vector, 'jwk', test.data); | ||
| 219 | + testError('jwk', algorithm, data, name, usages, true, "DataError", "Invalid 'kty' field"); | ||
| 220 | + } | ||
| 221 | + }); | ||
| 222 | + }); | ||
| 223 | + }); | ||
| 224 | + | ||
| 225 | + // The 'ext' field is not correct. | ||
| 226 | + testVectors.forEach(function(vector) { | ||
| 227 | + var name = vector.name; | ||
| 228 | + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { | ||
| 229 | + getValidKeyData(algorithm).forEach(function(test) { | ||
| 230 | + if (test.format === "jwk") { | ||
| 231 | + var data = {crv: test.data.crv, kty: test.data.kty, d: test.data.d, x: test.data.x, d: test.data.d}; | ||
| 232 | + data.ext = false; | ||
| 233 | + var usages = validUsages(vector, 'jwk', test.data); | ||
| 234 | + testError('jwk', algorithm, data, name, usages, true, "DataError", "Import from a non-extractable"); | ||
| 235 | + } | ||
| 236 | + }); | ||
| 237 | + }); | ||
| 238 | + }); | ||
| 239 | + | ||
| 240 | + // The 'use' field is incorrect. | ||
| 241 | + testVectors.forEach(function(vector) { | ||
| 242 | + var name = vector.name; | ||
| 243 | + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { | ||
| 244 | + getValidKeyData(algorithm).forEach(function(test) { | ||
| 245 | + if (test.format === "jwk") { | ||
| 246 | + var data = {crv: test.data.crv, kty: test.data.kty, d: test.data.d, x: test.data.x, d: test.data.d}; | ||
| 247 | + data.use = "invalid"; | ||
| 248 | + var usages = validUsages(vector, 'jwk', test.data); | ||
| 249 | + if (usages.length !== 0) | ||
| 250 | + testError('jwk', algorithm, data, name, usages, true, "DataError", "Invalid 'use' field"); | ||
| 251 | + } | ||
| 252 | + }); | ||
| 253 | + }); | ||
| 254 | + }); | ||
| 255 | + | ||
| 256 | + // The 'crv' field is incorrect. | ||
| 257 | + testVectors.forEach(function(vector) { | ||
| 258 | + var name = vector.name; | ||
| 259 | + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { | ||
| 260 | + getValidKeyData(algorithm).forEach(function(test) { | ||
| 261 | + if (test.format === "jwk") { | ||
| 262 | + var data = {crv: test.data.crv, kty: test.data.kty, d: test.data.d, x: test.data.x, d: test.data.d}; | ||
| 263 | + data.crv = getMismatchedCrvField(algorithm) | ||
| 264 | + var usages = validUsages(vector, 'jwk', test.data); | ||
| 265 | + testError('jwk', algorithm, data, name, usages, true, "DataError", "Invalid 'crv' field"); | ||
| 266 | + } | ||
| 267 | + }); | ||
| 268 | + }); | ||
| 269 | + }); | ||
| 195 | 270 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,7 +11,7 @@ function runTests(algorithmName) { | |||
| 11 | 11 | ['spki', 'jwk', 'raw'].forEach(function(format) { | |
| 12 | 12 | if (format === "jwk") { // Not all fields used for public keys | |
| 13 | 13 | testFormat(format, algorithm, jwkData, algorithmName, usages, extractable); | |
| 14 | - // Test for https://github.com/WICG/webcrypto-secure-curves/pull/24 | ||
| 14 | + // Test for https://github.com/w3c/webcrypto/pull/401 | ||
| 15 | 15 | if (extractable) { | |
| 16 | 16 | testJwkAlgBehaviours(algorithm, jwkData.jwk, algorithmName, usages); | |
| 17 | 17 | } | |
@@ -27,7 +27,7 @@ function runTests(algorithmName) { | |||
| 27 | 27 | ['pkcs8', 'jwk'].forEach(function(format) { | |
| 28 | 28 | testFormat(format, algorithm, data, algorithmName, usages, extractable); | |
| 29 | 29 | ||
| 30 | - // Test for https://github.com/WICG/webcrypto-secure-curves/pull/24 | ||
| 30 | + // Test for https://github.com/w3c/webcrypto/pull/401 | ||
| 31 | 31 | if (format === "jwk" && extractable) { | |
| 32 | 32 | testJwkAlgBehaviours(algorithm, data.jwk, algorithmName, usages); | |
| 33 | 33 | } | |
@@ -67,27 +67,34 @@ function testFormat(format, algorithm, keyData, keySize, usages, extractable) { | |||
| 67 | 67 | }); | |
| 68 | 68 | } | |
| 69 | 69 | ||
| 70 | - // Test importKey/exportKey "alg" behaviours, alg is ignored upon import and alg is missing for Ed25519 and Ed448 JWK export | ||
| 71 | - // https://github.com/WICG/webcrypto-secure-curves/pull/24 | ||
| 70 | + // Test importKey/exportKey "alg" behaviours (https://github.com/w3c/webcrypto/pull/401) | ||
| 71 | + // - alg is ignored for ECDH import | ||
| 72 | + // - TODO: alg is checked to be the algorithm.name or EdDSA for Ed25519 and Ed448 import | ||
| 73 | + // - alg is missing for ECDH export | ||
| 74 | + // - alg is the algorithm name for Ed25519 and Ed448 export | ||
| 72 | 75 | function testJwkAlgBehaviours(algorithm, keyData, crv, usages) { | |
| 73 | 76 | [algorithm, algorithm.name].forEach((alg) => { | |
| 74 | - promise_test(function(test) { | ||
| 75 | - return subtle.importKey('jwk', { ...keyData, alg: 'this is ignored' }, alg, true, usages). | ||
| 76 | - then(function(key) { | ||
| 77 | - assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object"); | ||
| 78 | - | ||
| 79 | - return subtle.exportKey('jwk', key). | ||
| 80 | - then(function(result) { | ||
| 81 | - assert_equals(Object.keys(result).length, keyData.d ? 6 : 5, "Correct number of JWK members"); | ||
| 82 | - assert_equals(result.alg, undefined, 'No JWK "alg" member is present'); | ||
| 83 | - assert_true(equalJwk(keyData, result), "Round trip works"); | ||
| 84 | - }, function(err) { | ||
| 77 | + (crv.startsWith('Ed') ? [algorithm.name, 'EdDSA'] : ['this is ignored']).forEach((jwkAlg) => { | ||
| 78 | + promise_test(function(test) { | ||
| 79 | + return subtle.importKey('jwk', { ...keyData, alg: jwkAlg }, alg, true, usages). | ||
| 80 | + then(function(key) { | ||
| 81 | + assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object"); | ||
| 82 | + | ||
| 83 | + return subtle.exportKey('jwk', key). | ||
| 84 | + then(function(result) { | ||
| 85 | + let expectedKeys = crv.startsWith('Ed') ? 6 : 5 | ||
| 86 | + if (keyData.d) expectedKeys++ | ||
| 87 | + assert_equals(Object.keys(result).length, expectedKeys, "Correct number of JWK members"); | ||
| 88 | + assert_equals(result.alg, crv.startsWith('Ed') ? algorithm.name : undefined, 'Expected JWK "alg" member'); | ||
| 89 | + assert_true(equalJwk(keyData, result), "Round trip works"); | ||
| 90 | + }, function(err) { | ||
| 91 | + assert_unreached("Threw an unexpected error: " + err.toString()); | ||
| 92 | + }); | ||
| 93 | + }, function(err) { | ||
| 85 | 94 | assert_unreached("Threw an unexpected error: " + err.toString()); | |
| 86 | - }); | ||
| 87 | - }, function(err) { | ||
| 88 | - assert_unreached("Threw an unexpected error: " + err.toString()); | ||
| 89 | - }); | ||
| 90 | - }, "Good parameters with ignored JWK alg: " + crv.toString() + " " + parameterString('jwk', keyData, alg, true, usages)); | ||
| 95 | + }); | ||
| 96 | + }, 'Good parameters with JWK alg' + (crv.startsWith('Ed') ? ` ${jwkAlg}: ` : ': ') + crv.toString() + " " + parameterString('jwk', keyData, alg, true, usages, jwkAlg)); | ||
| 97 | + }); | ||
| 91 | 98 | }); | |
| 92 | 99 | } | |
| 93 | 100 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments