diff --git a/docs/README.md b/docs/README.md index d2e999be66..9e62d2aa30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -625,6 +625,7 @@ specified by the parameters are first. - `parameters`: `` - `kty`: `` Key Type to filter for. + - `crv`: `` Key Curve to filter for. (for EC and OKP keys) - `alg`: `` Key supported algorithm to filter for. - `kid`: `` Key ID to filter for. - `use`: `` Filter keys with the specified use defined. Keys missing "use" parameter will @@ -643,6 +644,7 @@ parameters is returned. - `parameters`: `` - `kty`: `` Key Type to filter for. + - `crv`: `` Key Curve to filter for. (for EC and OKP keys) - `alg`: `` Key supported algorithm to filter for. - `kid`: `` Key ID to filter for. - `use`: `` Filter keys with the specified use defined. Keys missing "use" parameter will diff --git a/lib/jwks/keystore.js b/lib/jwks/keystore.js index b6ee1ae964..462bf5fcf3 100644 --- a/lib/jwks/keystore.js +++ b/lib/jwks/keystore.js @@ -6,25 +6,13 @@ const Key = require('../jwk/key/base') const importKey = require('../jwk/import') const { USES_MAPPING } = require('../help/consts') -const keyscore = (key, { alg, kid, use, ops, x5t, x5t256 }) => { +const keyscore = (key, { alg, use, ops }) => { let score = 0 if (alg && key.alg) { score++ } - if (kid && key.kid) { - score++ - } - - if (x5t && key.x5t) { - score++ - } - - if (x5t256 && key['x5t#S256']) { - score++ - } - if (use && key.use) { score++ } @@ -64,20 +52,16 @@ class KeyStore { i(this).keys = new Set(keys) } - all ({ alg, kid, use, kty, key_ops: ops, x5t, 'x5t#S256': x5t256 } = {}) { + all ({ alg, kid, use, kty, key_ops: ops, x5t, 'x5t#S256': x5t256, crv } = {}) { if (ops !== undefined && (!Array.isArray(ops) || !ops.length || ops.some(x => typeof x !== 'string'))) { throw new TypeError('`key_ops` must be a non-empty array of strings') } - const search = { alg, kid, use, ops, x5t, x5t256 } + const search = { alg, use, ops } return [...i(this).keys] .filter((key) => { let candidate = true - if (alg !== undefined && !key.algorithms().has(alg)) { - candidate = false - } - if (candidate && kid !== undefined && key.kid !== kid) { candidate = false } @@ -94,6 +78,14 @@ class KeyStore { candidate = false } + if (candidate && crv !== undefined && (key.crv !== crv)) { + candidate = false + } + + if (alg !== undefined && !key.algorithms().has(alg)) { + candidate = false + } + if (candidate && use !== undefined && (key.use !== undefined && key.use !== use)) { candidate = false } diff --git a/test/jwks/keystore.test.js b/test/jwks/keystore.test.js index 26e49ef8e9..7b8587e996 100644 --- a/test/jwks/keystore.test.js +++ b/test/jwks/keystore.test.js @@ -149,6 +149,18 @@ test('.all() and .get() use sort', t => { t.is(ks.get({ use: 'sig' }), k2) }) +test('.all() and .get() crv filter', t => { + const k = generateSync('EC', 'P-256') + const k2 = generateSync('EC', 'P-384') + const ks = new KeyStore(k, k2) + t.deepEqual(ks.all({ crv: 'P-256' }), [k]) + t.deepEqual(ks.all({ crv: 'P-384' }), [k2]) + t.deepEqual(ks.all({ crv: 'P-521' }), []) + t.is(ks.get({ crv: 'P-256' }), k) + t.is(ks.get({ crv: 'P-384' }), k2) + t.is(ks.get({ crv: 'P-521' }), undefined) +}) + test('.all() and .get() kid filter', t => { const k = generateSync('RSA', undefined, { kid: 'foobar' }) const ks = new KeyStore(k) diff --git a/types/index.d.ts b/types/index.d.ts index 708879acad..43120ae384 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -180,6 +180,7 @@ export namespace JWKS { kty?: keyType; x5t?: string; 'x5t#S256'?: string; + crv?: string; } class KeyStore {