mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
192 lines
5.5 KiB
TypeScript
192 lines
5.5 KiB
TypeScript
// Copyright wpt contributors
|
|
// Adopted from the web-platform-test/WebCryptoAPI/generateKey
|
|
// https://github.com/web-platform-tests/wpt/tree/6b7cd07ee9a3ad1ce849b36bdb882b723fa172d8/WebCryptoAPI/generateKey
|
|
|
|
// TODO: The following tests should be removed once the node-wpt
|
|
// or wpt test runner is fully adopted.
|
|
// FYI: https://github.com/oven-sh/bun/issues/19673
|
|
|
|
// helpers.js
|
|
//
|
|
// Helper functions used by several WebCryptoAPI tests
|
|
//
|
|
|
|
export var registeredAlgorithmNames = [
|
|
"RSASSA-PKCS1-v1_5",
|
|
"RSA-PSS",
|
|
"RSA-OAEP",
|
|
"ECDSA",
|
|
"ECDH",
|
|
"AES-CTR",
|
|
"AES-CBC",
|
|
"AES-GCM",
|
|
"AES-KW",
|
|
"HMAC",
|
|
"SHA-1",
|
|
"SHA-256",
|
|
"SHA-384",
|
|
"SHA-512",
|
|
"HKDF",
|
|
"PBKDF2",
|
|
"Ed25519",
|
|
// "Ed448", TODO: Operation is not supported
|
|
"X25519",
|
|
// "X448", TODO: Operation is not supported
|
|
];
|
|
|
|
// Treats an array as a set, and generates an array of all non-empty
|
|
// subsets (which are themselves arrays).
|
|
//
|
|
// The order of members of the "subsets" is not guaranteed.
|
|
export function allNonemptySubsetsOf(arr) {
|
|
var results: any[] = [];
|
|
var firstElement;
|
|
var remainingElements;
|
|
|
|
for (var i = 0; i < arr.length; i++) {
|
|
firstElement = arr[i];
|
|
remainingElements = arr.slice(i + 1);
|
|
results.push([firstElement]);
|
|
|
|
if (remainingElements.length > 0) {
|
|
allNonemptySubsetsOf(remainingElements).forEach(function (combination) {
|
|
combination.push(firstElement);
|
|
results.push(combination);
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
// Create a string representation of keyGeneration parameters for
|
|
// test names and labels.
|
|
export function objectToString(obj): string {
|
|
var keyValuePairs: string[] = [];
|
|
|
|
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: string) {
|
|
keyValuePairs.push(keyName + ": " + objectToString(obj[keyName]));
|
|
});
|
|
return "{" + keyValuePairs.join(", ") + "}";
|
|
} else if (typeof obj === "undefined") {
|
|
return "undefined";
|
|
} else {
|
|
return obj.toString();
|
|
}
|
|
}
|
|
|
|
export function unique(names) {
|
|
return [...new Set(names)];
|
|
}
|
|
|
|
// Algorithm name specifiers are case-insensitive. Generate several
|
|
// case variations of a given name.
|
|
export function allNameVariants(name, slowTest) {
|
|
var upCaseName = name.toUpperCase();
|
|
var lowCaseName = name.toLowerCase();
|
|
var mixedCaseName = upCaseName.substring(0, 1) + lowCaseName.substring(1);
|
|
|
|
// for slow tests effectively cut the amount of work in third by only
|
|
// returning one variation
|
|
if (slowTest) return [mixedCaseName];
|
|
return unique([upCaseName, lowCaseName, mixedCaseName]);
|
|
}
|
|
|
|
// The algorithm parameter is an object with a name and other
|
|
// properties. Given the name, generate all valid parameters.
|
|
export function allAlgorithmSpecifiersFor(algorithmName) {
|
|
var results: any[] = [];
|
|
|
|
// RSA key generation is slow. Test a minimal set of parameters
|
|
var hashes = ["SHA-1", "SHA-256"];
|
|
|
|
// EC key generation is a lot faster. Check all curves in the spec
|
|
var curves = ["P-256", "P-384", "P-521"];
|
|
|
|
if (algorithmName.toUpperCase().substring(0, 3) === "AES") {
|
|
// Specifier properties are name and length
|
|
[128, 192, 256].forEach(function (length) {
|
|
results.push({ name: algorithmName, length: length });
|
|
});
|
|
} else if (algorithmName.toUpperCase() === "HMAC") {
|
|
[
|
|
{ hash: "SHA-1", length: 160 },
|
|
{ hash: "SHA-256", length: 256 },
|
|
{ hash: "SHA-384", length: 384 },
|
|
{ hash: "SHA-512", length: 512 },
|
|
{ hash: "SHA-1" },
|
|
{ hash: "SHA-256" },
|
|
{ hash: "SHA-384" },
|
|
{ hash: "SHA-512" },
|
|
].forEach(function (hashAlgorithm) {
|
|
results.push({ name: algorithmName, ...hashAlgorithm });
|
|
});
|
|
} else if (algorithmName.toUpperCase().substring(0, 3) === "RSA") {
|
|
hashes.forEach(function (hashName) {
|
|
results.push({
|
|
name: algorithmName,
|
|
hash: hashName,
|
|
modulusLength: 2048,
|
|
publicExponent: new Uint8Array([1, 0, 1]),
|
|
});
|
|
});
|
|
} else if (algorithmName.toUpperCase().substring(0, 2) === "EC") {
|
|
curves.forEach(function (curveName) {
|
|
results.push({ name: algorithmName, namedCurve: curveName });
|
|
});
|
|
} else if (
|
|
algorithmName.toUpperCase().substring(0, 1) === "X" ||
|
|
algorithmName.toUpperCase().substring(0, 2) === "ED"
|
|
) {
|
|
results.push({ name: algorithmName });
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
// Create every possible valid usages parameter, given legal
|
|
// usages. Note that an empty usages parameter is not always valid.
|
|
//
|
|
// There is an optional parameter - mandatoryUsages. If provided,
|
|
// it should be an array containing those usages of which one must be
|
|
// included.
|
|
export function allValidUsages(validUsages, emptyIsValid, mandatoryUsages: any[]) {
|
|
if (typeof mandatoryUsages === "undefined") {
|
|
mandatoryUsages = [];
|
|
}
|
|
|
|
var okaySubsets: any[] = [];
|
|
allNonemptySubsetsOf(validUsages).forEach(function (subset) {
|
|
if (mandatoryUsages.length === 0) {
|
|
okaySubsets.push(subset);
|
|
} else {
|
|
for (var i = 0; i < mandatoryUsages.length; i++) {
|
|
if (subset.includes(mandatoryUsages[i])) {
|
|
okaySubsets.push(subset);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (emptyIsValid && validUsages.length !== 0) {
|
|
okaySubsets.push([]);
|
|
}
|
|
|
|
okaySubsets.push(validUsages.concat(mandatoryUsages).concat(validUsages)); // Repeated values are allowed
|
|
return okaySubsets;
|
|
}
|