diff --git a/lib/help/asn1/rsa_private_key.js b/lib/help/asn1/rsa_private_key.js index ac3cc2b375..acd4f7575c 100644 --- a/lib/help/asn1/rsa_private_key.js +++ b/lib/help/asn1/rsa_private_key.js @@ -1,6 +1,6 @@ module.exports = function () { this.seq().obj( - this.key('version').int(), + this.key('version').int({ 0: 'two-prime', 1: 'multi' }), this.key('n').int(), this.key('e').int(), this.key('d').int(), diff --git a/lib/help/key_utils.js b/lib/help/key_utils.js index 3494127235..81328c6f8d 100644 --- a/lib/help/key_utils.js +++ b/lib/help/key_utils.js @@ -59,7 +59,11 @@ const keyObjectToJWK = { const RSAPrivateKey = asn1.get('RSAPrivateKey') const { privateKey } = PrivateKeyInfo.decode(der) - const { n, e, d, p, q, dp, dq, qi } = RSAPrivateKey.decode(privateKey) + const { version, n, e, d, p, q, dp, dq, qi } = RSAPrivateKey.decode(privateKey) + + if (version !== 'two-prime') { + throw new errors.JOSENotSupported('Private RSA keys with more than two primes are not supported') + } return { kty: 'RSA', @@ -186,6 +190,16 @@ const jwkToPem = { private (jwk) { const RSAPrivateKey = asn1.get('RSAPrivateKey') + if ('oth' in jwk) { + throw new errors.JOSENotSupported('Private RSA keys with more than two primes are not supported') + } + + if (jwk.p || jwk.q || jwk.dp || jwk.dq || jwk.qi) { + if (!(jwk.p && jwk.q && jwk.dp && jwk.dq && jwk.qi)) { + throw new errors.JWKImportFailed('all other private key parameters must be present when any one of them is present') + } + } + return RSAPrivateKey.encode({ version: 0, n: base64url.decodeToBuffer(jwk.n), diff --git a/lib/jwk/import.js b/lib/jwk/import.js index 7b1583c23e..dc42677e36 100644 --- a/lib/jwk/import.js +++ b/lib/jwk/import.js @@ -52,7 +52,11 @@ const importKey = (key, parameters) => { let pem try { pem = jwkToPem(key) - } catch (err) {} + } catch (err) { + if (err instanceof errors.JOSEError) { + throw err + } + } if (pem && key.d) { privateKey = createPrivateKey(pem) } else if (pem) { diff --git a/test/jwk/import.test.js b/test/jwk/import.test.js index ce01ff6b73..536ff3dab5 100644 --- a/test/jwk/import.test.js +++ b/test/jwk/import.test.js @@ -1,7 +1,7 @@ const test = require('ava') const crypto = require('crypto') -const { JWK: { importKey }, errors } = require('../..') +const { JWK: { importKey, generate }, errors } = require('../..') const fixtures = require('../fixtures') @@ -85,3 +85,24 @@ test('failed to import throws an error', t => { }, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'only RSA, EC and OKP asymmetric keys are supported' }) }) }) + + +test('fails to import RSA without all optimization parameters', async t => { + const full = (await generate('RSA')).toJWK(true) + for (const param of ['p', 'q', 'dp', 'dq', 'qi']) { + const { [param]: omit, ...jwk } = full + t.throws(() => { + importKey(jwk) + }, { instanceOf: errors.JWKImportFailed, code: 'ERR_JWK_IMPORT_FAILED', message: 'all other private key parameters must be present when any one of them is present' }) + } +}) + +test('fails to import JWK RSA with oth', async t => { + const jwk = (await generate('RSA')).toJWK(true) + t.throws(() => { + importKey({ + ...jwk, + oth: [] + }) + }, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'Private RSA keys with more than two primes are not supported' }) +})