Skip to content

Commit

Permalink
util: add util.types.isKeyObject and util.types.isCryptoKey
Browse files Browse the repository at this point in the history
closes #38611
  • Loading branch information
panva committed May 14, 2021
1 parent aefc621 commit dec5d19
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 4 deletions.
20 changes: 20 additions & 0 deletions doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions lib/internal/util/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const {
ArrayBufferIsView,
ObjectDefineProperties,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials;

Expand Down Expand Up @@ -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);
}
}
});
25 changes: 24 additions & 1 deletion test/parallel/test-crypto-key-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -23,7 +24,8 @@ const {
privateDecrypt,
privateEncrypt,
getCurves,
generateKeyPairSync
generateKeyPairSync,
webcrypto,
} = require('crypto');

const fixtures = require('../common/fixtures');
Expand Down Expand Up @@ -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));
});
}
10 changes: 10 additions & 0 deletions test/parallel/test-util-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
23 changes: 22 additions & 1 deletion test/parallel/test-webcrypto-keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -220,6 +224,8 @@ const vectors = {

assert(publicKey);
assert(privateKey);
assert(isCryptoKey(publicKey));
assert(isCryptoKey(privateKey));

assert(publicKey instanceof CryptoKey);
assert(privateKey instanceof CryptoKey);
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -430,6 +438,7 @@ const vectors = {
}, true, usages);

assert(key);
assert(isCryptoKey(key));

assert.strictEqual(key.type, 'secret');
assert.strictEqual(key.extractable, true);
Expand Down Expand Up @@ -488,6 +497,7 @@ const vectors = {
}

assert(key);
assert(isCryptoKey(key));

assert.strictEqual(key.type, 'secret');
assert.strictEqual(key.extractable, true);
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand All @@ -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));
}

0 comments on commit dec5d19

Please sign in to comment.