Tests: Import WPT importKey tests for Ed25519 and X25519

This commit is contained in:
Andreas Kling 2024-11-24 20:06:21 +01:00 committed by Andreas Kling
commit e0def9d745
Notes: github-actions[bot] 2024-11-24 22:29:55 +00:00
14 changed files with 1341 additions and 0 deletions

View file

@ -0,0 +1,210 @@
function run_test(algorithmNames) {
var subtle = crypto.subtle; // Change to test prefixed implementations
setup({explicit_timeout: true});
// These tests check that importKey and exportKey throw an error, and that
// the error is of the right type, for a wide set of incorrect parameters.
// Error testing occurs by setting the parameter that should trigger the
// error to an invalid value, then combining that with all valid
// parameters that should be checked earlier by importKey, and all
// valid and invalid parameters that should be checked later by
// importKey.
//
// There are a lot of combinations of possible parameters for both
// success and failure modes, resulting in a very large number of tests
// performed.
var allTestVectors = [ // Parameters that should work for importKey / exportKey
{name: "Ed25519", privateUsages: ["sign"], publicUsages: ["verify"]},
{name: "Ed448", privateUsages: ["sign"], publicUsages: ["verify"]},
{name: "ECDSA", privateUsages: ["sign"], publicUsages: ["verify"]},
{name: "X25519", privateUsages: ["deriveKey", "deriveBits"], publicUsages: []},
{name: "X448", privateUsages: ["deriveKey", "deriveBits"], publicUsages: []},
{name: "ECDH", privateUsages: ["deriveKey", "deriveBits"], publicUsages: []}
];
var testVectors = [];
if (algorithmNames && !Array.isArray(algorithmNames)) {
algorithmNames = [algorithmNames];
};
allTestVectors.forEach(function(vector) {
if (!algorithmNames || algorithmNames.includes(vector.name)) {
testVectors.push(vector);
}
});
function parameterString(format, algorithm, extractable, usages, data) {
if (typeof algorithm !== "object" && typeof algorithm !== "string") {
alert(algorithm);
}
var jwk_label = "";
if (format === "jwk")
jwk_label = data.d === undefined ? " (public) " : "(private)";
var result = "(" +
objectToString(format) + jwk_label + ", " +
objectToString(algorithm) + ", " +
objectToString(extractable) + ", " +
objectToString(usages) +
")";
return result;
}
// Test that a given combination of parameters results in an error,
// AND that it is the correct kind of error.
//
// Expected error is either a number, tested against the error code,
// or a string, tested against the error name.
function testError(format, algorithm, keyData, keySize, usages, extractable, expectedError, testTag) {
promise_test(async() => {
let key;
try {
key = await subtle.importKey(format, keyData, algorithm, extractable, usages);
} catch(err) {
let actualError = typeof expectedError === "number" ? err.code : err.name;
assert_equals(actualError, expectedError, testTag + " not supported.");
}
assert_equals(key, undefined, "Operation succeeded, but should not have.");
}, testTag + ": importKey" + parameterString(format, algorithm, extractable, usages, keyData));
}
// Don't create an exhaustive list of all invalid usages,
// because there would usually be nearly 2**8 of them,
// way too many to test. Instead, create every singleton
// of an illegal usage, and "poison" every valid usage
// with an illegal one.
function invalidUsages(validUsages, mandatoryUsages) {
var results = [];
var illegalUsages = [];
["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey", "deriveKey", "deriveBits"].forEach(function(usage) {
if (!validUsages.includes(usage)) {
illegalUsages.push(usage);
}
});
var goodUsageCombinations = validUsages.length === 0 ? [] : allValidUsages(validUsages, false, mandatoryUsages);
illegalUsages.forEach(function(illegalUsage) {
results.push([illegalUsage]);
goodUsageCombinations.forEach(function(usageCombination) {
results.push(usageCombination.concat([illegalUsage]));
});
});
return results;
}
function validUsages(usages, format, data) {
if (format === 'spki' || format === 'raw') return usages.publicUsages
if (format === 'pkcs8') return usages.privateUsages
if (format === 'jwk') {
if (data === undefined)
return [];
return data.d === undefined ? usages.publicUsages : usages.privateUsages;
}
return [];
}
function isPrivateKey(data) {
return data.d !== undefined;
}
// Now test for properly handling errors
// - Unsupported algorithm
// - Bad usages for algorithm
// - Bad key lengths
// - Lack of a mandatory format field
// - Incompatible keys pair
// Algorithms normalize okay, but usages bad (though not empty).
// It shouldn't matter what other extractable is. Should fail
// due to SyntaxError
testVectors.forEach(function(vector) {
var name = vector.name;
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
getValidKeyData(algorithm).forEach(function(test) {
invalidUsages(validUsages(vector, test.format, test.data)).forEach(function(usages) {
[true, false].forEach(function(extractable) {
testError(test.format, algorithm, test.data, name, usages, extractable, "SyntaxError", "Bad usages");
});
});
});
});
});
// Algorithms normalize okay, but usages bad (empty).
// Should fail due to SyntaxError
testVectors.forEach(function(vector) {
var name = vector.name;
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
getValidKeyData(algorithm).filter((test) => test.format === 'pkcs8' || (test.format === 'jwk' && isPrivateKey(test.data))).forEach(function(test) {
[true, false].forEach(function(extractable) {
testError(test.format, algorithm, test.data, name, [/* Empty usages */], extractable, "SyntaxError", "Empty usages");
});
});
});
});
// Algorithms normalize okay, usages ok. The length of the key must throw a DataError exception.
testVectors.forEach(function(vector) {
var name = vector.name;
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
getBadKeyLengthData(algorithm).forEach(function(test) {
allValidUsages(validUsages(vector, test.format, test.data)).forEach(function(usages) {
[true, false].forEach(function(extractable) {
testError(test.format, algorithm, test.data, name, usages, extractable, "DataError", "Bad key length");
});
});
});
});
});
// Algorithms normalize okay, usages ok and valid key. The lack of the mandatory JWK parameter must throw a DataError exception.
testVectors.forEach(function(vector) {
var name = vector.name;
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
getMissingJWKFieldKeyData(algorithm).forEach(function(test) {
allValidUsages(validUsages(vector, 'jwk', test.data)).forEach(function(usages) {
[true, false].forEach(function(extractable) {
testError('jwk', algorithm, test.data, name, usages, extractable, "DataError", "Missing JWK '" + test.param + "' parameter");
});
});
});
});
});
// Algorithms normalize okay, usages ok and valid key. The public key is not compatible with the private key.
testVectors.forEach(function(vector) {
var name = vector.name;
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
getMismatchedJWKKeyData(algorithm).forEach(function(data) {
allValidUsages(vector.privateUsages).forEach(function(usages) {
[true].forEach(function(extractable) {
testError('jwk', algorithm, data, name, usages, extractable, "DataError", "Invalid key pair");
});
});
});
});
});
// Missing mandatory "name" field on algorithm
testVectors.forEach(function(vector) {
var name = vector.name;
// We just need *some* valid keydata, so pick the first available algorithm.
var algorithm = allAlgorithmSpecifiersFor(name)[0];
getValidKeyData(algorithm).forEach(function(test) {
validUsages(vector, test.format, test.data).forEach(function(usages) {
[true, false].forEach(function(extractable) {
testError(test.format, {}, test.data, name, usages, extractable, "TypeError", "Missing algorithm name");
});
});
});
});
}

