Skip to content

Commit fbf02e3

Browse files
panvatargos
authored andcommitted
util: add util.types.isKeyObject and util.types.isCryptoKey
closes #38611 PR-URL: #38619 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 36bb8da commit fbf02e3

File tree

6 files changed

+115
-4
lines changed

6 files changed

+115
-4
lines changed

doc/api/util.md

+20
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,16 @@ util.types.isBoxedPrimitive(Object(Symbol('foo'))); // Returns true
14831483
util.types.isBoxedPrimitive(Object(BigInt(5))); // Returns true
14841484
```
14851485

1486+
### `util.types.isCryptoKey(value)`
1487+
<!-- YAML
1488+
added: REPLACEME
1489+
-->
1490+
1491+
* `value` {Object}
1492+
* Returns: {boolean}
1493+
1494+
Returns `true` if `value` is a {CryptoKey}, `false` otherwise.
1495+
14861496
### `util.types.isDataView(value)`
14871497
<!-- YAML
14881498
added: v10.0.0
@@ -1678,6 +1688,16 @@ util.types.isInt32Array(new Int32Array()); // Returns true
16781688
util.types.isInt32Array(new Float64Array()); // Returns false
16791689
```
16801690

1691+
### `util.types.isKeyObject(value)`
1692+
<!-- YAML
1693+
added: REPLACEME
1694+
-->
1695+
1696+
* `value` {Object}
1697+
* Returns: {boolean}
1698+
1699+
Returns `true` if `value` is a {KeyObject}, `false` otherwise.
1700+
16811701
### `util.types.isMap(value)`
16821702
<!-- YAML
16831703
added: v10.0.0

lib/internal/crypto/keys.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -639,8 +639,8 @@ function createPrivateKey(key) {
639639
return new PrivateKeyObject(handle);
640640
}
641641

642-
function isKeyObject(key) {
643-
return key instanceof KeyObject;
642+
function isKeyObject(obj) {
643+
return obj != null && obj[kKeyType] !== undefined;
644644
}
645645

646646
// Our implementation of CryptoKey is a simple wrapper around a KeyObject

lib/internal/util/types.js

+37
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const {
44
ArrayBufferIsView,
5+
ObjectDefineProperties,
56
TypedArrayPrototypeGetSymbolToStringTag,
67
} = primordials;
78

@@ -69,3 +70,39 @@ module.exports = {
6970
isBigInt64Array,
7071
isBigUint64Array
7172
};
73+
74+
let isCryptoKey;
75+
let isKeyObject;
76+
77+
ObjectDefineProperties(module.exports, {
78+
isKeyObject: {
79+
configurable: false,
80+
enumerable: true,
81+
value(obj) {
82+
if (!process.versions.openssl) {
83+
return false;
84+
}
85+
86+
if (!isKeyObject) {
87+
({ isKeyObject } = require('internal/crypto/keys'));
88+
}
89+
90+
return isKeyObject(obj);
91+
}
92+
},
93+
isCryptoKey: {
94+
configurable: false,
95+
enumerable: true,
96+
value(obj) {
97+
if (!process.versions.openssl) {
98+
return false;
99+
}
100+
101+
if (!isCryptoKey) {
102+
({ isCryptoKey } = require('internal/crypto/keys'));
103+
}
104+
105+
return isCryptoKey(obj);
106+
}
107+
}
108+
});

test/parallel/test-crypto-key-objects.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ if (common.hasOpenSSL3)
88
common.skip('temporarily skipping for OpenSSL 3.0-alpha15');
99

1010
const assert = require('assert');
11+
const { types: { isKeyObject } } = require('util');
1112
const {
1213
createCipheriv,
1314
createDecipheriv,
@@ -23,7 +24,8 @@ const {
2324
privateDecrypt,
2425
privateEncrypt,
2526
getCurves,
26-
generateKeyPairSync
27+
generateKeyPairSync,
28+
webcrypto,
2729
} = require('crypto');
2830

2931
const fixtures = require('../common/fixtures');
@@ -774,3 +776,24 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem',
774776
message: `Unsupported JWK EC curve: ${namedCurve}.`
775777
});
776778
}
779+
780+
{
781+
const buffer = Buffer.from('Hello World');
782+
const keyObject = createSecretKey(buffer);
783+
const keyPair = generateKeyPairSync('ec', { namedCurve: 'P-256' });
784+
assert(isKeyObject(keyPair.publicKey));
785+
assert(isKeyObject(keyPair.privateKey));
786+
assert(isKeyObject(keyObject));
787+
788+
assert(!isKeyObject(buffer));
789+
790+
webcrypto.subtle.importKey(
791+
'node.keyObject',
792+
keyPair.publicKey,
793+
{ name: 'ECDH', namedCurve: 'P-256' },
794+
false,
795+
[],
796+
).then((cryptoKey) => {
797+
assert(!isKeyObject(cryptoKey));
798+
});
799+
}

