Commit 56da329c761 for nodejs
commit 56da329c761518be0005f355c8d70e8faa8599bc
Author: Node.js GitHub Bot <github-bot@iojs.org>
Date: Mon Oct 19 20:46:45 2026 -0400
test: update WPT for WebCryptoAPI to e15690d276
PR-URL: https://github.com/nodejs/node/pull/66813
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
diff --git a/test/fixtures/wpt/WebCryptoAPI/digest/digest.js b/test/fixtures/wpt/WebCryptoAPI/digest/digest.js
index 63dfd86ebf1..ab1453c58ae 100644
--- a/test/fixtures/wpt/WebCryptoAPI/digest/digest.js
+++ b/test/fixtures/wpt/WebCryptoAPI/digest/digest.js
@@ -59,7 +59,9 @@ function runDigestTests(subtle, sourceData, getVectors) {
promise_test(function () {
var buffer = new Uint8Array(sourceData[size]);
var algorithm = withNameGetter(vector.algorithm, function () {
- buffer.buffer.transfer();
+ if (!buffer.buffer.detached) {
+ buffer.buffer.transfer();
+ }
return algorithmName(vector.algorithm);
});
return subtle.digest(algorithm, buffer).then(function (result) {
diff --git a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js
index 9caecf695cf..57567fd4975 100644
--- a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js
+++ b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js
@@ -102,7 +102,9 @@ function run_test() {
var operation = subtle.encrypt({
...vector.algorithm,
get name() {
- plaintext.buffer.transfer();
+ if (!plaintext.buffer.detached) {
+ plaintext.buffer.transfer();
+ }
return vector.algorithm.name;
}
}, vector.key, plaintext)
@@ -244,7 +246,9 @@ function run_test() {
var operation = subtle.decrypt({
...vector.algorithm,
get name() {
- ciphertext.buffer.transfer();
+ if (!ciphertext.buffer.detached) {
+ ciphertext.buffer.transfer();
+ }
return vector.algorithm.name;
}
}, vector.key, ciphertext)
diff --git a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js
index 951ffd56e58..d866b7b4779 100644
--- a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js
+++ b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js
@@ -124,7 +124,9 @@ function run_test() {
var operation = subtle.decrypt({
...vector.algorithm,
get name() {
- ciphertext.buffer.transfer();
+ if (!ciphertext.buffer.detached) {
+ ciphertext.buffer.transfer();
+ }
return vector.algorithm.name;
}
}, vector.privateKey, ciphertext)
@@ -337,7 +339,9 @@ function run_test() {
var operation = subtle.encrypt({
...vector.algorithm,
get name() {
- plaintext.buffer.transfer();
+ if (!plaintext.buffer.detached) {
+ plaintext.buffer.transfer();
+ }
return vector.algorithm.name;
}
}, vector.publicKey, plaintext)
diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_fixed_length.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_fixed_length.https.any.js
new file mode 100644
index 00000000000..66123b24c79
--- /dev/null
+++ b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_fixed_length.https.any.js
@@ -0,0 +1,127 @@
+// META: title=WebCryptoAPI: OKP imports preserve fixed-length key material
+
+const message = bytes("010203");
+const peer = {
+ pkcs8: bytes("302e020100300506032b656e0422042038adaddfe94506a579a2cabcc9a50794b464689e065ed3e86b76e1ef1011f01a"),
+ spki: bytes("302a300506032b656e032100a1d178cd56e2528f7b8d82ba2e3772b219c944f0e8fbfb0d1ca3951d0ce00b13"),
+};
+
+const vectors = [
+ {
+ algorithm: "Ed25519",
+ name: "a leading-zero private key",
+ pkcs8: "302e020100300506032b6570042204200007070707070707070707070707070707070707070707070707070707070707",
+ raw: "ff812f84e53570c36ae9479aad71e649c3cc4a04a6768632150febdd66a238a8",
+ signature: "94ff57055f3b90728d704bfbf19a3e4b49806f98a10384ae01ed5c700e6d482a12dd5f6372ce160f5cf94e8cd53555a7b525658d8f4126d463fa4200578d710e",
+ spki: "302a300506032b6570032100ff812f84e53570c36ae9479aad71e649c3cc4a04a6768632150febdd66a238a8",
+ },
+ {
+ algorithm: "Ed25519",
+ name: "an all-zero private key",
+ pkcs8: "302e020100300506032b6570042204200000000000000000000000000000000000000000000000000000000000000000",
+ raw: "3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
+ signature: "2a26779ba6cbb5e54292257f725af112b273c38728329682d99ed81ba6d7670350ae4cc53c5456fa437128d19298a5d949ab46e3d41ab3dbcfb0b35c895e9304",
+ spki: "302a300506032b65700321003b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
+ },
+ {
+ algorithm: "Ed25519",
+ name: "a leading-zero public key",
+ pkcs8: "302e020100300506032b6570042204204dca5ad94292a81e64a2c780e98d5469f53523107d9b00a63e37b5097786481f",
+ raw: "00009314998a59a276e35cac5d39d9cf642b5add8fc428baca5d18a7b30cda40",
+ signature: "b6a45af39f7545b0fb894a583c5156e027a97cb09e46a999ffb269aec6fc0d0af76169c7771d09431c08ee22cb99c8966fa261097c843855cd2005678c88710a",
+ spki: "302a300506032b657003210000009314998a59a276e35cac5d39d9cf642b5add8fc428baca5d18a7b30cda40",
+ },
+ {
+ algorithm: "X25519",
+ name: "a leading-zero private key",
+ pkcs8: "302e020100300506032b656e042204200007070707070707070707070707070707070707070707070707070707070707",
+ raw: "13be4feaeaf204c7fd3358fc9c00721881d174278128227ec674f37f7fe97b6d",
+ secret: "51eafdc7ed3371472837de1aca43bee0b198aa02d1f619eb26ed1d1045bcd936",
+ spki: "302a300506032b656e03210013be4feaeaf204c7fd3358fc9c00721881d174278128227ec674f37f7fe97b6d",
+ },
+ {
+ algorithm: "X25519",
+ name: "an all-zero private key",
+ pkcs8: "302e020100300506032b656e042204200000000000000000000000000000000000000000000000000000000000000000",
+ raw: "2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74",
+ secret: "caa5f83ef211ee3ce3ae25b011f85ba0c55384769049a04bfc19770373c6df30",
+ spki: "302a300506032b656e0321002fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74",
+ },
+ {
+ algorithm: "X25519",
+ name: "a leading-zero public key",
+ pkcs8: "302e020100300506032b656e0422042031821845335f559760a05a2e1d3b0fd6e603b6a2640d969cd29e28ea9c5dddd7",
+ raw: "00a3785afdc7bb07fa13a4b075f00576cba6946a70cd6ad20b25c949eae6f636",
+ secret: "83b1b1eafc349edfc4401760c9949bc2fa95fceebd51cd7d87c2fd4a6ac85d21",
+ spki: "302a300506032b656e03210000a3785afdc7bb07fa13a4b075f00576cba6946a70cd6ad20b25c949eae6f636",
+ },
+];
+
+function bytes(hex) {
+ return new Uint8Array(hex.match(/../g).map(value => Number.parseInt(value, 16)));
+}
+
+function base64url(value) {
+ return btoa(String.fromCharCode(...value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
+}
+
+function privateBytes(pkcs8) {
+ return pkcs8.slice(-32);
+}
+
+for (const vector of vectors) {
+ promise_test(async () => {
+ const pkcs8 = bytes(vector.pkcs8);
+ const privateUsages = vector.algorithm === "Ed25519" ? ["sign"] : ["deriveBits"];
+ const privateKey = await crypto.subtle.importKey("pkcs8", pkcs8, vector.algorithm, true, privateUsages);
+
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.exportKey("pkcs8", privateKey)),
+ pkcs8,
+ "PKCS#8 round trip",
+ );
+ const jwk = await crypto.subtle.exportKey("jwk", privateKey);
+ assert_equals(jwk.d, base64url(privateBytes(pkcs8)), "JWK private key bytes");
+ assert_equals(jwk.x, base64url(bytes(vector.raw)), "JWK public key bytes");
+
+ const spki = bytes(vector.spki);
+ const publicUsages = vector.algorithm === "Ed25519" ? ["verify"] : [];
+ const publicKey = await crypto.subtle.importKey("spki", spki, vector.algorithm, true, publicUsages);
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.exportKey("spki", publicKey)),
+ spki,
+ "SPKI round trip",
+ );
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.exportKey("raw", publicKey)),
+ bytes(vector.raw),
+ "raw public key",
+ );
+
+ if (vector.algorithm === "Ed25519") {
+ const signature = new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, message));
+ assert_true(
+ await crypto.subtle.verify("Ed25519", publicKey, signature, message),
+ "generated signature verifies",
+ );
+ assert_true(
+ await crypto.subtle.verify("Ed25519", publicKey, bytes(vector.signature), message),
+ "independent reference signature verifies",
+ );
+ return;
+ }
+
+ const peerPublic = await crypto.subtle.importKey("spki", peer.spki, "X25519", false, []);
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.deriveBits({name: "X25519", public: peerPublic}, privateKey, 256)),
+ bytes(vector.secret),
+ "independent reference shared secret",
+ );
+ const peerPrivate = await crypto.subtle.importKey("pkcs8", peer.pkcs8, "X25519", false, ["deriveBits"]);
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.deriveBits({name: "X25519", public: publicKey}, peerPrivate, 256)),
+ bytes(vector.secret),
+ "imported public key shared secret",
+ );
+ }, `${vector.algorithm} preserves ${vector.name}`);
+}
diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_malformed_asn1.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_malformed_asn1.https.any.js
new file mode 100644
index 00000000000..adfd9f68c1b
--- /dev/null
+++ b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_malformed_asn1.https.any.js
@@ -0,0 +1,99 @@
+// META: title=WebCryptoAPI: OKP imports reject malformed ASN.1
+
+const vectors = [
+ {
+ algorithm: "Ed25519",
+ pkcs8: "302e020100300506032b6570042204200007070707070707070707070707070707070707070707070707070707070707",
+ raw: "ff812f84e53570c36ae9479aad71e649c3cc4a04a6768632150febdd66a238a8",
+ leadingZeroRaw: "00009314998a59a276e35cac5d39d9cf642b5add8fc428baca5d18a7b30cda40",
+ spki: "302a300506032b6570032100ff812f84e53570c36ae9479aad71e649c3cc4a04a6768632150febdd66a238a8",
+ },
+ {
+ algorithm: "X25519",
+ pkcs8: "302e020100300506032b656e042204200007070707070707070707070707070707070707070707070707070707070707",
+ raw: "13be4feaeaf204c7fd3358fc9c00721881d174278128227ec674f37f7fe97b6d",
+ leadingZeroRaw: "00a3785afdc7bb07fa13a4b075f00576cba6946a70cd6ad20b25c949eae6f636",
+ spki: "302a300506032b656e03210013be4feaeaf204c7fd3358fc9c00721881d174278128227ec674f37f7fe97b6d",
+ },
+];
+
+function bytes(hex) {
+ return new Uint8Array(hex.match(/../g).map(value => Number.parseInt(value, 16)));
+}
+
+function spki(algorithm, raw) {
+ const oid = algorithm === "Ed25519" ? 0x70 : 0x6e;
+ return new Uint8Array([
+ 0x30, raw.length + 10,
+ 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, oid,
+ 0x03, raw.length + 1, 0x00,
+ ...raw,
+ ]);
+}
+
+for (const vector of vectors) {
+ for (const format of ["pkcs8", "spki"]) {
+ promise_test(async test => {
+ const encoded = bytes(vector[format]);
+ const usages = format === "pkcs8"
+ ? (vector.algorithm === "Ed25519" ? ["sign"] : ["deriveBits"])
+ : (vector.algorithm === "Ed25519" ? ["verify"] : []);
+ await promise_rejects_dom(
+ test,
+ "DataError",
+ crypto.subtle.importKey(format, encoded.slice(0, -1), vector.algorithm, true, usages),
+ "truncated input",
+ );
+ const invalidTag = encoded.slice();
+ invalidTag[0] = 0x31;
+ await promise_rejects_dom(
+ test,
+ "DataError",
+ crypto.subtle.importKey(format, invalidTag, vector.algorithm, true, usages),
+ "invalid outer ASN.1 tag",
+ );
+ }, `${vector.algorithm} rejects malformed ${format}`);
+ }
+}
+
+for (const vector of vectors) {
+ const usages = vector.algorithm === "Ed25519" ? ["verify"] : [];
+ const raw = bytes(vector.raw);
+ const leadingZeroRaw = bytes(vector.leadingZeroRaw);
+
+ promise_test(async () => {
+ const key = await crypto.subtle.importKey(
+ "spki",
+ spki(vector.algorithm, leadingZeroRaw),
+ vector.algorithm,
+ true,
+ usages,
+ );
+ assert_array_equals(
+ new Uint8Array(await crypto.subtle.exportKey("raw", key)),
+ leadingZeroRaw,
+ "valid fixed-width public value",
+ );
+ }, `${vector.algorithm} accepts a valid 32-byte leading-zero SPKI public value`);
+
+ const invalidPublicValues = [
+ { name: "31-byte", raw: raw.slice(1) },
+ { name: "33-byte", raw: new Uint8Array([...raw, 0x01]) },
+ { name: "leading-zero 33-byte", raw: new Uint8Array([0x00, ...raw]) },
+ ];
+ for (const invalid of invalidPublicValues) {
+ promise_test(async test => {
+ await promise_rejects_dom(
+ test,
+ "DataError",
+ crypto.subtle.importKey(
+ "spki",
+ spki(vector.algorithm, invalid.raw),
+ vector.algorithm,
+ true,
+ usages,
+ ),
+ );
+ }, `${vector.algorithm} rejects a ${invalid.name} SPKI public value`);
+ }
+}
diff --git a/test/fixtures/wpt/WebCryptoAPI/modern-algos/digest/xof_digest.js b/test/fixtures/wpt/WebCryptoAPI/modern-algos/digest/xof_digest.js
index f5ef5846b79..124d74f6392 100644
--- a/test/fixtures/wpt/WebCryptoAPI/modern-algos/digest/xof_digest.js
+++ b/test/fixtures/wpt/WebCryptoAPI/modern-algos/digest/xof_digest.js
@@ -98,7 +98,9 @@ function runXofDigestTests(subtle, options) {
var duringCallParams = {
get name() {
// Transfer the buffer while calling digest
- buffer.buffer.transfer();
+ if (!buffer.buffer.detached) {
+ buffer.buffer.transfer();
+ }
return alg;
},
outputLength: outputLength,
diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/mac.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/mac.js
index 27787c91d8a..fd92e0c4949 100644
--- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/mac.js
+++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/mac.js
@@ -107,7 +107,9 @@ function runMacTests(options) {
promise_test(function(test) {
var signature = copyBuffer(vector.signature);
var operation = subtle.verify(operationAlgorithm(vector, function() {
- signature.buffer.transfer();
+ if (!signature.buffer.detached) {
+ signature.buffer.transfer();
+ }
return options.operationAlgorithm(vector).name;
}), vector.key, signature, vector.plaintext)
.then(function(is_verified) {
@@ -212,7 +214,9 @@ function runMacTests(options) {
promise_test(function(test) {
var plaintext = copyBuffer(vector.plaintext);
var operation = subtle.verify(operationAlgorithm(vector, function() {
- plaintext.buffer.transfer();
+ if (!plaintext.buffer.detached) {
+ plaintext.buffer.transfer();
+ }
return options.operationAlgorithm(vector).name;
}), vector.key, vector.signature, plaintext)
.then(function(is_verified) {
diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/signature.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/signature.js
index 2d734e1d973..1c6efa0bd22 100644
--- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/signature.js
+++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/signature.js
@@ -125,7 +125,9 @@ function runSignatureTests(options) {
const key = await publicKey(vector);
const signature = copyBuffer(vector.signature);
const duringCallAlgorithm = algorithmWithNameGetter(vector, function () {
- signature.buffer.transfer();
+ if (!signature.buffer.detached) {
+ signature.buffer.transfer();
+ }
return algorithmName(vector);
});
const isVerified = await subtle.verify(
@@ -174,7 +176,9 @@ function runSignatureTests(options) {
const key = await publicKey(vector);
const data = copyBuffer(vector.data);
const duringCallAlgorithm = algorithmWithNameGetter(vector, function () {
- data.buffer.transfer();
+ if (!data.buffer.detached) {
+ data.buffer.transfer();
+ }
return algorithmName(vector);
});
const isVerified = await subtle.verify(
diff --git a/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/aes_kw_unwrapKey_failures.https.any.js b/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/aes_kw_unwrapKey_failures.https.any.js
new file mode 100644
index 00000000000..aa198151a1f
--- /dev/null
+++ b/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/aes_kw_unwrapKey_failures.https.any.js
@@ -0,0 +1,38 @@
+// META: title=WebCryptoAPI: unwrapKey() with invalid AES-KW wrapped keys
+
+// Test vector from RFC 3394, section 4.1: wrap 128 bits of key data with a
+// 128-bit KEK.
+var kekBytes = new Uint8Array([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]);
+var keyBytes = new Uint8Array([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
+var wrappedKeyBytes = new Uint8Array([0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
+ 0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, 0x9d, 0x3e, 0x86, 0x23,
+ 0x71, 0xd2, 0xcf, 0xe5]);
+
+function importKek() {
+ return crypto.subtle.importKey("raw", kekBytes, "AES-KW", false, ["unwrapKey"]);
+}
+
+function unwrapKey(kek, wrappedKey) {
+ return crypto.subtle.unwrapKey("raw", wrappedKey, kek, "AES-KW", "AES-CBC", true, ["encrypt", "decrypt"]);
+}
+
+promise_test(async () => {
+ const kek = await importKek();
+ const key = await unwrapKey(kek, wrappedKeyBytes);
+ const exported = new Uint8Array(await crypto.subtle.exportKey("raw", key));
+ assert_array_equals(exported, keyBytes);
+}, "AES-KW unwrapKey with a valid wrapped key");
+
+promise_test(async (t) => {
+ const kek = await importKek();
+ const tamperedKeyBytes = wrappedKeyBytes.slice();
+ tamperedKeyBytes[tamperedKeyBytes.length - 1] ^= 1;
+ return promise_rejects_dom(t, "OperationError", unwrapKey(kek, tamperedKeyBytes));
+}, "AES-KW unwrapKey with a tampered wrapped key");
+
+promise_test(async (t) => {
+ const kek = await importKek();
+ return promise_rejects_dom(t, "OperationError", unwrapKey(kek, wrappedKeyBytes.slice(0, 16)));
+}, "AES-KW unwrapKey with a wrapped key shorter than 24 bytes");
diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json
index 2d12ad45360..711d469cc36 100644
--- a/test/fixtures/wpt/versions.json
+++ b/test/fixtures/wpt/versions.json
@@ -100,7 +100,7 @@
"path": "web-locks"
},
"WebCryptoAPI": {
- "commit": "b638c093cd3e1849715130bcd99041f79980bb12",
+ "commit": "e15690d276ae50728b9d557f4e04f894588d34a0",
"path": "WebCryptoAPI"
},
"webidl": {
diff --git a/test/wpt/status/WebCryptoAPI.cjs b/test/wpt/status/WebCryptoAPI.cjs
index 606cbbac34d..a73db3793a9 100644
--- a/test/wpt/status/WebCryptoAPI.cjs
+++ b/test/wpt/status/WebCryptoAPI.cjs
@@ -176,6 +176,8 @@ if (hasFIPS(3, 5)) {
'derive_bits_keys/derived_bits_length.https.any.js',
/^X25519 derivation/,
],
+ ['import_export/okp_fixed_length.https.any.js', /^X25519 /],
+ ['import_export/okp_malformed_asn1.https.any.js', /^X25519 /],
['modern-algos/encap_decap/encap_decap_bits.https.any.js', /mlkem/i],
['modern-algos/encap_decap/encap_decap_keys.https.any.js', /mlkem/i],
['modern-algos/getPublicKey.https.any.js', /(?:X25519|X448|MLKEM)/],