mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
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>
This commit is contained in:
1 parent
107133ceb8
commit
56da329c76
11 files changed
+297
-11
No files matched your search
+3
-1
@@ -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) {
|
||||
|
||||
+6
-2
@@ -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)
|
||||
|
||||
+6
-2
@@ -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)
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
@@ -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`);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
+6
-2
@@ -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) {
|
||||
|
||||
+6
-2
@@ -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(
|
||||
|
||||
+38
@@ -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");
|
||||
Vendored
+1
-1
@@ -100,7 +100,7 @@
|
||||
"path": "web-locks"
|
||||
},
|
||||
"WebCryptoAPI": {
|
||||
"commit": "b638c093cd3e1849715130bcd99041f79980bb12",
|
||||
"commit": "e15690d276ae50728b9d557f4e04f894588d34a0",
|
||||
"path": "WebCryptoAPI"
|
||||
},
|
||||
"webidl": {
|
||||
|
||||
@@ -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)/],
|
||||
|
||||
Reference in new issue
Block a user