Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions benchmark/crypto/kem.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ if (Object.keys(keyFixtures).length === 0) {
}

const bench = common.createBenchmark(main, {
keyType: Object.keys(keyFixtures),
// Keep one size per family by default; other fixtures remain available via keyType.
keyType: ['rsa', 'p-256', 'x25519', 'ml-kem-768'].filter((type) => keyFixtures[type]),
mode: ['sync', 'async', 'async-parallel'],
keyFormat: ['keyObject', 'keyObject.unique', 'pem', 'der', 'jwk',
'raw-public', 'raw-private', 'raw-seed'],
Expand All @@ -57,6 +58,9 @@ const bench = common.createBenchmark(main, {
// assess whether mutexes over the key material impact the operation
if (p.keyFormat === 'keyObject.unique')
return p.mode === 'async-parallel';
// Compare execution modes with pre-imported keys; measure parsing synchronously.
if (p.mode !== 'sync' && p.keyFormat !== 'keyObject')
return false;
// raw-public is only supported for encapsulate, not rsa
if (p.keyFormat === 'raw-public')
return p.keyType !== 'rsa' && p.op === 'encapsulate';
Expand Down Expand Up @@ -127,7 +131,8 @@ function main({ n, mode, keyFormat, keyType, op }) {
keyFixtures[keyType].publicKey :
keyFixtures[keyType].privateKey;
const createKeyFn = isEncapsulate ? crypto.createPublicKey : crypto.createPrivateKey;
const pems = [...Buffer.alloc(n)].map(() => pemSource);
const count = keyFormat === 'keyObject.unique' ? n : 1;
const pems = Array(count).fill(pemSource);
const keyObjects = pems.map(createKeyFn);

// Warm up OpenSSL's provider operation cache for each key object
Expand Down
79 changes: 79 additions & 0 deletions benchmark/crypto/keyobject-serialization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';

const common = require('../common.js');
const { hasOpenSSL, hasFIPS, isBoringSSL } = require('../../test/common/crypto.js');
const fixtures = require('../../test/common/fixtures.js');
const { createPrivateKey, createPublicKey } = require('crypto');

const keys = {
'rsa': 'rsa_private_2048',
'rsa-pss': 'rsa_pss_private_2048',
'p-256': 'ec_p256_private',
'p-384': 'ec_p384_private',
'p-521': 'ec_p521_private',
'ed25519': 'ed25519_private',
'x25519': 'x25519_private',
};
if (!isBoringSSL) {
keys.ed448 = 'ed448_private';
keys.x448 = 'x448_private';
if (!hasFIPS()) keys['rsa-multiprime'] = 'rsa_private_2048_3_primes';
}
if (hasOpenSSL(3, 5) || isBoringSSL) {
keys['ml-dsa-44'] = 'ml_dsa_44_private_seed_only';
keys['ml-dsa-87'] = 'ml_dsa_87_private_seed_only';
keys['ml-kem-768'] = 'ml_kem_768_private_seed_only';
keys['ml-kem-1024'] = 'ml_kem_1024_private_seed_only';
}
if (hasOpenSSL(3, 5)) {
keys['slh-dsa-sha2-128s'] = 'slh_dsa_sha2_128s_private';
keys['slh-dsa-shake-256s'] = 'slh_dsa_shake_256s_private';
}

const bench = common.createBenchmark(main, {
// Keep one size per family by default; other fixtures remain available via keyType.
keyType: ['rsa', 'rsa-pss', 'p-256', 'ed25519', 'x25519',
'ml-dsa-44', 'ml-kem-768', 'slh-dsa-sha2-128s'].filter((type) => keys[type]),
operation: ['import', 'export'],
// PEM can be selected with format=pem; DER covers ASN.1 encoding by default.
format: ['jwk', 'der', 'raw-public', 'raw-private', 'raw-seed'],
type: ['public', 'private'],
n: [1e4],
}, {
combinationFilter({ keyType, format, type }) {
if (format === 'jwk') return keyType !== 'rsa-pss';
if (!format.startsWith('raw-')) return true;
if (keyType.startsWith('rsa')) return false;
if (format === 'raw-public') return type === 'public';
if (format === 'raw-private') return type === 'private' && !keyType.startsWith('ml-');
return type === 'private' && keyType.startsWith('ml-');
},
});

function main({ keyType, operation, format, type, n }) {
const privateKey = createPrivateKey(fixtures.readKey(`${keys[keyType]}.pem`));
const key = type === 'private' ? privateKey : createPublicKey(privateKey);
const options = { format };
if (format === 'pem' || format === 'der') {
options.type = type === 'private' ? 'pkcs8' : 'spki';
}
let run;
if (operation === 'export') {
run = () => key.export(options);
} else {
const input = { ...options, key: key.export(options) };
if (format.startsWith('raw-')) {
input.asymmetricKeyType = key.asymmetricKeyType;
if (input.asymmetricKeyType === 'ec') {
input.namedCurve = key.asymmetricKeyDetails.namedCurve;
}
}
const importKey = type === 'private' ? createPrivateKey : createPublicKey;
run = () => importKey(input);
}
// Resolve provider operations and warm the JS path before timing.
for (let i = 0; i < 100; i++) run();
bench.start();
for (let i = 0; i < n; i++) run();
bench.end(n);
}
11 changes: 6 additions & 5 deletions benchmark/crypto/oneshot-sign.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ if (hasOpenSSL(3, 5)) {

const data = crypto.randomBytes(256);

let pems;
let keyObjects;

const bench = common.createBenchmark(main, {
keyType: Object.keys(keyFixtures),
mode: ['sync', 'async', 'async-parallel'],
Expand All @@ -39,6 +36,9 @@ const bench = common.createBenchmark(main, {
// assess whether mutexes over the key material impact the operation
if (p.keyFormat === 'keyObject.unique')
return p.mode === 'async-parallel';
// Compare execution modes with pre-imported keys; measure parsing synchronously.
if (p.mode !== 'sync' && p.keyFormat !== 'keyObject')
return false;
// raw-private is not supported for rsa and ml-dsa
if (p.keyFormat === 'raw-private')
return p.keyType !== 'rsa' && !p.keyType.startsWith('ml-');
Expand Down Expand Up @@ -97,8 +97,9 @@ function measureAsyncParallel(n, digest, privateKey, keys) {
}

function main({ n, mode, keyFormat, keyType }) {
pems ||= [...Buffer.alloc(n)].map(() => keyFixtures[keyType]);
keyObjects ||= pems.map(crypto.createPrivateKey);
const count = keyFormat === 'keyObject.unique' ? n : 1;
const pems = Array(count).fill(keyFixtures[keyType]);
const keyObjects = pems.map(crypto.createPrivateKey);

// Warm up OpenSSL's provider operation cache for each key object
for (const keyObject of keyObjects) {
Expand Down
11 changes: 6 additions & 5 deletions benchmark/crypto/oneshot-verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ if (hasOpenSSL(3, 5)) {

const data = crypto.randomBytes(256);

let pems;
let keyObjects;

const bench = common.createBenchmark(main, {
keyType: Object.keys(keyFixtures),
mode: ['sync', 'async', 'async-parallel'],
Expand All @@ -46,6 +43,9 @@ const bench = common.createBenchmark(main, {
// assess whether mutexes over the key material impact the operation
if (p.keyFormat === 'keyObject.unique')
return p.mode === 'async-parallel';
// Compare execution modes with pre-imported keys; measure parsing synchronously.
if (p.mode !== 'sync' && p.keyFormat !== 'keyObject')
return false;
// raw-public is not supported by rsa
if (p.keyFormat === 'raw-public')
return p.keyType !== 'rsa';
Expand Down Expand Up @@ -104,8 +104,9 @@ function measureAsyncParallel(n, digest, signature, publicKey, keys) {
}

function main({ n, mode, keyFormat, keyType }) {
pems ||= [...Buffer.alloc(n)].map(() => keyFixtures[keyType].publicKey);
keyObjects ||= pems.map(crypto.createPublicKey);
const count = keyFormat === 'keyObject.unique' ? n : 1;
const pems = Array(count).fill(keyFixtures[keyType].publicKey);
const keyObjects = pems.map(crypto.createPublicKey);

// Warm up OpenSSL's provider operation cache for each key object
const warmupDigest = keyType === 'rsa' || keyType === 'ec' ? 'sha256' : null;
Expand Down
Loading
Loading