lib: refactor kSupportedAlgorithms

PR-URL: https://github.com/nodejs/node/pull/59365
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
Filip Skokan 2025-08-09 13:41:45 +02:00
parent 0cc2c83e32
commit 5329f73816
No known key found for this signature in database

View File

@ -171,184 +171,229 @@ const kNamedCurveAliases = {
'P-521': 'secp521r1',
};
const kSupportedAlgorithms = {
'digest': {
'SHA-1': null,
'SHA-256': null,
'SHA-384': null,
'SHA-512': null,
// Algorithm definitions organized by algorithm name
const kAlgorithmDefinitions = {
'AES-CBC': {
'generateKey': 'AesKeyGenParams',
'exportKey': null,
'importKey': null,
'encrypt': 'AesCbcParams',
'decrypt': 'AesCbcParams',
'get key length': 'AesDerivedKeyParams',
},
'generateKey': {
'RSASSA-PKCS1-v1_5': 'RsaHashedKeyGenParams',
'RSA-PSS': 'RsaHashedKeyGenParams',
'RSA-OAEP': 'RsaHashedKeyGenParams',
'ECDSA': 'EcKeyGenParams',
'ECDH': 'EcKeyGenParams',
'AES-CTR': 'AesKeyGenParams',
'AES-CBC': 'AesKeyGenParams',
'AES-GCM': 'AesKeyGenParams',
'HMAC': 'HmacKeyGenParams',
'Ed25519': null,
'X25519': null,
'AES-CTR': {
'generateKey': 'AesKeyGenParams',
'exportKey': null,
'importKey': null,
'encrypt': 'AesCtrParams',
'decrypt': 'AesCtrParams',
'get key length': 'AesDerivedKeyParams',
},
'exportKey': {
'RSASSA-PKCS1-v1_5': null,
'RSA-PSS': null,
'RSA-OAEP': null,
'ECDSA': null,
'ECDH': null,
'HMAC': null,
'AES-CTR': null,
'AES-CBC': null,
'AES-GCM': null,
'Ed25519': null,
'X25519': null,
'AES-GCM': {
'generateKey': 'AesKeyGenParams',
'exportKey': null,
'importKey': null,
'encrypt': 'AeadParams',
'decrypt': 'AeadParams',
'get key length': 'AesDerivedKeyParams',
},
'sign': {
'RSASSA-PKCS1-v1_5': null,
'RSA-PSS': 'RsaPssParams',
'ECDSA': 'EcdsaParams',
'HMAC': null,
'Ed25519': null,
},
'verify': {
'RSASSA-PKCS1-v1_5': null,
'RSA-PSS': 'RsaPssParams',
'ECDSA': 'EcdsaParams',
'HMAC': null,
'Ed25519': null,
},
'importKey': {
'RSASSA-PKCS1-v1_5': 'RsaHashedImportParams',
'RSA-PSS': 'RsaHashedImportParams',
'RSA-OAEP': 'RsaHashedImportParams',
'ECDSA': 'EcKeyImportParams',
'ECDH': 'EcKeyImportParams',
'HMAC': 'HmacImportParams',
'HKDF': null,
'PBKDF2': null,
'AES-CTR': null,
'AES-CBC': null,
'AES-GCM': null,
'Ed25519': null,
'X25519': null,
},
'deriveBits': {
'HKDF': 'HkdfParams',
'PBKDF2': 'Pbkdf2Params',
'ECDH': 'EcdhKeyDeriveParams',
'X25519': 'EcdhKeyDeriveParams',
},
'encrypt': {
'RSA-OAEP': 'RsaOaepParams',
'AES-CBC': 'AesCbcParams',
'AES-GCM': 'AeadParams',
'AES-CTR': 'AesCtrParams',
},
'decrypt': {
'RSA-OAEP': 'RsaOaepParams',
'AES-CBC': 'AesCbcParams',
'AES-GCM': 'AeadParams',
'AES-CTR': 'AesCtrParams',
},
'get key length': {
'AES-CBC': 'AesDerivedKeyParams',
'AES-CTR': 'AesDerivedKeyParams',
'AES-GCM': 'AesDerivedKeyParams',
'HMAC': 'HmacImportParams',
'HKDF': null,
'PBKDF2': null,
},
'wrapKey': {},
'unwrapKey': {},
};
const conditionalAlgorithms = ObjectEntries({
'AES-KW': [{
'AES-KW': {
'generateKey': 'AesKeyGenParams',
'exportKey': null,
'importKey': null,
'get key length': 'AesDerivedKeyParams',
'wrapKey': null,
'unwrapKey': null,
}, !process.features.openssl_is_boringssl],
});
},
'ChaCha20-Poly1305': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'encrypt': 'AeadParams',
'decrypt': 'AeadParams',
'get key length': null,
},
'cSHAKE128': { 'digest': 'CShakeParams' },
'cSHAKE256': { 'digest': 'CShakeParams' },
'ECDH': {
'generateKey': 'EcKeyGenParams',
'exportKey': null,
'importKey': 'EcKeyImportParams',
'deriveBits': 'EcdhKeyDeriveParams',
},
'ECDSA': {
'generateKey': 'EcKeyGenParams',
'exportKey': null,
'importKey': 'EcKeyImportParams',
'sign': 'EcdsaParams',
'verify': 'EcdsaParams',
},
'Ed25519': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'sign': null,
'verify': null,
},
'Ed448': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'sign': 'Ed448Params',
'verify': 'Ed448Params',
},
'HKDF': {
'importKey': null,
'deriveBits': 'HkdfParams',
'get key length': null,
},
'HMAC': {
'generateKey': 'HmacKeyGenParams',
'exportKey': null,
'importKey': 'HmacImportParams',
'sign': null,
'verify': null,
'get key length': 'HmacImportParams',
},
'ML-DSA-44': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'sign': 'ContextParams',
'verify': 'ContextParams',
},
'ML-DSA-65': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'sign': 'ContextParams',
'verify': 'ContextParams',
},
'ML-DSA-87': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'sign': 'ContextParams',
'verify': 'ContextParams',
},
'PBKDF2': {
'importKey': null,
'deriveBits': 'Pbkdf2Params',
'get key length': null,
},
'RSA-OAEP': {
'generateKey': 'RsaHashedKeyGenParams',
'exportKey': null,
'importKey': 'RsaHashedImportParams',
'encrypt': 'RsaOaepParams',
'decrypt': 'RsaOaepParams',
},
'RSA-PSS': {
'generateKey': 'RsaHashedKeyGenParams',
'exportKey': null,
'importKey': 'RsaHashedImportParams',
'sign': 'RsaPssParams',
'verify': 'RsaPssParams',
},
'RSASSA-PKCS1-v1_5': {
'generateKey': 'RsaHashedKeyGenParams',
'exportKey': null,
'importKey': 'RsaHashedImportParams',
'sign': null,
'verify': null,
},
'SHA-1': { 'digest': null },
'SHA-256': { 'digest': null },
'SHA-384': { 'digest': null },
'SHA-512': { 'digest': null },
'SHA3-256': { 'digest': null },
'SHA3-384': { 'digest': null },
'SHA3-512': { 'digest': null },
'X25519': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'deriveBits': 'EcdhKeyDeriveParams',
},
'X448': {
'generateKey': null,
'exportKey': null,
'importKey': null,
'deriveBits': 'EcdhKeyDeriveParams',
},
};
for (let i = 0; i < conditionalAlgorithms.length; i++) {
if (conditionalAlgorithms[i][1][1]) {
const name = conditionalAlgorithms[i][0];
const ops = ObjectEntries(conditionalAlgorithms[i][1][0]);
for (let j = 0; j < ops.length; j++) {
const { 0: op, 1: dict } = ops[j];
kSupportedAlgorithms[op][name] = dict;
// Conditionally supported algorithms
const conditionalAlgorithms = {
'AES-KW': !process.features.openssl_is_boringssl,
'ChaCha20-Poly1305': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getCiphers(), 'chacha20-poly1305'),
'cSHAKE128': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getHashes(), 'shake128'),
'cSHAKE256': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getHashes(), 'shake256'),
'Ed448': !process.features.openssl_is_boringssl,
'ML-DSA-44': !!EVP_PKEY_ML_DSA_44,
'ML-DSA-65': !!EVP_PKEY_ML_DSA_65,
'ML-DSA-87': !!EVP_PKEY_ML_DSA_87,
'SHA3-256': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getHashes(), 'sha3-256'),
'SHA3-384': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getHashes(), 'sha3-384'),
'SHA3-512': !process.features.openssl_is_boringssl ||
ArrayPrototypeIncludes(getHashes(), 'sha3-512'),
'X448': !process.features.openssl_is_boringssl,
};
// Experimental algorithms
const experimentalAlgorithms = [
'ChaCha20-Poly1305',
'cSHAKE128',
'cSHAKE256',
'Ed448',
'ML-DSA-44',
'ML-DSA-65',
'ML-DSA-87',
'SHA3-256',
'SHA3-384',
'SHA3-512',
'X448',
];
// Transform the algorithm definitions into the operation-keyed structure
function createSupportedAlgorithms(algorithmDefs) {
const result = {};
for (const { 0: algorithmName, 1: operations } of ObjectEntries(algorithmDefs)) {
// Skip algorithms that are conditionally not supported
if (ObjectPrototypeHasOwnProperty(conditionalAlgorithms, algorithmName) &&
!conditionalAlgorithms[algorithmName]) {
continue;
}
for (const { 0: operation, 1: dict } of ObjectEntries(operations)) {
result[operation] ||= {};
// Add experimental warnings for experimental algorithms
if (ArrayPrototypeIncludes(experimentalAlgorithms, algorithmName)) {
ObjectDefineProperty(result[operation], algorithmName, {
get() {
emitExperimentalWarning(`The ${algorithmName} Web Crypto API algorithm`);
return dict;
},
__proto__: null,
enumerable: true,
});
} else {
result[operation][algorithmName] = dict;
}
}
}
return result;
}
const experimentalAlgorithms = ObjectEntries({});
if (!process.features.openssl_is_boringssl) {
ArrayPrototypePush(experimentalAlgorithms,
['Ed448', {
generateKey: null,
sign: 'Ed448Params',
verify: 'Ed448Params',
importKey: null,
exportKey: null,
}],
['X448', {
generateKey: null,
importKey: null,
deriveBits: 'EcdhKeyDeriveParams',
exportKey: null,
}],
['cSHAKE128', { digest: 'CShakeParams' }],
['cSHAKE256', { digest: 'CShakeParams' }],
['ChaCha20-Poly1305', {
'encrypt': 'AeadParams',
'decrypt': 'AeadParams',
'generateKey': null,
'importKey': null,
'exportKey': null,
'get key length': null,
}],
['SHA3-256', { digest: null }],
['SHA3-384', { digest: null }],
['SHA3-512', { digest: null }],
);
}
for (const { 0: algorithm, 1: nid } of [
['ML-DSA-44', EVP_PKEY_ML_DSA_44],
['ML-DSA-65', EVP_PKEY_ML_DSA_65],
['ML-DSA-87', EVP_PKEY_ML_DSA_87],
]) {
if (nid) {
ArrayPrototypePush(experimentalAlgorithms, [algorithm, {
generateKey: null,
sign: 'ContextParams',
verify: 'ContextParams',
importKey: null,
exportKey: null,
}]);
}
}
for (let i = 0; i < experimentalAlgorithms.length; i++) {
const name = experimentalAlgorithms[i][0];
const ops = ObjectEntries(experimentalAlgorithms[i][1]);
for (let j = 0; j < ops.length; j++) {
const { 0: op, 1: dict } = ops[j];
ObjectDefineProperty(kSupportedAlgorithms[op], name, {
get() {
emitExperimentalWarning(`The ${name} Web Crypto API algorithm`);
return dict;
},
__proto__: null,
enumerable: true,
});
}
}
const kSupportedAlgorithms = createSupportedAlgorithms(kAlgorithmDefinitions);
const simpleAlgorithmDictionaries = {
AeadParams: { iv: 'BufferSource', additionalData: 'BufferSource' },