node/lib/internal/crypto/kem.js
Filip Skokan f8d68d30ae
crypto: support ML-KEM, DHKEM, and RSASVE key encapsulation mechanisms
PR-URL: https://github.com/nodejs/node/pull/59491
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2025-08-20 14:30:58 +00:00

113 lines
2.3 KiB
JavaScript

'use strict';
const {
FunctionPrototypeCall,
} = primordials;
const {
codes: {
ERR_CRYPTO_KEM_NOT_SUPPORTED,
},
} = require('internal/errors');
const {
validateFunction,
} = require('internal/validators');
const {
kCryptoJobAsync,
kCryptoJobSync,
KEMDecapsulateJob,
KEMEncapsulateJob,
} = internalBinding('crypto');
const {
preparePrivateKey,
preparePublicOrPrivateKey,
} = require('internal/crypto/keys');
const {
getArrayBufferOrView,
} = require('internal/crypto/util');
function encapsulate(key, callback) {
if (!KEMEncapsulateJob)
throw new ERR_CRYPTO_KEM_NOT_SUPPORTED();
if (callback !== undefined)
validateFunction(callback, 'callback');
const {
data: keyData,
format: keyFormat,
type: keyType,
passphrase: keyPassphrase,
} = preparePublicOrPrivateKey(key);
const job = new KEMEncapsulateJob(
callback ? kCryptoJobAsync : kCryptoJobSync,
keyData,
keyFormat,
keyType,
keyPassphrase);
if (!callback) {
const { 0: err, 1: result } = job.run();
if (err !== undefined)
throw err;
const { 0: sharedKey, 1: ciphertext } = result;
return { sharedKey, ciphertext };
}
job.ondone = (error, result) => {
if (error) return FunctionPrototypeCall(callback, job, error);
const { 0: sharedKey, 1: ciphertext } = result;
FunctionPrototypeCall(callback, job, null, { sharedKey, ciphertext });
};
job.run();
}
function decapsulate(key, ciphertext, callback) {
if (!KEMDecapsulateJob)
throw new ERR_CRYPTO_KEM_NOT_SUPPORTED();
if (callback !== undefined)
validateFunction(callback, 'callback');
const {
data: keyData,
format: keyFormat,
type: keyType,
passphrase: keyPassphrase,
} = preparePrivateKey(key);
ciphertext = getArrayBufferOrView(ciphertext, 'ciphertext');
const job = new KEMDecapsulateJob(
callback ? kCryptoJobAsync : kCryptoJobSync,
keyData,
keyFormat,
keyType,
keyPassphrase,
ciphertext);
if (!callback) {
const { 0: err, 1: result } = job.run();
if (err !== undefined)
throw err;
return result;
}
job.ondone = (error, result) => {
if (error) return FunctionPrototypeCall(callback, job, error);
FunctionPrototypeCall(callback, job, null, result);
};
job.run();
}
module.exports = {
encapsulate,
decapsulate,
};