test/parallel/test-util-types.js

+10
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,13 @@ for (const [ value, _method ] of [
281281
await m.evaluate();
282282
assert.ok(types.isModuleNamespaceObject(m.namespace));
283283
})().then(common.mustCall());
284+
285+
{
286+
// eslint-disable-next-line node-core/crypto-check
287+
if (common.hasCrypto) {
288+
const crypto = require('crypto');
289+
assert.ok(!types.isKeyObject(crypto.createHash('sha1')));
290+
}
291+
assert.ok(!types.isCryptoKey());
292+
assert.ok(!types.isKeyObject());
293+
}

test/parallel/test-webcrypto-keygen.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { subtle, CryptoKey } = require('crypto').webcrypto;
9+
const { types: { isCryptoKey } } = require('util');
10+
const {
11+
webcrypto: { subtle, CryptoKey },
12+
createSecretKey,
13+
} = require('crypto');
1014

1115
const allUsages = [
1216
'encrypt',
@@ -220,6 +224,8 @@ const vectors = {
220224

221225
assert(publicKey);
222226
assert(privateKey);
227+
assert(isCryptoKey(publicKey));
228+
assert(isCryptoKey(privateKey));
223229

224230
assert(publicKey instanceof CryptoKey);
225231
assert(privateKey instanceof CryptoKey);
@@ -366,6 +372,8 @@ const vectors = {
366372

367373
assert(publicKey);
368374
assert(privateKey);
375+
assert(isCryptoKey(publicKey));
376+
assert(isCryptoKey(privateKey));
369377

370378
assert.strictEqual(publicKey.type, 'public');
371379
assert.strictEqual(privateKey.type, 'private');
@@ -430,6 +438,7 @@ const vectors = {
430438
}, true, usages);
431439

432440
assert(key);
441+
assert(isCryptoKey(key));
433442

434443
assert.strictEqual(key.type, 'secret');
435444
assert.strictEqual(key.extractable, true);
@@ -488,6 +497,7 @@ const vectors = {
488497
}
489498

490499
assert(key);
500+
assert(isCryptoKey(key));
491501

492502
assert.strictEqual(key.type, 'secret');
493503
assert.strictEqual(key.extractable, true);
@@ -544,6 +554,8 @@ const vectors = {
544554

545555
assert(publicKey);
546556
assert(privateKey);
557+
assert(isCryptoKey(publicKey));
558+
assert(isCryptoKey(privateKey));
547559

548560
assert.strictEqual(publicKey.type, 'public');
549561
assert.strictEqual(privateKey.type, 'private');
@@ -634,6 +646,8 @@ const vectors = {
634646
}, true, ['deriveKey']);
635647
assert(publicKey);
636648
assert(privateKey);
649+
assert(isCryptoKey(publicKey));
650+
assert(isCryptoKey(privateKey));
637651
assert.strictEqual(publicKey.type, 'public');
638652
assert.strictEqual(privateKey.type, 'private');
639653
assert.strictEqual(publicKey.algorithm.name, 'NODE-DH');
@@ -646,3 +660,10 @@ const vectors = {
646660
assert.throws(() => new CryptoKey(), {
647661
code: 'ERR_OPERATION_FAILED'
648662
});
663+
664+
{
665+
const buffer = Buffer.from('Hello World');
666+
const keyObject = createSecretKey(buffer);
667+
assert(!isCryptoKey(buffer));
668+
assert(!isCryptoKey(keyObject));
669+
}

0 commit comments

Comments
 (0)