View file

@ -0,0 +1,213 @@
var subtle = crypto.subtle;
function runTests(algorithmName) {
var algorithm = {name: algorithmName};
var data = keyData[algorithmName];
var jwkData = {jwk: {kty: data.jwk.kty, crv: data.jwk.crv, x: data.jwk.x}};
[true, false].forEach(function(extractable) {
// Test public keys first
allValidUsages(data.publicUsages, true).forEach(function(usages) {
['spki', 'jwk', 'raw'].forEach(function(format) {
if (format === "jwk") { // Not all fields used for public keys
testFormat(format, algorithm, jwkData, algorithmName, usages, extractable);
// Test for https://github.com/WICG/webcrypto-secure-curves/pull/24
if (extractable) {
testJwkAlgBehaviours(algorithm, jwkData.jwk, algorithmName, usages);
}
} else {
testFormat(format, algorithm, data, algorithmName, usages, extractable);
}
});
});
// Next, test private keys
allValidUsages(data.privateUsages).forEach(function(usages) {
['pkcs8', 'jwk'].forEach(function(format) {
testFormat(format, algorithm, data, algorithmName, usages, extractable);
// Test for https://github.com/WICG/webcrypto-secure-curves/pull/24
if (format === "jwk" && extractable) {
testJwkAlgBehaviours(algorithm, data.jwk, algorithmName, usages);
}
});
});
});
}
// Test importKey with a given key format and other parameters. If
// extrable is true, export the key and verify that it matches the input.
function testFormat(format, algorithm, keyData, keySize, usages, extractable) {
[algorithm, algorithm.name].forEach((alg) => {
promise_test(function(test) {
return subtle.importKey(format, keyData[format], alg, extractable, usages).
then(function(key) {
assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object");
assert_goodCryptoKey(key, algorithm, extractable, usages, (format === 'pkcs8' || (format === 'jwk' && keyData[format].d)) ? 'private' : 'public');
if (!extractable) {
return;
}
return subtle.exportKey(format, key).
then(function(result) {
if (format !== "jwk") {
assert_true(equalBuffers(keyData[format], result), "Round trip works");
} else {
assert_true(equalJwk(keyData[format], result), "Round trip works");
}
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
}, "Good parameters: " + keySize.toString() + " bits " + parameterString(format, keyData[format], alg, extractable, usages));
});
}
// Test importKey/exportKey "alg" behaviours, alg is ignored upon import and alg is missing for Ed25519 and Ed448 JWK export
// https://github.com/WICG/webcrypto-secure-curves/pull/24
function testJwkAlgBehaviours(algorithm, keyData, crv, usages) {
[algorithm, algorithm.name].forEach((alg) => {
promise_test(function(test) {
return subtle.importKey('jwk', { ...keyData, alg: 'this is ignored' }, alg, true, usages).
then(function(key) {
assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object");
return subtle.exportKey('jwk', key).
then(function(result) {
assert_equals(Object.keys(result).length, keyData.d ? 6 : 5, "Correct number of JWK members");
assert_equals(result.alg, undefined, 'No JWK "alg" member is present');
assert_true(equalJwk(keyData, result), "Round trip works");
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
}, "Good parameters with ignored JWK alg: " + crv.toString() + " " + parameterString('jwk', keyData, alg, true, usages));
});
}
// Helper methods follow:
// Are two array buffers the same?
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;
}
// Are two Jwk objects "the same"? That is, does the object returned include
// matching values for each property that was expected? It's okay if the
// returned object has extra methods; they aren't checked.
function equalJwk(expected, got) {
var fields = Object.keys(expected);
var fieldName;
for(var i=0; i<fields.length; i++) {
fieldName = fields[i];
if (!(fieldName in got)) {
return false;
}
if (expected[fieldName] !== got[fieldName]) {
return false;
}
}
return true;
}
// Build minimal Jwk objects from raw key data and algorithm specifications
function jwkData(keyData, algorithm) {
var result = {
kty: "oct",
k: byteArrayToUnpaddedBase64(keyData)
};
if (algorithm.name.substring(0, 3) === "AES") {
result.alg = "A" + (8 * keyData.byteLength).toString() + algorithm.name.substring(4);
} else if (algorithm.name === "HMAC") {
result.alg = "HS" + algorithm.hash.substring(4);
}
return result;
}
// Jwk format wants Base 64 without the typical padding at the end.
function byteArrayToUnpaddedBase64(byteArray){
var binaryString = "";
for (var i=0; i<byteArray.byteLength; i++){
binaryString += String.fromCharCode(byteArray[i]);
}
var base64String = btoa(binaryString);
return base64String.replace(/=/g, "");
}
// Convert method parameters to a string to uniquely name each test
function parameterString(format, data, algorithm, extractable, usages) {
if ("byteLength" in data) {
data = "buffer(" + data.byteLength.toString() + ")";
} else {
data = "object(" + Object.keys(data).join(", ") + ")";
}
var result = "(" +
objectToString(format) + ", " +
objectToString(data) + ", " +
objectToString(algorithm) + ", " +
objectToString(extractable) + ", " +
objectToString(usages) +
")";
return result;
}
// Character representation of any object we may use as a parameter.
function objectToString(obj) {
var keyValuePairs = [];
if (Array.isArray(obj)) {
return "[" + obj.map(function(elem){return objectToString(elem);}).join(", ") + "]";
} else if (typeof obj === "object") {
Object.keys(obj).sort().forEach(function(keyName) {
keyValuePairs.push(keyName + ": " + objectToString(obj[keyName]));
});
return "{" + keyValuePairs.join(", ") + "}";
} else if (typeof obj === "undefined") {
return "undefined";
} else {
return obj.toString();
}
var keyValuePairs = [];
Object.keys(obj).sort().forEach(function(keyName) {
var value = obj[keyName];
if (typeof value === "object") {
value = objectToString(value);
} else if (typeof value === "array") {
value = "[" + value.map(function(elem){return objectToString(elem);}).join(", ") + "]";
} else {
value = value.toString();
}
keyValuePairs.push(keyName + ": " + value);
});
return "{" + keyValuePairs.join(", ") + "}";
}

View file

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=utf-8>
<title>WebCryptoAPI: importKey() for OKP keys</title>
<meta name="timeout" content="long">
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../util/helpers.js"></script>
<script src="okp_importKey_fixtures.js"></script>
<script src="okp_importKey.js"></script>
<div id=log></div>
<script src="../../WebCryptoAPI/import_export/okp_importKey_Ed25519.https.any.js"></script>

View file

@ -0,0 +1,9 @@
// META: title=WebCryptoAPI: importKey() for OKP keys
// META: timeout=long
// META: script=../util/helpers.js
// META: script=okp_importKey_fixtures.js
// META: script=okp_importKey.js
// Test importKey and exportKey for OKP algorithms.
runTests("Ed25519");

View file

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=utf-8>
<title>WebCryptoAPI: importKey() for OKP keys</title>
<meta name="timeout" content="long">
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../util/helpers.js"></script>
<script src="okp_importKey_fixtures.js"></script>
<script src="okp_importKey.js"></script>
<div id=log></div>
<script src="../../WebCryptoAPI/import_export/okp_importKey_X25519.https.any.js"></script>

View file

@ -0,0 +1,9 @@
// META: title=WebCryptoAPI: importKey() for OKP keys
// META: timeout=long
// META: script=../util/helpers.js
// META: script=okp_importKey_fixtures.js
// META: script=okp_importKey.js
// Test importKey and exportKey for OKP algorithms.
runTests("X25519");

View file

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=utf-8>
<title>WebCryptoAPI: importKey() for Failures</title>
<meta name="timeout" content="long">
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../util/helpers.js"></script>
<script src="okp_importKey_failures_fixtures.js"></script>
<script src="importKey_failures.js"></script>
<div id=log></div>
<script src="../../WebCryptoAPI/import_export/okp_importKey_failures_Ed25519.https.any.js"></script>

View file

@ -0,0 +1,7 @@
// META: title=WebCryptoAPI: importKey() for Failures
// META: timeout=long
// META: script=../util/helpers.js
// META: script=okp_importKey_failures_fixtures.js
// META: script=importKey_failures.js
run_test(["Ed25519"]);

View file

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=utf-8>
<title>WebCryptoAPI: importKey() for Failures</title>
<meta name="timeout" content="long">
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../util/helpers.js"></script>
<script src="okp_importKey_failures_fixtures.js"></script>
<script src="importKey_failures.js"></script>
<div id=log></div>
<script src="../../WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.js"></script>

View file

@ -0,0 +1,8 @@
// META: title=WebCryptoAPI: importKey() for Failures
// META: timeout=long
// META: script=../util/helpers.js
// META: script=okp_importKey_failures_fixtures.js
// META: script=importKey_failures.js
run_test(["X25519"]);

View file

@ -0,0 +1,414 @@
// Setup: define the correct behaviors that should be sought, and create
// helper functions that generate all possible test parameters for
// different situations.
function getValidKeyData(algorithm) {
return validKeyData[algorithm.name];
}
function getBadKeyLengthData(algorithm) {
return badKeyLengthData[algorithm.name];
}
function getMissingJWKFieldKeyData(algorithm) {
return missingJWKFieldKeyData[algorithm.name];
}
function getMismatchedJWKKeyData(algorithm) {
return mismatchedJWKKeyData[algorithm.name];
}
var validKeyData = {
"Ed25519": [
{
format: "spki",
data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204])
},
{
format: "pkcs8",
data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168, 31])
},
{
format: "raw",
data: new Uint8Array([216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204])
},
{
format: "jwk",
data: {
crv: "Ed25519",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "Ed25519",
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
kty: "OKP"
},
}
],
"Ed448": [
{
format: "spki",
data: new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
},
{
format: "pkcs8",
data: new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29, 46]),
},
{
format: "raw",
data: new Uint8Array([171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
},
{
format: "jwk",
data: {
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "Ed448",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
kty: "OKP"
},
},
],
"X25519": [
{
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]),
},
{
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]),
},
{
format: "raw",
data: new Uint8Array([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]),
},
{
format: "jwk",
data: {
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2E",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "X25519",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
kty: "OKP"
},
},
],
"X448": [
{
format: "spki",
data: new Uint8Array([48, 66, 48, 5, 6, 3, 43, 101, 111, 3, 57, 0, 182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206, 111]),
},
{
format: "pkcs8",
data: new Uint8Array([48, 70, 2, 1, 0, 48, 5, 6, 3, 43, 101, 111, 4, 58, 4, 56, 88, 199, 210, 154, 62, 181, 25, 178, 157, 0, 207, 177, 145, 187, 100, 252, 109, 138, 66, 216, 241, 113, 118, 39, 43, 137, 242, 39, 45, 24, 25, 41, 92, 101, 37, 192, 130, 150, 113, 176, 82, 239, 7, 39, 83, 15, 24, 142, 49, 208, 204, 83, 191, 38, 146, 158]),
},
{
format: "raw",
data: new Uint8Array([182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206, 111]),
},
{
format: "jwk",
data: {
crv: "X448",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp4",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "X448",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
kty: "OKP"
},
},
],
};
// Removed just the last byte.
var badKeyLengthData = {
"Ed25519": [
{
format: "spki",
data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61])
},
{
format: "pkcs8",
data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168])
},
{
format: "raw",
data: new Uint8Array([216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61])
},
{
format: "jwk",
data: {
crv: "Ed25519",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB",
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
kty: "OKP"
}
},
{
format: "jwk",
data: {
crv: "Ed25519",
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPc",
kty: "OKP"
}
}
],
"Ed448": [
{
format: "spki",
data: new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90]),
},
{
format: "pkcs8",
data: new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29]),
},
{
format: "raw",
data: new Uint8Array([171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90]),
},
{
format: "jwk",
data: {
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "Ed448",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalq",
kty: "OKP"
},
},
],
"X25519": [
{
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]),
},
{
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]),
},
{
format: "raw",
data: new Uint8Array([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]),
},
{
format: "jwk",
data: {
crv: "X25519",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lw",
kty: "OKP"
}
},
{
format: "jwk",
data: {
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
kty: "OKP"
},
},
],
"X448": [
{
format: "spki",
data: new Uint8Array([48, 66, 48, 5, 6, 3, 43, 101, 111, 3, 57, 0, 182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206]),
},
{
format: "pkcs8",
data: new Uint8Array([48, 70, 2, 1, 0, 48, 5, 6, 3, 43, 101, 111, 4, 58, 4, 56, 88, 199, 210, 154, 62, 181, 25, 178, 157, 0, 207, 177, 145, 187, 100, 252, 109, 138, 66, 216, 241, 113, 118, 39, 43, 137, 242, 39, 45, 24, 25, 41, 92, 101, 37, 192, 130, 150, 113, 176, 82, 239, 7, 39, 83, 15, 24, 142, 49, 208, 204, 83, 191, 38, 146]),
},
{
format: "raw",
data: new Uint8Array([182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206]),
},
{
format: "jwk",
data: {
crv: "X448",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
kty: "OKP"
},
},
{
format: "jwk",
data: {
crv: "X448",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm",
kty: "OKP"
},
},
],
};
var missingJWKFieldKeyData = {
"Ed25519": [
{
param: "x",
data: {
crv: "Ed25519",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
kty: "OKP"
},
},
{
param: "kty",
data: {
crv: "Ed25519",
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
},
},
{
param: "crv",
data: {
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
kty: "OKP"
},
}
],
"Ed448": [
{
param: "x",
data: {
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
kty: "OKP"
}
},
{
param: "kty",
data: {
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
}
},
{
param: "crv",
data: {
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
kty: "OKP"
}
}
],
"X25519": [
{
param: "x",
data: {
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2E",
kty: "OKP"
},
},
{
param: "kty",
data: {
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2E",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
},
},
{
param: "crv",
data: {
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
kty: "OKP"
},
}
],
"X448": [
{
param: "x",
data: {
crv: "X448",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp4",
kty: "OKP"
}
},
{
param: "kty",
data: {
crv: "X448",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp4",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
}
},
{
param: "crv",
data: {
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
kty: "OKP"
}
}
],
};
// The public key doesn't match the private key.
var mismatchedJWKKeyData = {
"Ed25519": [
{
crv: "Ed25519",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
kty: "OKP"
},
],
"Ed448": [
{
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
x: "X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq_oJWGA",
kty: "OKP"
},
],
"X25519": [
{
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2E",
x: "hSDwCYkwp1R0i33ctD73Wg2_Og0mOBr066SpjqqbTmo",
kty: "OKP"
},
],
"X448": [
{
crv: "X448",
kty: "OKP",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp4",
x: "mwj3zDG34+Z9ItWuoSEHSic70rg94Jxj+qc9LCLF2bvINmRyQdlT1AxbEtqIEg1TF3+A5TLEH6A",
},
],
}

