crypto: return cached copies from CryptoKey algorithm and usages getters

Fixes: https://github.com/nodejs/node/issues/59534
PR-URL: https://github.com/nodejs/node/pull/59538
Fixes: https://github.com/nodejs/node/issues/59535
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
This commit is contained in:
Filip Skokan 2025-08-19 14:02:53 +02:00 committed by Node.js GitHub Bot
parent 9d744b5b63
commit d30090b427
2 changed files with 32 additions and 2 deletions

View File

@ -1,6 +1,7 @@
'use strict';
const {
ArrayFrom,
ArrayPrototypeSlice,
ObjectDefineProperties,
ObjectDefineProperty,
@ -81,6 +82,8 @@ const kAlgorithm = Symbol('kAlgorithm');
const kExtractable = Symbol('kExtractable');
const kKeyType = Symbol('kKeyType');
const kKeyUsages = Symbol('kKeyUsages');
const kCachedAlgorithm = Symbol('kCachedAlgorithm');
const kCachedKeyUsages = Symbol('kCachedKeyUsages');
// Key input contexts.
const kConsumePublic = 0;
@ -835,13 +838,19 @@ class CryptoKey {
get algorithm() {
if (!(this instanceof CryptoKey))
throw new ERR_INVALID_THIS('CryptoKey');
return this[kAlgorithm];
if (!this[kCachedAlgorithm]) {
this[kCachedAlgorithm] ??= { ...this[kAlgorithm] };
this[kCachedAlgorithm].hash &&= { ...this[kCachedAlgorithm].hash };
this[kCachedAlgorithm].publicExponent &&= new Uint8Array(this[kCachedAlgorithm].publicExponent);
}
return this[kCachedAlgorithm];
}
get usages() {
if (!(this instanceof CryptoKey))
throw new ERR_INVALID_THIS('CryptoKey');
return this[kKeyUsages];
this[kCachedKeyUsages] ??= ArrayFrom(this[kKeyUsages]);
return this[kCachedKeyUsages];
}
}

View File

@ -0,0 +1,21 @@
import * as common from '../common/index.mjs';
if (!common.hasCrypto)
common.skip('missing crypto');
import * as assert from 'node:assert';
import * as util from 'node:util';
const { subtle } = globalThis.crypto;
const kp = await subtle.generateKey('Ed25519', true, ['sign', 'verify']);
assert.notStrictEqual(kp.publicKey.algorithm, kp.privateKey.algorithm);
assert.notStrictEqual(kp.publicKey.usages, kp.privateKey.usages);
kp.publicKey.algorithm.name = 'ed25519';
assert.strictEqual(kp.publicKey.algorithm.name, 'ed25519');
kp.publicKey.usages.push('foo');
assert.ok(kp.publicKey.usages.includes('foo'));
assert.ok(util.inspect(kp.publicKey).includes("algorithm: { name: 'Ed25519' }"));
assert.ok(util.inspect(kp.publicKey).includes("usages: [ 'verify' ]"));
await subtle.sign('Ed25519', kp.privateKey, Buffer.alloc(32));