lib: refactor kSupportedAlgorithms · nodejs/node@93fc80a

@@ -171,185 +171,230 @@ const kNamedCurveAliases = {

171171

'P-521': 'secp521r1',

172172

};

173173174-

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+

};

276325277-

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+

};

287347288-

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+

}

320373321-

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-

}

336392337-

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

}

352395396+

const kSupportedAlgorithms = createSupportedAlgorithms(kAlgorithmDefinitions);

397+353398

const simpleAlgorithmDictionaries = {

354399

AeadParams: { iv: 'BufferSource', additionalData: 'BufferSource' },

355400

RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier' },