View file

@ -0,0 +1,58 @@
var keyData = {
"Ed25519": {
privateUsages: ["sign"],
publicUsages: ["verify"],
spki: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204]),
raw: new Uint8Array([216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204]),
pkcs8: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168, 31]),
jwk: {
crv: "Ed25519",
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
kty: "OKP"
}
},
"Ed448": {
privateUsages: ["sign"],
publicUsages: ["verify"],
spki: new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
raw: new Uint8Array([171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
pkcs8: new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29, 46]),
jwk: {
crv: "Ed448",
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
kty: "OKP"
}
},
"X25519": {
privateUsages: ["deriveKey", "deriveBits"],
publicUsages: [],
spki: 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]),
raw: new Uint8Array([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]),
pkcs8: 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]),
jwk: {
crv: "X25519",
d: "yIOOdtBX37fYyVpp4TgWCt1jc_1xpNJ2u1bjqBtk_2E",
x: "HPKx5gIuxTc3Htf1PlT6EVTYPpjrZOpR-uWzMHz-lwY",
kty: "OKP"
}
},
"X448": {
privateUsages: ["deriveKey", "deriveBits"],
publicUsages: [],
spki: new Uint8Array([48, 66, 48, 5, 6, 3, 43, 101, 111, 3, 57, 0, 182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206, 111]),
raw: new Uint8Array([182, 4, 161, 209, 165, 205, 29, 148, 38, 213, 97, 239, 99, 10, 158, 177, 108, 190, 105, 213, 185, 202, 97, 94, 220, 83, 99, 62, 251, 82, 234, 49, 230, 230, 160, 161, 219, 172, 198, 231, 108, 188, 230, 72, 45, 126, 75, 163, 213, 93, 158, 128, 39, 101, 206, 111]),
pkcs8: new Uint8Array([48, 70, 2, 1, 0, 48, 5, 6, 3, 43, 101, 111, 4, 58, 4, 56, 88, 199, 210, 154, 62, 181, 25, 178, 157, 0, 207, 177, 145, 187, 100, 252, 109, 138, 66, 216, 241, 113, 118, 39, 43, 137, 242, 39, 45, 24, 25, 41, 92, 101, 37, 192, 130, 150, 113, 176, 82, 239, 7, 39, 83, 15, 24, 142, 49, 208, 204, 83, 191, 38, 146, 158]),
jwk: {
crv: "X448",
d: "WMfSmj61GbKdAM-xkbtk_G2KQtjxcXYnK4nyJy0YGSlcZSXAgpZxsFLvBydTDxiOMdDMU78mkp4",
x: "tgSh0aXNHZQm1WHvYwqesWy-adW5ymFe3FNjPvtS6jHm5qCh26zG52y85kgtfkuj1V2egCdlzm8",
kty: "OKP"
}
},
};