Skip to content

Commit ead1caa

Browse files
committed
crypto: handle invalid prepareAsymmetricKey JWK inputs
Fixes #44471
1 parent 8524793 commit ead1caa

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

lib/internal/crypto/keygen.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const {
3131
SecretKeyObject,
3232
parsePublicKeyEncoding,
3333
parsePrivateKeyEncoding,
34-
isJwk
3534
} = require('internal/crypto/keys');
3635

3736
const {
@@ -66,6 +65,10 @@ const { isArrayBufferView } = require('internal/util/types');
6665

6766
const { getOptionValue } = require('internal/options');
6867

68+
function isJwk(obj) {
69+
return obj != null && obj.kty !== undefined;
70+
}
71+
6972
function wrapKey(key, ctor) {
7073
if (typeof key === 'string' ||
7174
isArrayBufferView(key) ||

lib/internal/crypto/keys.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -525,14 +525,19 @@ function prepareAsymmetricKey(key, ctx) {
525525
return { format: kKeyFormatPEM, data: getArrayBufferOrView(key, 'key') };
526526
} else if (typeof key === 'object') {
527527
const { key: data, encoding, format } = key;
528+
528529
// The 'key' property can be a KeyObject as well to allow specifying
529530
// additional options such as padding along with the key.
530531
if (isKeyObject(data))
531532
return { data: getKeyObjectHandle(data, ctx) };
532533
else if (isCryptoKey(data))
533534
return { data: getKeyObjectHandle(data[kKeyObject], ctx) };
534-
else if (isJwk(data) && format === 'jwk')
535+
else if (format === 'jwk') {
536+
validateObject(data, 'key.key');
537+
validateString(data.kty, 'key.key.kty');
535538
return { data: getKeyObjectHandleFromJwk(data, ctx), format: 'jwk' };
539+
}
540+
536541
// Either PEM or DER using PKCS#1 or SPKI.
537542
if (!isStringOrBuffer(data)) {
538543
throw new ERR_INVALID_ARG_TYPE(
@@ -720,10 +725,6 @@ function isCryptoKey(obj) {
720725
return obj != null && obj[kKeyObject] !== undefined;
721726
}
722727

723-
function isJwk(obj) {
724-
return obj != null && obj.kty !== undefined;
725-
}
726-
727728
module.exports = {
728729
// Public API.
729730
createSecretKey,
@@ -745,5 +746,4 @@ module.exports = {
745746
PrivateKeyObject,
746747
isKeyObject,
747748
isCryptoKey,
748-
isJwk,
749749
};

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,3 +868,23 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem',
868868
assert(!first.equals(third));
869869
assert(!third.equals(first));
870870
}
871+
872+
{
873+
// This should not cause a crash: https://github.com/nodejs/node/issues/44471
874+
for (const key of ['', 'foo', null, undefined, true, Boolean]) {
875+
assert.throws(() => {
876+
createPublicKey({ key, format: 'jwk' });
877+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
878+
assert.throws(() => {
879+
createPrivateKey({ key, format: 'jwk' });
880+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
881+
}
882+
for (const kty of [null, undefined, true, Boolean]) {
883+
assert.throws(() => {
884+
createPublicKey({ key: { kty }, format: 'jwk' });
885+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key\.kty" property must be of type string/ });
886+
assert.throws(() => {
887+
createPrivateKey({ key: { kty }, format: 'jwk' });
888+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key\.kty" property must be of type string/ });
889+
}
890+
}

test/parallel/test-crypto-sign-verify.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,3 +756,21 @@ assert.throws(
756756
message: /digest too big for rsa key/
757757
});
758758
}
759+
760+
{
761+
// This should not cause a crash: https://github.com/nodejs/node/issues/44471
762+
for (const key of ['', 'foo', null, undefined, true, Boolean]) {
763+
assert.throws(() => {
764+
crypto.verify('sha256', 'foo', { key, format: 'jwk' }, Buffer.alloc(0));
765+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
766+
assert.throws(() => {
767+
crypto.createVerify('sha256').verify({ key, format: 'jwk' }, Buffer.alloc(0));
768+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
769+
assert.throws(() => {
770+
crypto.sign('sha256', 'foo', { key, format: 'jwk' });
771+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
772+
assert.throws(() => {
773+
crypto.createSign('sha256').sign({ key, format: 'jwk' });
774+
}, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ });
775+
}
776+
}

0 commit comments

Comments
 (0)