Skip to content

Commit 93fc80a

Browse files
panvatargos
authored andcommitted
lib: refactor kSupportedAlgorithms
PR-URL: #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>
1 parent a95386f commit 93fc80a

File tree

1 file changed

+205
-160
lines changed

1 file changed

+205
-160
lines changed

lib/internal/crypto/util.js

Lines changed: 205 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -171,185 +171,230 @@ const kNamedCurveAliases = {
171171
'P-521': 'secp521r1',
172172
};
173173

174-
const kSupportedAlgorithms = {
175-
'digest': {
176-
'SHA-1': null,
177-
'SHA-256': null,
178-
'SHA-384': null,
179-
'SHA-512': null,
174+
// Algorithm definitions organized by algorithm name
175+
const kAlgorithmDefinitions = {
176+
'AES-CBC': {
177+
'generateKey': 'AesKeyGenParams',
178+
'exportKey': null,
179+
'importKey': null,
180+
'encrypt': 'AesCbcParams',
181+
'decrypt': 'AesCbcParams',
182+
'get key length': 'AesDerivedKeyParams',
183+
},
184+
'AES-CTR': {
185+
'generateKey': 'AesKeyGenParams',
186+
'exportKey': null,
187+
'importKey': null,
188+
'encrypt': 'AesCtrParams',
189+
'decrypt': 'AesCtrParams',
190+
'get key length': 'AesDerivedKeyParams',
180191
},
181-
'generateKey': {
182-
'RSASSA-PKCS1-v1_5': 'RsaHashedKeyGenParams',
183-
'RSA-PSS': 'RsaHashedKeyGenParams',
184-
'RSA-OAEP': 'RsaHashedKeyGenParams',
185-
'ECDSA': 'EcKeyGenParams',
186-
'ECDH': 'EcKeyGenParams',
187-
'AES-CTR': 'AesKeyGenParams',
188-
'AES-CBC': 'AesKeyGenParams',
189-
'AES-GCM': 'AesKeyGenParams',
190-
'HMAC': 'HmacKeyGenParams',
191-
'Ed25519': null,
192-
'X25519': null,
192+
'AES-GCM': {
193+
'generateKey': 'AesKeyGenParams',
194+
'exportKey': null,
195+
'importKey': null,
196+
'encrypt': 'AeadParams',
197+
'decrypt': 'AeadParams',
198+
'get key length': 'AesDerivedKeyParams',
193199
},
194-
'exportKey': {
195-
'RSASSA-PKCS1-v1_5': null,
196-
'RSA-PSS': null,
197-
'RSA-OAEP': null,
198-
'ECDSA': null,
199-
'ECDH': null,
200-
'HMAC': null,
201-
'AES-CTR': null,
202-
'AES-CBC': null,
203-
'AES-GCM': null,
204-
'Ed25519': null,
205-
'X25519': null,
200+
'AES-KW': {
201+
'generateKey': 'AesKeyGenParams',
202+
'exportKey': null,
203+
'importKey': null,
204+
'get key length': 'AesDerivedKeyParams',
205+
'wrapKey': null,
206+
'unwrapKey': null,
206207
},
207-
'sign': {
208-
'RSASSA-PKCS1-v1_5': null,
209-
'RSA-PSS': 'RsaPssParams',
210-
'ECDSA': 'EcdsaParams',
211-
'HMAC': null,
212-
'Ed25519': null,
208+
'ChaCha20-Poly1305': {
209+
'generateKey': null,
210+
'exportKey': null,
211+
'importKey': null,
212+
'encrypt': 'AeadParams',
213+
'decrypt': 'AeadParams',
214+
'get key length': null,
213215
},
214-
'verify': {
215-
'RSASSA-PKCS1-v1_5': null,
216-
'RSA-PSS': 'RsaPssParams',
217-
'ECDSA': 'EcdsaParams',
218-
'HMAC': null,
219-
'Ed25519': null,
216+
'cSHAKE128': { 'digest': 'CShakeParams' },
217+
'cSHAKE256': { 'digest': 'CShakeParams' },
218+
'ECDH': {
219+
'generateKey': 'EcKeyGenParams',
220+
'exportKey': null,
221+
'importKey': 'EcKeyImportParams',
222+
'deriveBits': 'EcdhKeyDeriveParams',
220223
},
221-
'importKey': {
222-
'RSASSA-PKCS1-v1_5': 'RsaHashedImportParams',
223-
'RSA-PSS': 'RsaHashedImportParams',
224-
'RSA-OAEP': 'RsaHashedImportParams',
225-
'ECDSA': 'EcKeyImportParams',
226-
'ECDH': 'EcKeyImportParams',
227-
'HMAC': 'HmacImportParams',
228-
'HKDF': null,
229-
'PBKDF2': null,
230-
'AES-CTR': null,
231-
'AES-CBC': null,
232-
'AES-GCM': null,
233-
'Ed25519': null,
234-
'X25519': null,
224+
'ECDSA': {
225+
'generateKey': 'EcKeyGenParams',
226+
'exportKey': null,
227+
'importKey': 'EcKeyImportParams',
228+
'sign': 'EcdsaParams',
229+
'verify': 'EcdsaParams',
235230
},
236-
'deriveBits': {
237-
'HKDF': 'HkdfParams',
238-
'PBKDF2': 'Pbkdf2Params',
239-
'ECDH': 'EcdhKeyDeriveParams',
240-
'X25519': 'EcdhKeyDeriveParams',
231+
'Ed25519': {
232+
'generateKey': null,
233+
'exportKey': null,
234+
'importKey': null,
235+
'sign': null,
236+
'verify': null,
241237
},
242-
'encrypt': {
243-
'RSA-OAEP': 'RsaOaepParams',
244-
'AES-CBC': 'AesCbcParams',
245-
'AES-GCM': 'AeadParams',
246-
'AES-CTR': 'AesCtrParams',
238+
'Ed448': {
239+
'generateKey': null,
240+
'exportKey': null,
241+
'importKey': null,
242+
'sign': 'Ed448Params',
243+
'verify': 'Ed448Params',
247244
},
248-
'decrypt': {
249-
'RSA-OAEP': 'RsaOaepParams',
250-
'AES-CBC': 'AesCbcParams',
251-
'AES-GCM': 'AeadParams',
252-
'AES-CTR': 'AesCtrParams',
245+
'HKDF': {
246+
'importKey': null,
247+
'deriveBits': 'HkdfParams',
248+
'get key length': null,
253249
},
254-
'get key length': {
255-
'AES-CBC': 'AesDerivedKeyParams',
256-
'AES-CTR': 'AesDerivedKeyParams',
257-
'AES-GCM': 'AesDerivedKeyParams',
258-
'HMAC': 'HmacImportParams',
259-
'HKDF': null,
260-
'PBKDF2': null,
250+
'HMAC': {
251+
'generateKey': 'HmacKeyGenParams',
252+
'exportKey': null,
253+
'importKey': 'HmacImportParams',
254+
'sign': null,
255+
'verify': null,
256+
'get key length': 'HmacImportParams',
261257
},
262-
'wrapKey': {},
263-
'unwrapKey': {},
264-
};
265-
266-
const conditionalAlgorithms = ObjectEntries({
267-
'AES-KW': [{
268-
'generateKey': 'AesKeyGenParams',
258+
'ML-DSA-44': {
259+
'generateKey': null,
269260
'exportKey': null,
270261
'importKey': null,
271-
'get key length': 'AesDerivedKeyParams',
272-
'wrapKey': null,
273-
'unwrapKey': null,
274-
}, !process.features.openssl_is_boringssl],
275-
});
262+
'sign': 'ContextParams',
263+
'verify': 'ContextParams',
264+
},
265+
'ML-DSA-65': {
266+
'generateKey': null,
267+
'exportKey': null,
268+
'importKey': null,
269+
'sign': 'ContextParams',
270+
'verify': 'ContextParams',
271+
},
272+
'ML-DSA-87': {
273+
'generateKey': null,
274+
'exportKey': null,
275+
'importKey': null,
276+
'sign': 'ContextParams',
277+
'verify': 'ContextParams',
278+
},
279+
'PBKDF2': {
280+
'importKey': null,
281+
'deriveBits': 'Pbkdf2Params',
282+
'get key length': null,
283+
},
284+
'RSA-OAEP': {
285+
'generateKey': 'RsaHashedKeyGenParams',
286+
'exportKey': null,
287+
'importKey': 'RsaHashedImportParams',
288+
'encrypt': 'RsaOaepParams',
289+
'decrypt': 'RsaOaepParams',
290+
},
291+
'RSA-PSS': {
292+
'generateKey': 'RsaHashedKeyGenParams',
293+
'exportKey': null,
294+
'importKey': 'RsaHashedImportParams',
295+
'sign': 'RsaPssParams',
296+
'verify': 'RsaPssParams',
297+
},
298+
'RSASSA-PKCS1-v1_5': {
299+
'generateKey': 'RsaHashedKeyGenParams',
300+
'exportKey': null,
301+
'importKey': 'RsaHashedImportParams',
302+
'sign': null,
303+
'verify': null,
304+
},
305+
'SHA-1': { 'digest': null },
306+
'SHA-256': { 'digest': null },
307+
'SHA-384': { 'digest': null },
308+
'SHA-512': { 'digest': null },
309+
'SHA3-256': { 'digest': null },
310+
'SHA3-384': { 'digest': null },
311+
'SHA3-512': { 'digest': null },
312+
'X25519': {
313+
'generateKey': null,
314+
'exportKey': null,
315+
'importKey': null,
316+
'deriveBits': 'EcdhKeyDeriveParams',
317+
},
318+
'X448': {
319+
'generateKey': null,
320+
'exportKey': null,
321+
'importKey': null,
322+
'deriveBits': 'EcdhKeyDeriveParams',
323+
},
324+
};
276325

277-
for (let i = 0; i < conditionalAlgorithms.length; i++) {
278-
if (conditionalAlgorithms[i][1][1]) {
279-
const name = conditionalAlgorithms[i][0];
280-
const ops = ObjectEntries(conditionalAlgorithms[i][1][0]);
281-
for (let j = 0; j < ops.length; j++) {
282-
const { 0: op, 1: dict } = ops[j];
283-
kSupportedAlgorithms[op][name] = dict;
284-
}
285-
}
286-
}
326+
// Conditionally supported algorithms
327+
const conditionalAlgorithms = {
328+
'AES-KW': !process.features.openssl_is_boringssl,
329+
'ChaCha20-Poly1305': !process.features.openssl_is_boringssl ||
330+
ArrayPrototypeIncludes(getCiphers(), 'chacha20-poly1305'),
331+
'cSHAKE128': !process.features.openssl_is_boringssl ||
332+
ArrayPrototypeIncludes(getHashes(), 'shake128'),
333+
'cSHAKE256': !process.features.openssl_is_boringssl ||
334+
ArrayPrototypeIncludes(getHashes(), 'shake256'),
335+
'Ed448': !process.features.openssl_is_boringssl,
336+
'ML-DSA-44': !!EVP_PKEY_ML_DSA_44,
337+
'ML-DSA-65': !!EVP_PKEY_ML_DSA_65,
338+
'ML-DSA-87': !!EVP_PKEY_ML_DSA_87,
339+
'SHA3-256': !process.features.openssl_is_boringssl ||
340+
ArrayPrototypeIncludes(getHashes(), 'sha3-256'),
341+
'SHA3-384': !process.features.openssl_is_boringssl ||
342+
ArrayPrototypeIncludes(getHashes(), 'sha3-384'),
343+
'SHA3-512': !process.features.openssl_is_boringssl ||
344+
ArrayPrototypeIncludes(getHashes(), 'sha3-512'),
345+
'X448': !process.features.openssl_is_boringssl,
346+
};
287347

288-
const experimentalAlgorithms = ObjectEntries({});
289-
290-
if (!process.features.openssl_is_boringssl) {
291-
ArrayPrototypePush(experimentalAlgorithms,
292-
['Ed448', {
293-
generateKey: null,
294-
sign: 'Ed448Params',
295-
verify: 'Ed448Params',
296-
importKey: null,
297-
exportKey: null,
298-
}],
299-
['X448', {
300-
generateKey: null,
301-
importKey: null,
302-
deriveBits: 'EcdhKeyDeriveParams',
303-
exportKey: null,
304-
}],
305-
['cSHAKE128', { digest: 'CShakeParams' }],
306-
['cSHAKE256', { digest: 'CShakeParams' }],
307-
['ChaCha20-Poly1305', {
308-
'encrypt': 'AeadParams',
309-
'decrypt': 'AeadParams',
310-
'generateKey': null,
311-
'importKey': null,
312-
'exportKey': null,
313-
'get key length': null,
314-
}],
315-
['SHA3-256', { digest: null }],
316-
['SHA3-384', { digest: null }],
317-
['SHA3-512', { digest: null }],
318-
);
319-
}
348+
// Experimental algorithms
349+
const experimentalAlgorithms = [
350+
'ChaCha20-Poly1305',
351+
'cSHAKE128',
352+
'cSHAKE256',
353+
'Ed448',
354+
'ML-DSA-44',
355+
'ML-DSA-65',
356+
'ML-DSA-87',
357+
'SHA3-256',
358+
'SHA3-384',
359+
'SHA3-512',
360+
'X448',
361+
];
362+
363+
// Transform the algorithm definitions into the operation-keyed structure
364+
function createSupportedAlgorithms(algorithmDefs) {
365+
const result = {};
366+
367+
for (const { 0: algorithmName, 1: operations } of ObjectEntries(algorithmDefs)) {
368+
// Skip algorithms that are conditionally not supported
369+
if (ObjectPrototypeHasOwnProperty(conditionalAlgorithms, algorithmName) &&
370+
!conditionalAlgorithms[algorithmName]) {
371+
continue;
372+
}
320373

321-
for (const { 0: algorithm, 1: nid } of [
322-
['ML-DSA-44', EVP_PKEY_ML_DSA_44],
323-
['ML-DSA-65', EVP_PKEY_ML_DSA_65],
324-
['ML-DSA-87', EVP_PKEY_ML_DSA_87],
325-
]) {
326-
if (nid) {
327-
ArrayPrototypePush(experimentalAlgorithms, [algorithm, {
328-
generateKey: null,
329-
sign: 'ContextParams',
330-
verify: 'ContextParams',
331-
importKey: null,
332-
exportKey: null,
333-
}]);
374+
for (const { 0: operation, 1: dict } of ObjectEntries(operations)) {
375+
result[operation] ||= {};
376+
377+
// Add experimental warnings for experimental algorithms
378+
if (ArrayPrototypeIncludes(experimentalAlgorithms, algorithmName)) {
379+
ObjectDefineProperty(result[operation], algorithmName, {
380+
get() {
381+
emitExperimentalWarning(`The ${algorithmName} Web Crypto API algorithm`);
382+
return dict;
383+
},
384+
__proto__: null,
385+
enumerable: true,
386+
});
387+
} else {
388+
result[operation][algorithmName] = dict;
389+
}
390+
}
334391
}
335-
}
336392

337-
for (let i = 0; i < experimentalAlgorithms.length; i++) {
338-
const name = experimentalAlgorithms[i][0];
339-
const ops = ObjectEntries(experimentalAlgorithms[i][1]);
340-
for (let j = 0; j < ops.length; j++) {
341-
const { 0: op, 1: dict } = ops[j];
342-
ObjectDefineProperty(kSupportedAlgorithms[op], name, {
343-
get() {
344-
emitExperimentalWarning(`The ${name} Web Crypto API algorithm`);
345-
return dict;
346-
},
347-
__proto__: null,
348-
enumerable: true,
349-
});
350-
}
393+
return result;
351394
}
352395

396+
const kSupportedAlgorithms = createSupportedAlgorithms(kAlgorithmDefinitions);
397+
353398
const simpleAlgorithmDictionaries = {
354399
AeadParams: { iv: 'BufferSource', additionalData: 'BufferSource' },
355400
RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier' },

0 commit comments

Comments
 (0)