Skip to content

Commit 7f58476

Browse files
panvaaduh95
authored andcommitted
crypto: use the public CryptoKey prototype
Give generated, imported, converted, and transferred keys the public interface prototype directly, without an intermediate internal object. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: #66237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
1 parent 7587062 commit 7f58476

3 files changed

Lines changed: 35 additions & 10 deletions

File tree

‎lib/internal/crypto/keys.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,10 +1167,9 @@ function getKeyObjectAsymmetricKeyDetails(key) {
11671167
// KEM-only seed data) lives
11681168
// on a C++ class, NativeCryptoKey, created by createCryptoKeyClass.
11691169
// InternalCryptoKey is the only constructor we expose to internal
1170-
// code; it extends NativeCryptoKey to get that storage and then has
1171-
// its prototype spliced so the chain visible to user code is:
1172-
// instance -> InternalCryptoKey.prototype
1173-
// -> CryptoKey.prototype
1170+
// code; it extends NativeCryptoKey to get that storage and gives each
1171+
// instance the public interface prototype:
1172+
// instance -> CryptoKey.prototype
11741173
// -> Object.prototype
11751174
//
11761175
// Normal construction caches all native internal slots in a private class
@@ -1313,6 +1312,7 @@ const {
13131312
extractable,
13141313
secondaryHandle,
13151314
seedData);
1315+
ObjectSetPrototypeOf(this, CryptoKey.prototype);
13161316
if (algorithm !== undefined) {
13171317
this.#slots = [
13181318
handle.getKeyType(),

‎test/parallel/test-webcrypto-cryptokey-brand-check.js‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ const { subtle } = globalThis.crypto;
3838
}
3939
assert.strictEqual(isCryptoKey(key), true);
4040
assert.strictEqual(Object.hasOwn(CryptoKey, 'getSlots'), false);
41-
const internalProto = Object.getPrototypeOf(key);
42-
assert.strictEqual(Object.hasOwn(internalProto, 'getSlots'), false);
43-
assert.strictEqual('getSlots' in internalProto, false);
44-
assert.strictEqual(internalProto.constructor, CryptoKey);
45-
assert.strictEqual(Object.getPrototypeOf(internalProto), CryptoKey.prototype);
41+
const keyPrototype = Object.getPrototypeOf(key);
42+
assert.strictEqual(Object.hasOwn(keyPrototype, 'getSlots'), false);
43+
assert.strictEqual('getSlots' in keyPrototype, false);
44+
assert.strictEqual(keyPrototype.constructor, CryptoKey);
45+
assert.strictEqual(keyPrototype, CryptoKey.prototype);
4646

4747
const invalidThis = { code: 'ERR_INVALID_THIS', name: 'TypeError' };
4848
const invalidArgType = { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' };
@@ -93,7 +93,7 @@ const { subtle } = globalThis.crypto;
9393
await assertInvalidReceiver(receiver);
9494
}
9595

96-
// Prototype spoofing with InternalCryptoKey.prototype must not pass
96+
// Prototype spoofing with CryptoKey.prototype must not pass
9797
// util.types.isCryptoKey().
9898
const spoofed = {};
9999
Object.setPrototypeOf(spoofed, Object.getPrototypeOf(key));
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
const assert = require('assert');
8+
const { createSecretKey } = require('crypto');
9+
const { subtle } = globalThis.crypto;
10+
11+
function check(key) {
12+
assert.strictEqual(Object.getPrototypeOf(key), CryptoKey.prototype);
13+
assert.strictEqual(Object.getPrototypeOf(structuredClone(key)), CryptoKey.prototype);
14+
assert(key instanceof CryptoKey);
15+
}
16+
17+
(async () => {
18+
check(await subtle.generateKey({ name: 'AES-GCM', length: 128 }, true, ['encrypt']));
19+
check(await subtle.importKey('raw', new Uint8Array(16), 'AES-GCM', true, ['encrypt']));
20+
const pair = await subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' },
21+
true, ['sign', 'verify']);
22+
check(pair.publicKey);
23+
check(pair.privateKey);
24+
check(createSecretKey(new Uint8Array(16)).toCryptoKey('AES-GCM', true, ['encrypt']));
25+
})().then(common.mustCall());

0 commit comments

Comments
 (0)