mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
crypto: report actual RSA modulus lengths
Use the generated key's modulus size for both CryptoKey algorithm objects. Preserve successful backend generation when it rounds the requested size, keeping metadata consistent across export and cloning. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/66237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
This commit is contained in:
1 parent
cf36e304e3
commit
618f793464
2 files changed
+56
-2
No files matched your search
@@ -32,6 +32,7 @@ const {
|
||||
bigIntArrayToUnsignedInt,
|
||||
getUsagesMask,
|
||||
jobPromise,
|
||||
jobPromiseThen,
|
||||
normalizeHashName,
|
||||
validateAlgorithm,
|
||||
validateMaxBufferLength,
|
||||
@@ -132,7 +133,7 @@ function rsaKeyGenerate(
|
||||
const keyUsages = getKeyPairUsages(usagesSet, allowedUsages);
|
||||
validateUsagesNotEmpty(keyUsages.private);
|
||||
|
||||
return jobPromise(() => new RsaKeyPairGenJob(
|
||||
return jobPromiseThen(jobPromise(() => new RsaKeyPairGenJob(
|
||||
kCryptoJobWebCrypto,
|
||||
kKeyVariantRSA_SSA_PKCS1_v1_5,
|
||||
modulusLength,
|
||||
@@ -140,7 +141,13 @@ function rsaKeyGenerate(
|
||||
keyAlgorithm,
|
||||
getUsagesMask(keyUsages.public),
|
||||
getUsagesMask(keyUsages.private),
|
||||
extractable));
|
||||
extractable)), (result) => {
|
||||
const { modulusLength: actualModulusLength } =
|
||||
getCryptoKeyHandle(result.publicKey).keyDetail({ __proto__: null });
|
||||
getCryptoKeyAlgorithm(result.publicKey).modulusLength = actualModulusLength;
|
||||
getCryptoKeyAlgorithm(result.privateKey).modulusLength = actualModulusLength;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function rsaExportKey(key, format) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { generateKeyPairSync, KeyObject } = require('crypto');
|
||||
const { subtle } = globalThis.crypto;
|
||||
|
||||
(async () => {
|
||||
for (const name of ['RSA-PSS', 'RSASSA-PKCS1-v1_5', 'RSA-OAEP']) {
|
||||
const usages = name === 'RSA-OAEP' ? ['encrypt', 'decrypt'] : ['sign', 'verify'];
|
||||
for (const modulusLength of [1025, 2048, 2049]) {
|
||||
let pair;
|
||||
try {
|
||||
pair = await subtle.generateKey({
|
||||
name, modulusLength, hash: 'SHA-256', publicExponent: new Uint8Array([1, 0, 1]),
|
||||
}, true, usages);
|
||||
} catch (err) {
|
||||
if (modulusLength === 2048 || err.name !== 'OperationError')
|
||||
throw err;
|
||||
// Only reject sizes the backend also rejects. Some backends round
|
||||
// the requested size, which must still produce a usable CryptoKey.
|
||||
assert.throws(() => generateKeyPairSync('rsa', { modulusLength }),
|
||||
{ name: 'Error' });
|
||||
continue;
|
||||
}
|
||||
const actualModulusLength =
|
||||
KeyObject.from(pair.publicKey).asymmetricKeyDetails.modulusLength;
|
||||
for (const key of [pair.publicKey, pair.privateKey]) {
|
||||
assert.strictEqual(key.algorithm.modulusLength, actualModulusLength);
|
||||
assert.strictEqual(
|
||||
KeyObject.from(key).asymmetricKeyDetails.modulusLength, actualModulusLength);
|
||||
assert.deepStrictEqual(structuredClone(key).algorithm, key.algorithm);
|
||||
|
||||
const format = key.type === 'public' ? 'spki' : 'pkcs8';
|
||||
const imported = await subtle.importKey(
|
||||
format, await subtle.exportKey(format, key),
|
||||
{ name, hash: 'SHA-256' }, true, key.usages);
|
||||
assert.deepStrictEqual(imported.algorithm, key.algorithm);
|
||||
}
|
||||
const publicKey = await subtle.getPublicKey(pair.privateKey, pair.publicKey.usages);
|
||||
assert.deepStrictEqual(publicKey.algorithm, pair.publicKey.algorithm);
|
||||
}
|
||||
}
|
||||
})().then(common.mustCall());
|
||||
Reference in new issue
Block a user