util: add util.types.isKeyObject and util.types.isCryptoKey

closes #38611

PR-URL: https://github.com/nodejs/node/pull/38619
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
This commit is contained in:
Filip Skokan
2021-05-10 12:33:11 +02:00
parent 2130598e91
commit 3ee1f9a29a
6 changed files with 115 additions and 4 deletions

View File

@@ -1485,6 +1485,16 @@ util.types.isBoxedPrimitive(Object(Symbol('foo'))); // Returns true
util.types.isBoxedPrimitive(Object(BigInt(5))); // Returns true
```
### `util.types.isCryptoKey(value)`
<!-- YAML
added: REPLACEME
-->
* `value` {Object}
* Returns: {boolean}
Returns `true` if `value` is a {CryptoKey}, `false` otherwise.
### `util.types.isDataView(value)`
<!-- YAML
added: v10.0.0
@@ -1680,6 +1690,16 @@ util.types.isInt32Array(new Int32Array()); // Returns true
util.types.isInt32Array(new Float64Array()); // Returns false
```
### `util.types.isKeyObject(value)`
<!-- YAML
added: REPLACEME
-->
* `value` {Object}
* Returns: {boolean}
Returns `true` if `value` is a {KeyObject}, `false` otherwise.
### `util.types.isMap(value)`
<!-- YAML
added: v10.0.0

View File

@@ -639,8 +639,8 @@ function createPrivateKey(key) {
return new PrivateKeyObject(handle);
}
function isKeyObject(key) {
return key instanceof KeyObject;
function isKeyObject(obj) {
return obj != null && obj[kKeyType] !== undefined;
}
// Our implementation of CryptoKey is a simple wrapper around a KeyObject

View File

@@ -2,6 +2,7 @@
const {
ArrayBufferIsView,
ObjectDefineProperties,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials;
@@ -69,3 +70,39 @@ module.exports = {
isBigInt64Array,
isBigUint64Array
};
let isCryptoKey;
let isKeyObject;
ObjectDefineProperties(module.exports, {
isKeyObject: {
configurable: false,
enumerable: true,
value(obj) {
if (!process.versions.openssl) {
return false;
}
if (!isKeyObject) {
({ isKeyObject } = require('internal/crypto/keys'));
}
return isKeyObject(obj);
}
},
isCryptoKey: {
configurable: false,
enumerable: true,
value(obj) {
if (!process.versions.openssl) {
return false;
}
if (!isCryptoKey) {
({ isCryptoKey } = require('internal/crypto/keys'));
}
return isCryptoKey(obj);
}
}
});

View File

@@ -8,6 +8,7 @@ if (common.hasOpenSSL3)
common.skip('temporarily skipping for OpenSSL 3.0-alpha15');
const assert = require('assert');
const { types: { isKeyObject } } = require('util');
const {
createCipheriv,
createDecipheriv,
@@ -23,7 +24,8 @@ const {
privateDecrypt,
privateEncrypt,
getCurves,
generateKeyPairSync
generateKeyPairSync,
webcrypto,
} = require('crypto');
const fixtures = require('../common/fixtures');
@@ -774,3 +776,24 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem',
message: `Unsupported JWK EC curve: ${namedCurve}.`
});
}
{
const buffer = Buffer.from('Hello World');
const keyObject = createSecretKey(buffer);
const keyPair = generateKeyPairSync('ec', { namedCurve: 'P-256' });
assert(isKeyObject(keyPair.publicKey));
assert(isKeyObject(keyPair.privateKey));
assert(isKeyObject(keyObject));
assert(!isKeyObject(buffer));
webcrypto.subtle.importKey(
'node.keyObject',
keyPair.publicKey,
{ name: 'ECDH', namedCurve: 'P-256' },
false,
[],
).then((cryptoKey) => {
assert(!isKeyObject(cryptoKey));
});
}

View File

@@ -281,3 +281,13 @@ for (const [ value, _method ] of [
await m.evaluate();
assert.ok(types.isModuleNamespaceObject(m.namespace));
})().then(common.mustCall());
{
// eslint-disable-next-line node-core/crypto-check
if (common.hasCrypto) {
const crypto = require('crypto');
assert.ok(!types.isKeyObject(crypto.createHash('sha1')));
}
assert.ok(!types.isCryptoKey());
assert.ok(!types.isKeyObject());
}

View File

@@ -6,7 +6,11 @@ if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const { subtle, CryptoKey } = require('crypto').webcrypto;
const { types: { isCryptoKey } } = require('util');
const {
webcrypto: { subtle, CryptoKey },
createSecretKey,
} = require('crypto');
const allUsages = [
'encrypt',
@@ -220,6 +224,8 @@ const vectors = {
assert(publicKey);
assert(privateKey);
assert(isCryptoKey(publicKey));
assert(isCryptoKey(privateKey));
assert(publicKey instanceof CryptoKey);
assert(privateKey instanceof CryptoKey);
@@ -366,6 +372,8 @@ const vectors = {
assert(publicKey);
assert(privateKey);
assert(isCryptoKey(publicKey));
assert(isCryptoKey(privateKey));
assert.strictEqual(publicKey.type, 'public');
assert.strictEqual(privateKey.type, 'private');
@@ -430,6 +438,7 @@ const vectors = {
}, true, usages);
assert(key);
assert(isCryptoKey(key));
assert.strictEqual(key.type, 'secret');
assert.strictEqual(key.extractable, true);
@@ -488,6 +497,7 @@ const vectors = {
}
assert(key);
assert(isCryptoKey(key));
assert.strictEqual(key.type, 'secret');
assert.strictEqual(key.extractable, true);
@@ -544,6 +554,8 @@ const vectors = {
assert(publicKey);
assert(privateKey);
assert(isCryptoKey(publicKey));
assert(isCryptoKey(privateKey));
assert.strictEqual(publicKey.type, 'public');
assert.strictEqual(privateKey.type, 'private');
@@ -634,6 +646,8 @@ const vectors = {
}, true, ['deriveKey']);
assert(publicKey);
assert(privateKey);
assert(isCryptoKey(publicKey));
assert(isCryptoKey(privateKey));
assert.strictEqual(publicKey.type, 'public');
assert.strictEqual(privateKey.type, 'private');
assert.strictEqual(publicKey.algorithm.name, 'NODE-DH');
@@ -646,3 +660,10 @@ const vectors = {
assert.throws(() => new CryptoKey(), {
code: 'ERR_OPERATION_FAILED'
});
{
const buffer = Buffer.from('Hello World');
const keyObject = createSecretKey(buffer);
assert(!isCryptoKey(buffer));
assert(!isCryptoKey(keyObject));
}