mirror of https://github.com/nodejs/node.git
test,crypto: update WebCryptoAPI WPT
Refs: #54572 Refs: #54468 PR-URL: https://github.com/nodejs/node/pull/54593 Refs: https://github.com/nodejs/node/issues/54572 Refs: https://github.com/nodejs/node/pull/54468 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
parent
beabcec41c
commit
fc02b88f89
|
@ -458,8 +458,16 @@ class StatusLoader {
|
|||
|
||||
load() {
|
||||
const dir = path.join(__dirname, '..', 'wpt');
|
||||
const statusFile = path.join(dir, 'status', `${this.path}.json`);
|
||||
const result = JSON.parse(fs.readFileSync(statusFile, 'utf8'));
|
||||
let statusFile = path.join(dir, 'status', `${this.path}.json`);
|
||||
let result;
|
||||
|
||||
if (fs.existsSync(statusFile)) {
|
||||
result = JSON.parse(fs.readFileSync(statusFile, 'utf8'));
|
||||
} else {
|
||||
statusFile = path.join(dir, 'status', `${this.path}.cjs`);
|
||||
result = require(statusFile);
|
||||
}
|
||||
|
||||
this.rules.addRules(result);
|
||||
|
||||
const subDir = fixtures.path('wpt', this.path);
|
||||
|
|
|
@ -32,7 +32,7 @@ Last update:
|
|||
- user-timing: https://github.com/web-platform-tests/wpt/tree/5ae85bf826/user-timing
|
||||
- wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi
|
||||
- wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi
|
||||
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/5e042cbc4e/WebCryptoAPI
|
||||
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/6748a0a246/WebCryptoAPI
|
||||
- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions
|
||||
- webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/e97fac4791/webmessaging/broadcastchannel
|
||||
- webstorage: https://github.com/web-platform-tests/wpt/tree/9dafa89214/webstorage
|
||||
|
|
|
@ -6,8 +6,6 @@ function define_tests() {
|
|||
// Verify the derive functions perform checks against the all-zero value results,
|
||||
// ensuring small-order points are rejected.
|
||||
// https://www.rfc-editor.org/rfc/rfc7748#section-6.1
|
||||
// TODO: The spec states that the check must be done on use, but there is discussion about doing it on import.
|
||||
// https://github.com/WICG/webcrypto-secure-curves/pull/13
|
||||
Object.keys(kSmallOrderPoint).forEach(function(algorithmName) {
|
||||
kSmallOrderPoint[algorithmName].forEach(function(test) {
|
||||
promise_test(async() => {
|
||||
|
@ -23,8 +21,8 @@ function define_tests() {
|
|||
false, [])
|
||||
derived = await subtle.deriveBits({name: algorithmName, public: publicKey}, privateKey, 8 * sizes[algorithmName]);
|
||||
} catch (err) {
|
||||
assert_false(privateKey === undefined, "Private key should be valid.");
|
||||
assert_false(publicKey === undefined, "Public key should be valid.");
|
||||
assert_true(privateKey !== undefined, "Private key should be valid.");
|
||||
assert_true(publicKey !== undefined, "Public key should be valid.");
|
||||
assert_equals(err.name, "OperationError", "Should throw correct error, not " + err.name + ": " + err.message + ".");
|
||||
}
|
||||
assert_equals(derived, undefined, "Operation succeeded, but should not have.");
|
||||
|
@ -59,25 +57,6 @@ function define_tests() {
|
|||
});
|
||||
}, algorithmName + " mixed case parameters");
|
||||
|
||||
// Null length
|
||||
// "Null" is not valid per the current spec
|
||||
// - https://github.com/w3c/webcrypto/issues/322
|
||||
// - https://github.com/w3c/webcrypto/issues/329
|
||||
//
|
||||
// Proposal for a spec change:
|
||||
// - https://github.com/w3c/webcrypto/pull/345
|
||||
//
|
||||
// This test case may be replaced by these new tests:
|
||||
// - https://github.com/web-platform-tests/wpt/pull/43400
|
||||
promise_test(function(test) {
|
||||
return subtle.deriveBits({name: algorithmName, public: publicKeys[algorithmName]}, privateKeys[algorithmName], null)
|
||||
.then(function(derivation) {
|
||||
assert_true(equalBuffers(derivation, derivations[algorithmName]), "Derived correct bits");
|
||||
}, function(err) {
|
||||
assert_unreached("deriveBits failed with error " + err.name + ": " + err.message);
|
||||
});
|
||||
}, algorithmName + " with null length");
|
||||
|
||||
// Shorter than entire derivation per algorithm
|
||||
promise_test(function(test) {
|
||||
return subtle.deriveBits({name: algorithmName, public: publicKeys[algorithmName]}, privateKeys[algorithmName], 8 * sizes[algorithmName] - 32)
|
||||
|
|
11
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any.js
vendored
Normal file
11
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any.js
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
// META: title=WebCryptoAPI: deriveBits() tests for the 'length' parameter
|
||||
// META: script=derived_bits_length.js
|
||||
// META: script=derived_bits_length_vectors.js
|
||||
// META: script=derived_bits_length_testcases.js
|
||||
|
||||
// Define subtests from a `promise_test` to ensure the harness does not
|
||||
// complete before the subtests are available. `explicit_done` cannot be used
|
||||
// for this purpose because the global `done` function is automatically invoked
|
||||
// by the WPT infrastructure in dedicated worker tests defined using the
|
||||
// "multi-global" pattern.
|
||||
promise_test(define_tests, 'setup - define tests');
|
|
@ -0,0 +1,36 @@
|
|||
function define_tests() {
|
||||
// May want to test prefixed implementations.
|
||||
var subtle = self.crypto.subtle;
|
||||
|
||||
Object.keys(testCases).forEach(algorithm => {
|
||||
let testData = algorithms[algorithm];
|
||||
testCases[algorithm].forEach(testParam => {
|
||||
promise_test(async() => {
|
||||
let derivedBits, privateKey, publicKey;
|
||||
try {
|
||||
privateKey = await subtle.importKey(testData.privateKey.format, testData.privateKey.data, testData.importAlg, false, ["deriveBits"]);
|
||||
if (testData.deriveAlg.public !== undefined) {
|
||||
publicKey = await subtle.importKey(testData.publicKey.format, testData.publicKey.data, testData.importAlg, false, []);
|
||||
testData.deriveAlg.public = publicKey;
|
||||
}
|
||||
if (testParam.length === "omitted")
|
||||
derivedBits = await subtle.deriveBits(testData.deriveAlg, privateKey);
|
||||
else
|
||||
derivedBits = await subtle.deriveBits(testData.deriveAlg, privateKey, testParam.length);
|
||||
if (testParam.expected === undefined) {
|
||||
assert_unreached("deriveBits should have thrown an OperationError exception.");
|
||||
}
|
||||
assert_array_equals(new Uint8Array(derivedBits), testParam.expected, "Derived bits do not match the expected result.");
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError || testParam.expected !== undefined) {
|
||||
throw err;
|
||||
}
|
||||
assert_true(privateKey !== undefined, "Key should be valid.");
|
||||
assert_equals(err.name, "OperationError", "deriveBits correctly threw OperationError: " + err.message);
|
||||
}
|
||||
}, algorithm + " derivation with " + testParam.length + " as 'length' parameter");
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.resolve("define_tests");
|
||||
}
|
30
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length_testcases.js
vendored
Normal file
30
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length_testcases.js
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
var testCases = {
|
||||
"HKDF": [
|
||||
{length: 256, expected: algorithms["HKDF"].derivation},
|
||||
{length: 0, expected: undefined}, // explicitly disallowed, so should throw
|
||||
{length: null, expected: undefined }, // should throw an exception
|
||||
{length: undefined, expected: undefined }, // should throw an exception
|
||||
{length: "omitted", expected: undefined }, // default value is null, so should throw
|
||||
],
|
||||
"PBKDF2": [
|
||||
{length: 256, expected: algorithms["PBKDF2"].derivation},
|
||||
{length: 0, expected: undefined}, // explicitly disallowed, so should throw
|
||||
{length: null, expected: undefined }, // should throw an exception
|
||||
{length: undefined, expected: undefined }, // should throw an exception
|
||||
{length: "omitted", expected: undefined }, // default value is null, so should throw
|
||||
],
|
||||
"ECDH": [
|
||||
{length: 256, expected: algorithms["ECDH"].derivation},
|
||||
{length: 0, expected: emptyArray},
|
||||
{length: null, expected: algorithms["ECDH"].derivation},
|
||||
{length: undefined, expected: algorithms["ECDH"].derivation},
|
||||
{length: "omitted", expected: algorithms["ECDH"].derivation }, // default value is null
|
||||
],
|
||||
"X25519": [
|
||||
{length: 256, expected: algorithms["X25519"].derivation},
|
||||
{length: 0, expected: emptyArray},
|
||||
{length: null, expected: algorithms["X25519"].derivation},
|
||||
{length: undefined, expected: algorithms["X25519"].derivation},
|
||||
{length: "omitted", expected: algorithms["X25519"].derivation }, // default value is null
|
||||
],
|
||||
}
|
33
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length_vectors.js
vendored
Normal file
33
test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/derived_bits_length_vectors.js
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
const emptyArray = new Uint8Array([]);
|
||||
const rawKey = new Uint8Array([85, 115, 101, 114, 115, 32, 115, 104, 111, 117, 108, 100, 32, 112, 105, 99, 107, 32, 108, 111, 110, 103, 32, 112, 97, 115, 115, 112, 104, 114, 97, 115, 101, 115, 32, 40, 110, 111, 116, 32, 117, 115, 101, 32, 115, 104, 111, 114, 116, 32, 112, 97, 115, 115, 119, 111, 114, 100, 115, 41, 33]);
|
||||
const salt = new Uint8Array([83, 111, 100, 105, 117, 109, 32, 67, 104, 108, 111, 114, 105, 100, 101, 32, 99, 111, 109, 112, 111, 117, 110, 100]);
|
||||
const info = new Uint8Array([72, 75, 68, 70, 32, 101, 120, 116, 114, 97, 32, 105, 110, 102, 111]);
|
||||
|
||||
var algorithms = {
|
||||
"HKDF": {
|
||||
importAlg: {name: "HKDF"},
|
||||
privateKey: {format: "raw", data: rawKey},
|
||||
deriveAlg: {name: "HKDF", salt: salt, hash: "SHA-256", info: info},
|
||||
derivation: new Uint8Array([49, 183, 214, 133, 48, 168, 99, 231, 23, 192, 129, 202, 105, 23, 182, 134, 80, 179, 221, 154, 41, 243, 6, 6, 226, 202, 209, 153, 190, 193, 77, 19]),
|
||||
},
|
||||
"PBKDF2": {
|
||||
importAlg: {name: "PBKDF2"},
|
||||
privateKey: {format: "raw", data: rawKey},
|
||||
deriveAlg: {name: "PBKDF2", salt: salt, hash: "SHA-256", iterations: 100000},
|
||||
derivation: new Uint8Array([17, 153, 45, 139, 129, 51, 17, 36, 76, 84, 75, 98, 41, 41, 69, 226, 8, 212, 3, 206, 189, 107, 149, 82, 161, 165, 98, 6, 93, 153, 88, 234]),
|
||||
},
|
||||
"ECDH": {
|
||||
importAlg: {name: "ECDH", namedCurve: "P-256"},
|
||||
privateKey: {format: "pkcs8", data: new Uint8Array([48, 129, 135, 2, 1, 0, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 4, 109, 48, 107, 2, 1, 1, 4, 32, 15, 247, 79, 232, 241, 202, 175, 97, 92, 206, 241, 29, 217, 53, 114, 87, 98, 217, 216, 65, 236, 186, 185, 94, 170, 38, 68, 123, 52, 100, 245, 113, 161, 68, 3, 66, 0, 4, 140, 96, 11, 44, 102, 25, 45, 97, 158, 39, 210, 37, 107, 59, 151, 118, 178, 141, 30, 5, 246, 13, 234, 189, 98, 174, 123, 154, 211, 157, 224, 217, 59, 4, 102, 109, 199, 119, 14, 126, 207, 13, 211, 203, 203, 211, 110, 221, 107, 94, 220, 153, 81, 7, 55, 161, 237, 104, 46, 205, 112, 244, 10, 47])},
|
||||
publicKey: {format: "spki", data: new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 154, 116, 32, 120, 126, 95, 77, 105, 211, 232, 34, 114, 115, 1, 109, 56, 224, 71, 129, 133, 223, 127, 238, 156, 142, 103, 60, 202, 211, 79, 126, 128, 254, 49, 141, 182, 221, 107, 119, 218, 99, 32, 165, 246, 151, 89, 9, 68, 23, 177, 52, 239, 138, 139, 116, 193, 101, 4, 57, 198, 115, 0, 90, 61])},
|
||||
deriveAlg: {name: "ECDH", public: new Uint8Array ([])},
|
||||
derivation: new Uint8Array([14, 143, 60, 77, 177, 178, 162, 131, 115, 90, 0, 220, 87, 31, 26, 232, 151, 28, 227, 35, 250, 17, 131, 137, 203, 95, 65, 196, 59, 61, 181, 161]),
|
||||
},
|
||||
"X25519": {
|
||||
importAlg: {name: "X25519"},
|
||||
privateKey: {format: "pkcs8", data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 110, 4, 34, 4, 32, 200, 131, 142, 118, 208, 87, 223, 183, 216, 201, 90, 105, 225, 56, 22, 10, 221, 99, 115, 253, 113, 164, 210, 118, 187, 86, 227, 168, 27, 100, 255, 97])},
|
||||
publicKey: {format: "spki", data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 110, 3, 33, 0, 28, 242, 177, 230, 2, 46, 197, 55, 55, 30, 215, 245, 62, 84, 250, 17, 84, 216, 62, 152, 235, 100, 234, 81, 250, 229, 179, 48, 124, 254, 151, 6])},
|
||||
deriveAlg: {name: "X25519", public: new Uint8Array ([])},
|
||||
derivation: new Uint8Array([39, 104, 64, 157, 250, 185, 158, 194, 59, 140, 137, 185, 63, 245, 136, 2, 149, 247, 97, 118, 8, 143, 137, 228, 61, 254, 190, 126, 161, 149, 0, 8]),
|
||||
}
|
||||
};
|
|
@ -55,25 +55,6 @@ function define_tests() {
|
|||
});
|
||||
}, namedCurve + " mixed case parameters");
|
||||
|
||||
// Null length
|
||||
// "Null" is not valid per the current spec
|
||||
// - https://github.com/w3c/webcrypto/issues/322
|
||||
// - https://github.com/w3c/webcrypto/issues/329
|
||||
//
|
||||
// Proposal for a spec change:
|
||||
// - https://github.com/w3c/webcrypto/pull/345
|
||||
//
|
||||
// This test case may be replaced by these new tests:
|
||||
// - https://github.com/web-platform-tests/wpt/pull/43400
|
||||
promise_test(function(test) {
|
||||
return subtle.deriveBits({name: "ECDH", public: publicKeys[namedCurve]}, privateKeys[namedCurve], null)
|
||||
.then(function(derivation) {
|
||||
assert_true(equalBuffers(derivation, derivations[namedCurve]), "Derived correct bits");
|
||||
}, function(err) {
|
||||
assert_unreached("deriveBits failed with error " + err.name + ": " + err.message);
|
||||
});
|
||||
}, namedCurve + " with null length");
|
||||
|
||||
// Shorter than entire derivation per algorithm
|
||||
promise_test(function(test) {
|
||||
return subtle.deriveBits({name: "ECDH", public: publicKeys[namedCurve]}, privateKeys[namedCurve], 8 * sizes[namedCurve] - 32)
|
||||
|
|
|
@ -139,25 +139,6 @@ function define_tests() {
|
|||
});
|
||||
}, testName + " with missing info");
|
||||
|
||||
// length null (OperationError)
|
||||
// "Null" is not valid per the current spec
|
||||
// - https://github.com/w3c/webcrypto/issues/322
|
||||
// - https://github.com/w3c/webcrypto/issues/329
|
||||
//
|
||||
// Proposal for a spec change:
|
||||
// - https://github.com/w3c/webcrypto/pull/345
|
||||
//
|
||||
// This test case may be replaced by these new tests:
|
||||
// - https://github.com/web-platform-tests/wpt/pull/43400
|
||||
subsetTest(promise_test, function(test) {
|
||||
return subtle.deriveBits(algorithm, baseKeys[derivedKeySize], null)
|
||||
.then(function(derivation) {
|
||||
assert_unreached("null length should have thrown an OperationError");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "OperationError", "deriveBits with null length correctly threw OperationError: " + err.message);
|
||||
});
|
||||
}, testName + " with null length");
|
||||
|
||||
// length not multiple of 8 (OperationError)
|
||||
subsetTest(promise_test, function(test) {
|
||||
return subtle.deriveBits(algorithm, baseKeys[derivedKeySize], 44)
|
||||
|
|
|
@ -103,26 +103,6 @@ function define_tests() {
|
|||
|
||||
});
|
||||
|
||||
// Test various error conditions for deriveBits below:
|
||||
// length null (OperationError)
|
||||
// "Null" is not valid per the current spec
|
||||
// - https://github.com/w3c/webcrypto/issues/322
|
||||
// - https://github.com/w3c/webcrypto/issues/329
|
||||
//
|
||||
// Proposal for a spec change:
|
||||
// - https://github.com/w3c/webcrypto/pull/345
|
||||
//
|
||||
// This test case may be replaced by these new tests:
|
||||
// - https://github.com/web-platform-tests/wpt/pull/43400
|
||||
subsetTest(promise_test, function(test) {
|
||||
return subtle.deriveBits({name: "PBKDF2", salt: salts[saltSize], hash: hashName, iterations: parseInt(iterations)}, baseKeys[passwordSize], null)
|
||||
.then(function(derivation) {
|
||||
assert_unreached("null length should have thrown an OperationError");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "OperationError", "deriveBits with null length correctly threw OperationError: " + err.message);
|
||||
});
|
||||
}, testName + " with null length");
|
||||
|
||||
// 0 length (OperationError)
|
||||
subsetTest(promise_test, function(test) {
|
||||
return subtle.deriveBits({name: "PBKDF2", salt: salts[saltSize], hash: hashName, iterations: parseInt(iterations)}, baseKeys[passwordSize], 0)
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
// Step 1.
|
||||
test(function() {
|
||||
assert_throws_dom("TypeMismatchError", function() {
|
||||
self.crypto.getRandomValues(new Float16Array(6))
|
||||
}, "Float16Array")
|
||||
|
||||
assert_throws_dom("TypeMismatchError", function() {
|
||||
const len = 65536 / Float16Array.BYTES_PER_ELEMENT + 1;
|
||||
self.crypto.getRandomValues(new Float16Array(len));
|
||||
}, "Float16Array (too long)")
|
||||
}, "Float16 arrays");
|
||||
|
||||
test(function() {
|
||||
assert_throws_dom("TypeMismatchError", function() {
|
||||
self.crypto.getRandomValues(new Float32Array(6))
|
||||
|
@ -57,4 +68,10 @@ for (const array of arrays) {
|
|||
test(function() {
|
||||
assert_true(self.crypto.getRandomValues(new ctor(0)).length == 0)
|
||||
}, "Null arrays: " + array);
|
||||
|
||||
test(function() {
|
||||
class Buffer extends ctor {}
|
||||
// Must not throw for the test to pass
|
||||
self.crypto.getRandomValues(new Buffer(256));
|
||||
}, "Subclass of " + array);
|
||||
}
|
||||
|
|
17
test/fixtures/wpt/WebCryptoAPI/import_export/crashtests/importKey-unsettled-promise.https.any.js
vendored
Normal file
17
test/fixtures/wpt/WebCryptoAPI/import_export/crashtests/importKey-unsettled-promise.https.any.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// META: title=WebCryptoAPI: Assure promise returned by importKey is settled.
|
||||
// META: timeout=long
|
||||
// META: script=/common/gc.js
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const jwkKey = {};
|
||||
const extractable = true;
|
||||
crypto.subtle.importKey("jwk", jwkKey, {name: "UNSUPPORTED", hash: "SHA-224"}, extractable, []).then(
|
||||
() => { assert_unreached("Unsupported algorithm should cause promise rejection")},
|
||||
(err) => {
|
||||
assert_equals(err.name, "NotSupportedError");
|
||||
});
|
||||
await garbageCollect();
|
||||
})
|
||||
|
|
@ -1,363 +1,214 @@
|
|||
|
||||
function run_test() {
|
||||
setup({explicit_done: true});
|
||||
|
||||
var subtle = self.crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
// When are all these tests really done? When all the promises they use have resolved.
|
||||
var all_promises = [];
|
||||
|
||||
// Source file [algorithm_name]_vectors.js provides the getTestVectors method
|
||||
// for the algorithm that drives these tests.
|
||||
var testVectors = getTestVectors();
|
||||
|
||||
// Test verification first, because signing tests rely on that working
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, vector.signature, vector.data)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with an altered buffer after call
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, signature, vector.data)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
signature[0] = 255 - signature[0];
|
||||
return operation;
|
||||
}, vector.name + " verification with altered signature after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification with altered signature after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful verification even if data is altered after call.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
var data = copyBuffer(vector.data);
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, vector.signature, data)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
data[0] = 255 - data[0];
|
||||
return operation;
|
||||
}, vector.name + " with altered data after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with altered data after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for failures due to using privateKey to verify.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
return subtle.verify(algorithm, vector.privateKey, vector.signature, vector.data)
|
||||
.then(function(data) {
|
||||
assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name + ": " + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " using privateKey to verify");
|
||||
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " using privateKey to verify");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for failures due to using publicKey to sign.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
return subtle.sign(algorithm, vector.publicKey, vector.data)
|
||||
.then(function(signature) {
|
||||
assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name + ": " + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " using publicKey to sign");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " using publicKey to sign");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for failures due to no "verify" usage.
|
||||
testVectors.forEach(function(originalVector) {
|
||||
var vector = Object.assign({}, originalVector);
|
||||
|
||||
var promise = importVectorKeys(vector, [], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
return subtle.verify(algorithm, vector.publicKey, vector.signature, vector.data)
|
||||
.then(function(data) {
|
||||
assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": " + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " no verify usage");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " no verify usage");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful signing and verification.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
return subtle.sign(algorithm, vector.privateKey, vector.data)
|
||||
.then(function(signature) {
|
||||
assert_true(equalBuffers(signature, vector.signature), "Signing did not give the expected output");
|
||||
// Can we verify the signature?
|
||||
return subtle.verify(algorithm, vector.publicKey, signature, vector.data)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Round trip verification works");
|
||||
return signature;
|
||||
}, function(err) {
|
||||
assert_unreached("verify error for test " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
}, function(err) {
|
||||
assert_unreached("sign error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " round trip");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested signing or verifying
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " round trip");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test signing with the wrong algorithm
|
||||
testVectors.forEach(function(vector) {
|
||||
// Want to get the key for the wrong algorithm
|
||||
var promise = subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
.then(function(wrongKey) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
return importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.sign(algorithm, wrongKey, vector.data)
|
||||
.then(function(signature) {
|
||||
assert_unreached("Signing should not have succeeded for " + vector.name);
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " signing with wrong algorithm name");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " signing with wrong algorithm name");
|
||||
});
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
}, "generate wrong key step: " + vector.name + " signing with wrong algorithm name");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with the wrong algorithm
|
||||
testVectors.forEach(function(vector) {
|
||||
// Want to get the key for the wrong algorithm
|
||||
var promise = subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
.then(function(wrongKey) {
|
||||
return importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.verify(algorithm, wrongKey, vector.signature, vector.data)
|
||||
.then(function(signature) {
|
||||
assert_unreached("Verifying should not have succeeded for " + vector.name);
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verifying with wrong algorithm name");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verifying with wrong algorithm name");
|
||||
});
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
}, "generate wrong key step: " + vector.name + " verifying with wrong algorithm name");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification fails with wrong signature
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
var signature = copyBuffer(vector.signature);
|
||||
signature[0] = 255 - signature[0];
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, signature, vector.data)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to altered signature");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to altered signature");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification fails with short (odd length) signature
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
var signature = vector.signature.slice(1); // Skip the first byte
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, signature, vector.data)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to shortened signature");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to shortened signature");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification fails with wrong data
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify"], ["sign"])
|
||||
.then(function(vectors) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
var data = copyBuffer(vector.data);
|
||||
data[0] = 255 - data[0];
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.verify(algorithm, vector.publicKey, vector.signature, data)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to altered data");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to altered data");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
|
||||
promise_test(function() {
|
||||
return Promise.all(all_promises)
|
||||
.then(function() {done();})
|
||||
.catch(function() {done();})
|
||||
}, "setup");
|
||||
|
||||
// Test that generated keys are valid for signing and verifying.
|
||||
testVectors.forEach(function(vector) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
|
||||
// Test verification first, because signing tests rely on that working
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " verification");
|
||||
|
||||
// Test verification with an altered buffer after call
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
var signature = copyBuffer(vector.signature);
|
||||
[isVerified] = await Promise.all([
|
||||
subtle.verify(algorithm, key, signature, vector.data),
|
||||
signature[0] = 255 - signature[0]
|
||||
]);
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " verification with altered signature after call");
|
||||
|
||||
// Check for successful verification even if data is altered after call.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
var data = copyBuffer(vector.data);
|
||||
[isVerified] = await Promise.all([
|
||||
subtle.verify(algorithm, key, vector.signature, data),
|
||||
data[0] = 255 - data[0]
|
||||
]);
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " with altered data after call");
|
||||
|
||||
// Check for failures due to using privateKey to verify.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("pkcs8", vector.privateKeyBuffer, algorithm, false, ["sign"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " using privateKey to verify");
|
||||
|
||||
// Check for failures due to using publicKey to sign.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
let signature = await subtle.sign(algorithm, key, vector.data);
|
||||
assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " using publicKey to sign");
|
||||
|
||||
// Check for failures due to no "verify" usage.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, []);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
assert_unreached("Should have thrown error for no verify usage in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " no verify usage");
|
||||
|
||||
// Check for successful signing and verification.
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let privateKey, publicKey;
|
||||
let signature;
|
||||
try {
|
||||
privateKey = await subtle.importKey("pkcs8", vector.privateKeyBuffer, algorithm, false, ["sign"]);
|
||||
publicKey = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
signature = await subtle.sign(algorithm, privateKey, vector.data);
|
||||
isVerified = await subtle.verify(algorithm, publicKey, vector.signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(publicKey === undefined || privateKey === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_false(signature === undefined, "sign error for test " + vector.name + ": '" + err.message + "'");
|
||||
assert_unreached("verify error for test " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Round trip verification works");
|
||||
}, vector.name + " round trip");
|
||||
|
||||
// Test signing with the wrong algorithm
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let wrongKey;
|
||||
try {
|
||||
wrongKey = await subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
let signature = await subtle.sign(algorithm, wrongKey, vector.data);
|
||||
assert_unreached("Signing should not have succeeded for " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(wrongKey === undefined, "Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " signing with wrong algorithm name");
|
||||
|
||||
// Test verification with the wrong algorithm
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let wrongKey;
|
||||
try {
|
||||
wrongKey = await subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
let isVerified = await subtle.verify(algorithm, wrongKey, vector.signature, vector.data)
|
||||
assert_unreached("Verifying should not have succeeded for " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(wrongKey === undefined, "Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " verifying with wrong algorithm name");
|
||||
|
||||
// Test verification fails with wrong signature
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var signature = copyBuffer(vector.signature);
|
||||
signature[0] = 255 - signature[0];
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to altered signature");
|
||||
|
||||
// Test verification fails with short (odd length) signature
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var signature = vector.signature.slice(1); // Skip the first byte
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to shortened signature");
|
||||
|
||||
// Test verification fails with wrong data
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var data = copyBuffer(vector.data);
|
||||
data[0] = 255 - data[0];
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to altered data");
|
||||
|
||||
// Test that generated keys are valid for signing and verifying.
|
||||
promise_test(async() => {
|
||||
let key = await subtle.generateKey(algorithm, false, ["sign", "verify"]);
|
||||
let signature = await subtle.sign(algorithm, key.privateKey, vector.data);
|
||||
|
@ -366,42 +217,6 @@ function run_test() {
|
|||
}, "Sign and verify using generated " + vector.algorithmName + " keys.");
|
||||
});
|
||||
|
||||
|
||||
// A test vector has all needed fields for signing and verifying, EXCEPT that the
|
||||
// key field may be null. This function replaces that null with the Correct
|
||||
// CryptoKey object.
|
||||
//
|
||||
// Returns a Promise that yields an updated vector on success.
|
||||
function importVectorKeys(vector, publicKeyUsages, privateKeyUsages) {
|
||||
var publicPromise, privatePromise;
|
||||
|
||||
if (vector.publicKey !== null) {
|
||||
publicPromise = new Promise(function(resolve, reject) {
|
||||
resolve(vector);
|
||||
});
|
||||
} else {
|
||||
publicPromise = subtle.importKey(vector.publicKeyFormat, vector.publicKeyBuffer, {name: vector.algorithmName}, false, publicKeyUsages)
|
||||
.then(function(key) {
|
||||
vector.publicKey = key;
|
||||
return vector;
|
||||
}); // Returns a copy of the sourceBuffer it is sent.
|
||||
}
|
||||
|
||||
if (vector.privateKey !== null) {
|
||||
privatePromise = new Promise(function(resolve, reject) {
|
||||
resolve(vector);
|
||||
});
|
||||
} else {
|
||||
privatePromise = subtle.importKey(vector.privateKeyFormat, vector.privateKeyBuffer, {name: vector.algorithmName}, false, privateKeyUsages)
|
||||
.then(function(key) {
|
||||
vector.privateKey = key;
|
||||
return vector;
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all([publicPromise, privatePromise]);
|
||||
}
|
||||
|
||||
// Returns a copy of the sourceBuffer it is sent.
|
||||
function copyBuffer(sourceBuffer) {
|
||||
var source = new Uint8Array(sourceBuffer);
|
||||
|
@ -414,22 +229,5 @@ function run_test() {
|
|||
return copy;
|
||||
}
|
||||
|
||||
function equalBuffers(a, b) {
|
||||
if (a.byteLength !== b.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var aBytes = new Uint8Array(a);
|
||||
var bBytes = new Uint8Array(b);
|
||||
|
||||
for (var i=0; i<a.byteLength; i++) {
|
||||
if (aBytes[i] !== bBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
6
test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js
vendored
Normal file
6
test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// META: title=WebCryptoAPI: verify() Using EdDSA with small-order points
|
||||
// META: script=eddsa_vectors.js
|
||||
// META: script=eddsa_small_order_points.js
|
||||
// META: timeout=long
|
||||
|
||||
run_test();
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
function run_test() {
|
||||
var subtle = self.crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
// When verifying an Ed25519 or Ed448 signature, if the public key or the first half of the signature (R) is
|
||||
// an invalid or small-order element, return false.
|
||||
Object.keys(kSmallOrderTestCases).forEach(function (algorithmName) {
|
||||
var algorithm = {name: algorithmName};
|
||||
kSmallOrderTestCases[algorithmName].forEach(function(test) {
|
||||
promise_test(async() => {
|
||||
let isVerified = true;
|
||||
let publicKey;
|
||||
try {
|
||||
publicKey = await subtle.importKey("raw", test.keyData, algorithm, false, ["verify"])
|
||||
isVerified = await subtle.verify(algorithm, publicKey, test.signature, test.message);
|
||||
} catch (err) {
|
||||
assert_true(publicKey !== undefined, "Public key should be valid.");
|
||||
assert_unreached("The operation shouldn't fail, but it thown this error: " + err.name + ": " + err.message + ".");
|
||||
}
|
||||
assert_equals(isVerified, test.verified, "Signature verification result.");
|
||||
}, algorithmName + " Verification checks with small-order key of order - Test " + test.id);
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
|
@ -53,6 +53,145 @@ function getTestVectors() {
|
|||
|
||||
vectors.push(vector);
|
||||
});
|
||||
|
||||
return vectors;
|
||||
}
|
||||
|
||||
// https://eprint.iacr.org/2020/1244.pdf#table.caption.3
|
||||
var kSmallOrderPoints = [
|
||||
// Canonical serializations
|
||||
[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // #0 - Order 1
|
||||
[0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], // #1 - Order 2
|
||||
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80], // #2 - Order 4
|
||||
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // #3 - Order 4
|
||||
[0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F, 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F, 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6, 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0x7A], // #4 - Order 8
|
||||
[0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F, 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F, 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6, 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0xFA], // #5 - Order 8
|
||||
[0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0, 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0, 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39, 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x05], // #6 - Order 8
|
||||
[0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0, 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0, 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39, 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x85], // #7 - Order 8
|
||||
|
||||
// Non-canonical serializatons
|
||||
[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80], // #8 - Order 1
|
||||
[0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], // #9 - Order 2
|
||||
[0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], // #10 - Order 1
|
||||
[0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], // #11 - Order 1
|
||||
[0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], // #12 - Order 4
|
||||
[0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], // #13 - Order 4
|
||||
];
|
||||
|
||||
|
||||
var pubKeys = [
|
||||
[0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa], // kSmallOrderPoints #5
|
||||
[0xf7, 0xba, 0xde, 0xc5, 0xb8, 0xab, 0xea, 0xf6, 0x99, 0x58, 0x39, 0x92, 0x21, 0x9b, 0x7b, 0x22, 0x3f, 0x1d, 0xf3, 0xfb, 0xbe, 0xa9, 0x19, 0x84, 0x4e, 0x3f, 0x7c, 0x55, 0x4a, 0x43, 0xdd, 0x43], // highest 32 bytes of case "1" signature
|
||||
[0xcd, 0xb2, 0x67, 0xce, 0x40, 0xc5, 0xcd, 0x45, 0x30, 0x6f, 0xa5, 0xd2, 0xf2, 0x97, 0x31, 0x45, 0x93, 0x87, 0xdb, 0xf9, 0xeb, 0x93, 0x3b, 0x7b, 0xd5, 0xae, 0xd9, 0xa7, 0x65, 0xb8, 0x8d, 0x4d],
|
||||
[0x44, 0x2a, 0xad, 0x9f, 0x08, 0x9a, 0xd9, 0xe1, 0x46, 0x47, 0xb1, 0xef, 0x90, 0x99, 0xa1, 0xff, 0x47, 0x98, 0xd7, 0x85, 0x89, 0xe6, 0x6f, 0x28, 0xec, 0xa6, 0x9c, 0x11, 0xf5, 0x82, 0xa6, 0x23],
|
||||
[0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], // kSmallOrderPoints #9
|
||||
[0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], // kSmallOrderPoints #1
|
||||
]
|
||||
|
||||
// https://eprint.iacr.org/2020/1244.pdf
|
||||
// signature = (R, S); public key A, h = SHA512(R||A||M )
|
||||
// 8(SB) = 8R + 8(hA) => (1)
|
||||
// SB = R + hA => (2)
|
||||
var kSmallOrderTestCases = {
|
||||
"Ed25519": [
|
||||
{
|
||||
id: "0", // S = 0 | A's order = small | R's order = small | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x8c, 0x93, 0x25, 0x5d, 0x71, 0xdc, 0xab, 0x10, 0xe8, 0xf3, 0x79, 0xc2, 0x62, 0x00, 0xf3, 0xc7, 0xbd, 0x5f, 0x09, 0xd9, 0xbc, 0x30, 0x68, 0xd3, 0xef, 0x4e, 0xde, 0xb4, 0x85, 0x30, 0x22, 0xb6]),
|
||||
keyData : Uint8Array.from(pubKeys[0]),
|
||||
signature : Uint8Array.from([0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
verified: false, // small-order signature's R fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "1", // 0 < S < L | A's order = small | R's order = mixed | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x9b, 0xd9, 0xf4, 0x4f, 0x4d, 0xcc, 0x75, 0xbd, 0x53, 0x1b, 0x56, 0xb2, 0xcd, 0x28, 0x0b, 0x0b, 0xb3, 0x8f, 0xc1, 0xcd, 0x6d, 0x12, 0x30, 0xe1, 0x48, 0x61, 0xd8, 0x61, 0xde, 0x09, 0x2e, 0x79]),
|
||||
keyData : Uint8Array.from(pubKeys[0]),
|
||||
signature : Uint8Array.from([0xf7, 0xba, 0xde, 0xc5, 0xb8, 0xab, 0xea, 0xf6, 0x99, 0x58, 0x39, 0x92, 0x21, 0x9b, 0x7b, 0x22, 0x3f, 0x1d, 0xf3, 0xfb, 0xbe, 0xa9, 0x19, 0x84, 0x4e, 0x3f, 0x7c, 0x55, 0x4a, 0x43, 0xdd, 0x43, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // small-order key's data fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "2", // 0 < S < L | A's order = mixed | R's order = small | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0xae, 0xbf, 0x3f, 0x26, 0x01, 0xa0, 0xc8, 0xc5, 0xd3, 0x9c, 0xc7, 0xd8, 0x91, 0x16, 0x42, 0xf7, 0x40, 0xb7, 0x81, 0x68, 0x21, 0x8d, 0xa8, 0x47, 0x17, 0x72, 0xb3, 0x5f, 0x9d, 0x35, 0xb9, 0xab]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa, 0x8c, 0x4b, 0xd4, 0x5a, 0xec, 0xac, 0xa5, 0xb2, 0x4f, 0xb9, 0x7b, 0xc1, 0x0a, 0xc2, 0x7a, 0xc8, 0x75, 0x1a, 0x7d, 0xfe, 0x1b, 0xaf, 0xf8, 0xb9, 0x53, 0xec, 0x9f, 0x58, 0x33, 0xca, 0x26, 0x0e]),
|
||||
verified: false, // small-order signature's R fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "3", // 0 < S < L | A's order = mixed | R's order = mixed | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x9b, 0xd9, 0xf4, 0x4f, 0x4d, 0xcc, 0x75, 0xbd, 0x53, 0x1b, 0x56, 0xb2, 0xcd, 0x28, 0x0b, 0x0b, 0xb3, 0x8f, 0xc1, 0xcd, 0x6d, 0x12, 0x30, 0xe1, 0x48, 0x61, 0xd8, 0x61, 0xde, 0x09, 0x2e, 0x79]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x90, 0x46, 0xa6, 0x47, 0x50, 0x44, 0x49, 0x38, 0xde, 0x19, 0xf2, 0x27, 0xbb, 0x80, 0x48, 0x5e, 0x92, 0xb8, 0x3f, 0xdb, 0x4b, 0x65, 0x06, 0xc1, 0x60, 0x48, 0x4c, 0x01, 0x6c, 0xc1, 0x85, 0x2f, 0x87, 0x90, 0x9e, 0x14, 0x42, 0x8a, 0x7a, 0x1d, 0x62, 0xe9, 0xf2, 0x2f, 0x3d, 0x3a, 0xd7, 0x80, 0x2d, 0xb0, 0x2e, 0xb2, 0xe6, 0x88, 0xb6, 0xc5, 0x2f, 0xcd, 0x66, 0x48, 0xa9, 0x8b, 0xd0, 0x09]),
|
||||
verified: true, // mixed-order points are not checked.
|
||||
},
|
||||
{
|
||||
id: "4", // 0 < S < L | A's order = mixed | R's order = mixed | (1) = pass | (2) = fail
|
||||
message : Uint8Array.from([0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40, 0x11, 0xea, 0xcc, 0xd5, 0x5b, 0x53, 0xf5, 0x6c]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x16, 0x0a, 0x1c, 0xb0, 0xdc, 0x9c, 0x02, 0x58, 0xcd, 0x0a, 0x7d, 0x23, 0xe9, 0x4d, 0x8f, 0xa8, 0x78, 0xbc, 0xb1, 0x92, 0x5f, 0x2c, 0x64, 0x24, 0x6b, 0x2d, 0xee, 0x17, 0x96, 0xbe, 0xd5, 0x12, 0x5e, 0xc6, 0xbc, 0x98, 0x2a, 0x26, 0x9b, 0x72, 0x3e, 0x06, 0x68, 0xe5, 0x40, 0x91, 0x1a, 0x9a, 0x6a, 0x58, 0x92, 0x1d, 0x69, 0x25, 0xe4, 0x34, 0xab, 0x10, 0xaa, 0x79, 0x40, 0x55, 0x1a, 0x09]),
|
||||
verified: false, // expect a cofactorless verification algorithm.
|
||||
},
|
||||
{
|
||||
id: "5", // 0 < S < L | A's order = mixed | R's order = L | (1) = pass | (2) = fail
|
||||
message : Uint8Array.from([0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40, 0x11, 0xea, 0xcc, 0xd5, 0x5b, 0x53, 0xf5, 0x6c]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x21, 0x12, 0x2a, 0x84, 0xe0, 0xb5, 0xfc, 0xa4, 0x05, 0x2f, 0x5b, 0x12, 0x35, 0xc8, 0x0a, 0x53, 0x78, 0x78, 0xb3, 0x8f, 0x31, 0x42, 0x35, 0x6b, 0x2c, 0x23, 0x84, 0xeb, 0xad, 0x46, 0x68, 0xb7, 0xe4, 0x0b, 0xc8, 0x36, 0xda, 0xc0, 0xf7, 0x10, 0x76, 0xf9, 0xab, 0xe3, 0xa5, 0x3f, 0x9c, 0x03, 0xc1, 0xce, 0xee, 0xdd, 0xb6, 0x58, 0xd0, 0x03, 0x04, 0x94, 0xac, 0xe5, 0x86, 0x68, 0x74, 0x05]),
|
||||
verified: false, // expect a cofactorless verification algorithm.
|
||||
},
|
||||
{
|
||||
id: "6", // S > L | A's order = L | R's order = L | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41, 0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40]),
|
||||
keyData : Uint8Array.from(pubKeys[3]),
|
||||
signature : Uint8Array.from([0xe9, 0x6f, 0x66, 0xbe, 0x97, 0x6d, 0x82, 0xe6, 0x01, 0x50, 0xba, 0xec, 0xff, 0x99, 0x06, 0x68, 0x4a, 0xeb, 0xb1, 0xef, 0x18, 0x1f, 0x67, 0xa7, 0x18, 0x9a, 0xc7, 0x8e, 0xa2, 0x3b, 0x6c, 0x0e, 0x54, 0x7f, 0x76, 0x90, 0xa0, 0xe2, 0xdd, 0xcd, 0x04, 0xd8, 0x7d, 0xbc, 0x34, 0x90, 0xdc, 0x19, 0xb3, 0xb3, 0x05, 0x2f, 0x7f, 0xf0, 0x53, 0x8c, 0xb6, 0x8a, 0xfb, 0x36, 0x9b, 0xa3, 0xa5, 0x14]),
|
||||
verified: false, // S out of bounds
|
||||
},
|
||||
{
|
||||
id: "7", // S >> L | A's order = L | R's order = L | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41, 0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40]),
|
||||
keyData : Uint8Array.from(pubKeys[3]),
|
||||
signature : Uint8Array.from([0x8c, 0xe5, 0xb9, 0x6c, 0x8f, 0x26, 0xd0, 0xab, 0x6c, 0x47, 0x95, 0x8c, 0x9e, 0x68, 0xb9, 0x37, 0x10, 0x4c, 0xd3, 0x6e, 0x13, 0xc3, 0x35, 0x66, 0xac, 0xd2, 0xfe, 0x8d, 0x38, 0xaa, 0x19, 0x42, 0x7e, 0x71, 0xf9, 0x8a, 0x47, 0x34, 0xe7, 0x4f, 0x2f, 0x13, 0xf0, 0x6f, 0x97, 0xc2, 0x0d, 0x58, 0xcc, 0x3f, 0x54, 0xb8, 0xbd, 0x0d, 0x27, 0x2f, 0x42, 0xb6, 0x95, 0xdd, 0x7e, 0x89, 0xa8, 0xc2, 0x02]),
|
||||
verified: false, // S out of bounds
|
||||
},
|
||||
{
|
||||
id: "8", // 0 < S < L | A's order = mixed | R's order = small (non-canonical) | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #8 and accept #9, and viceversa
|
||||
message : Uint8Array.from([0x9b, 0xed, 0xc2, 0x67, 0x42, 0x37, 0x25, 0xd4, 0x73, 0x88, 0x86, 0x31, 0xeb, 0xf4, 0x59, 0x88, 0xba, 0xd3, 0xdb, 0x83, 0x85, 0x1e, 0xe8, 0x5c, 0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xbe, 0x96, 0x78, 0xac, 0x10, 0x2e, 0xdc, 0xd9, 0x2b, 0x02, 0x10, 0xbb, 0x34, 0xd7, 0x42, 0x8d, 0x12, 0xff, 0xc5, 0xdf, 0x5f, 0x37, 0xe3, 0x59, 0x94, 0x12, 0x66, 0xa4, 0xe3, 0x5f, 0x0f]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "9", // 0 < S < L | A's order = mixed | R's order = small (non-canonical) | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x9b, 0xed, 0xc2, 0x67, 0x42, 0x37, 0x25, 0xd4, 0x73, 0x88, 0x86, 0x31, 0xeb, 0xf4, 0x59, 0x88, 0xba, 0xd3, 0xdb, 0x83, 0x85, 0x1e, 0xe8, 0x5c, 0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0x8c, 0x5b, 0x64, 0xcd, 0x20, 0x89, 0x82, 0xaa, 0x38, 0xd4, 0x93, 0x66, 0x21, 0xa4, 0x77, 0x5a, 0xa2, 0x33, 0xaa, 0x05, 0x05, 0x71, 0x1d, 0x8f, 0xdc, 0xfd, 0xaa, 0x94, 0x3d, 0x49, 0x08]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "10", // 0 < S < L | A's order = small (non-canonical) | R's order = mixed | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #10 and accept #11, and viceversa
|
||||
message : Uint8Array.from([0xe9, 0x6b, 0x70, 0x21, 0xeb, 0x39, 0xc1, 0xa1, 0x63, 0xb6, 0xda, 0x4e, 0x30, 0x93, 0xdc, 0xd3, 0xf2, 0x13, 0x87, 0xda, 0x4c, 0xc4, 0x57, 0x2b, 0xe5, 0x88, 0xfa, 0xfa, 0xe2, 0x3c, 0x15, 0x5b]),
|
||||
keyData : Uint8Array.from(pubKeys[4]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "11", // 0 < S < L | A's order = small (non-canonical) | R's order = mixed | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #10 and accept #11, and viceversa
|
||||
message : Uint8Array.from([0x39, 0xa5, 0x91, 0xf5, 0x32, 0x1b, 0xbe, 0x07, 0xfd, 0x5a, 0x23, 0xdc, 0x2f, 0x39, 0xd0, 0x25, 0xd7, 0x45, 0x26, 0x61, 0x57, 0x46, 0x72, 0x7c, 0xee, 0xfd, 0x6e, 0x82, 0xae, 0x65, 0xc0, 0x6f]),
|
||||
keyData : Uint8Array.from(pubKeys[4]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
// https://eprint.iacr.org/2020/1244.pdf#section.A.2
|
||||
// cases breaking non-repudiation
|
||||
{
|
||||
id: "12", // 0 < S < L | A's order = small | R's order = mixed | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x53, 0x65, 0x6e, 0x64, 0x20, 0x31, 0x30, 0x30, 0x20, 0x55, 0x53, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x63, 0x65]),
|
||||
keyData : Uint8Array.from(pubKeys[5]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false,
|
||||
},
|
||||
{
|
||||
id: "13", // 0 < S < L | A's order = small | R's order = mixed | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x53, 0x65, 0x6e, 0x64, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x55, 0x53, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x63, 0x65]),
|
||||
keyData : Uint8Array.from(pubKeys[5]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
"path": "wasm/webapi"
|
||||
},
|
||||
"WebCryptoAPI": {
|
||||
"commit": "5e042cbc4ecab7b2279a5fd411c6daa24ca886c6",
|
||||
"commit": "6748a0a24614b01ce6527493a19ef846738bee3a",
|
||||
"path": "WebCryptoAPI"
|
||||
},
|
||||
"webidl/ecmascript-binding/es-exceptions": {
|
||||
|
|
|
@ -27,7 +27,7 @@ it's not yet clear how compliant the implementation is,
|
|||
the requirements and expected failures can be figured out in a later step
|
||||
when the tests are run for the first time.
|
||||
|
||||
See [Format of a status JSON file](#status-format) for details.
|
||||
See [Format of a status file](#status-format) for details.
|
||||
|
||||
### 2. Pull the WPT files
|
||||
|
||||
|
@ -98,7 +98,7 @@ add this to `test/wpt/status/url.json`:
|
|||
}
|
||||
```
|
||||
|
||||
See [Format of a status JSON file](#status-format) for details.
|
||||
See [Format of a status file](#status-format) for details.
|
||||
|
||||
### 5. Commit the changes and submit a Pull Request
|
||||
|
||||
|
@ -147,7 +147,7 @@ expected failures.
|
|||
|
||||
<a id="status-format"></a>
|
||||
|
||||
## Format of a status JSON file
|
||||
## Format of a status file
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -177,6 +177,10 @@ A test may have to be skipped because it depends on another irrelevant
|
|||
Web API, or certain harness has not been ported in our test runner yet.
|
||||
In that case it needs to be marked with `skip` instead of `fail`.
|
||||
|
||||
The status file may optionally also be a CJS module that exports the object.
|
||||
This allows for more complex logic to be used to determine the expected status
|
||||
of a test.
|
||||
|
||||
[Web Platform Tests]: https://github.com/web-platform-tests/wpt
|
||||
[`test/fixtures/wpt/README.md`]: ../fixtures/wpt/README.md
|
||||
[git node wpt]: https://github.com/nodejs/node-core-utils/blob/HEAD/docs/git-node.md#git-node-wpt
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
const os = require('node:os');
|
||||
|
||||
const s390x = os.arch() === 's390x';
|
||||
|
||||
module.exports = {
|
||||
'algorithm-discards-context.https.window.js': {
|
||||
'skip': 'Not relevant in Node.js context',
|
||||
},
|
||||
'historical.any.js': {
|
||||
'skip': 'Not relevant in Node.js context',
|
||||
},
|
||||
'getRandomValues.any.js': {
|
||||
'fail': {
|
||||
'note': 'Node.js does not support Float16Array',
|
||||
'expected': [
|
||||
'Float16 arrays',
|
||||
],
|
||||
},
|
||||
},
|
||||
'sign_verify/eddsa_small_order_points.https.any.js': {
|
||||
'fail': {
|
||||
'note': 'see https://github.com/nodejs/node/issues/54572',
|
||||
'expected': [
|
||||
'Ed25519 Verification checks with small-order key of order - Test 1',
|
||||
'Ed25519 Verification checks with small-order key of order - Test 2',
|
||||
'Ed25519 Verification checks with small-order key of order - Test 12',
|
||||
'Ed25519 Verification checks with small-order key of order - Test 13',
|
||||
...(s390x ? [] : [
|
||||
'Ed25519 Verification checks with small-order key of order - Test 0',
|
||||
'Ed25519 Verification checks with small-order key of order - Test 11',
|
||||
]),
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"algorithm-discards-context.https.window.js": {
|
||||
"skip": "Not relevant in Node.js context"
|
||||
},
|
||||
"historical.any.js": {
|
||||
"skip": "Not relevant in Node.js context"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue