Commit 5af55e612c1 for nodejs
commit 5af55e612c1c0fb21def18aa5114c7d554668443
Author: Filip Skokan <panva.ip@gmail.com>
Date: Tue Sep 22 22:27:08 2026 +0200
crypto: minimize RSA public exponent metadata
Omit leading zero octets from generated CryptoKey publicExponent
values, matching the BigInteger representation.
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>
diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js
index 56c58bf1262..767c5e14507 100644
--- a/lib/internal/crypto/rsa.js
+++ b/lib/internal/crypto/rsa.js
@@ -2,6 +2,8 @@
const {
TypedArrayPrototypeGetBuffer,
+ TypedArrayPrototypeGetByteOffset,
+ TypedArrayPrototypeGetLength,
Uint8Array,
} = primordials;
@@ -113,11 +115,17 @@ function rsaKeyGenerate(
const usagesSet = validateKeyUsages(usages, allowedUsages.keygen, name);
validateAlgorithm(algorithm, 'generateKey');
const publicExponentConverted = bigIntArrayToUnsignedInt(publicExponent);
+ let firstNonzeroByte = 0;
+ while (publicExponent[firstNonzeroByte] === 0)
+ firstNonzeroByte++;
const keyAlgorithm = {
name,
modulusLength,
- publicExponent,
+ publicExponent: new Uint8Array(
+ TypedArrayPrototypeGetBuffer(publicExponent),
+ TypedArrayPrototypeGetByteOffset(publicExponent) + firstNonzeroByte,
+ TypedArrayPrototypeGetLength(publicExponent) - firstNonzeroByte),
hash,
};
diff --git a/test/parallel/test-webcrypto-rsa-exponent-length.js b/test/parallel/test-webcrypto-rsa-exponent-length.js
new file mode 100644
index 00000000000..c227154c7a1
--- /dev/null
+++ b/test/parallel/test-webcrypto-rsa-exponent-length.js
@@ -0,0 +1,26 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const assert = require('assert');
+const { getFips } = require('crypto');
+const { subtle } = globalThis.crypto;
+
+(async () => {
+ const exponents = getFips() ? [[1, 0, 1]] : [[3], [1, 0, 1]];
+ for (const name of ['RSA-PSS', 'RSASSA-PKCS1-v1_5', 'RSA-OAEP']) {
+ const usages = name === 'RSA-OAEP' ? ['encrypt', 'decrypt'] : ['sign', 'verify'];
+ for (const exponent of exponents) {
+ const publicExponent = new Uint8Array([0, 0, 0, 0, ...exponent]);
+ const pair = await subtle.generateKey({
+ name, modulusLength: 2048, publicExponent, hash: 'SHA-256',
+ }, true, usages);
+ for (const key of [pair.publicKey, pair.privateKey]) {
+ assert.deepStrictEqual(key.algorithm.publicExponent, new Uint8Array(exponent));
+ }
+ assert.deepStrictEqual(publicExponent, new Uint8Array([0, 0, 0, 0, ...exponent]));
+ }
+ }
+})().then(common.mustCall());