mirror of
https://github.com/danbulant/jose
synced 2026-05-20 21:08:44 +00:00
fix: restrict RS key algorithms by the key's bit size
This commit is contained in:
parent
1dc58fc9a4
commit
9af295bdb2
2 changed files with 68 additions and 26 deletions
|
|
@ -6,14 +6,6 @@ const { THUMBPRINT_MATERIAL, PUBLIC_MEMBERS, PRIVATE_MEMBERS, JWK_MEMBERS } = re
|
|||
const Key = require('./base')
|
||||
|
||||
const generateKeyPair = promisify(async)
|
||||
const SIG_ALGS = new Set([
|
||||
'PS256',
|
||||
'RS256',
|
||||
'PS384',
|
||||
'RS384',
|
||||
'PS512',
|
||||
'RS512'
|
||||
])
|
||||
|
||||
const WRAP_ALGS = new Set([
|
||||
'RSA-OAEP',
|
||||
|
|
@ -25,6 +17,31 @@ Object.freeze(RSA_PUBLIC)
|
|||
const RSA_PRIVATE = new Set([...RSA_PUBLIC, 'd', 'p', 'q', 'dp', 'dq', 'qi'])
|
||||
Object.freeze(RSA_PRIVATE)
|
||||
|
||||
const sigAlgsAvailableFor = (length) => {
|
||||
switch (true) {
|
||||
case length >= 1040:
|
||||
return new Set(['PS256', 'RS256', 'PS384', 'RS384', 'PS512', 'RS512'])
|
||||
case length >= 784:
|
||||
return new Set(['PS256', 'RS256', 'PS384', 'RS384', 'RS512'])
|
||||
case length >= 752:
|
||||
return new Set(['PS256', 'RS256', 'RS384', 'RS512'])
|
||||
case length >= 624:
|
||||
return new Set(['PS256', 'RS256', 'RS384'])
|
||||
case length >= 528:
|
||||
return new Set(['PS256', 'RS256'])
|
||||
default:
|
||||
return new Set(['RS256'])
|
||||
}
|
||||
}
|
||||
|
||||
const wrapAlgsAvailableFor = (length) => {
|
||||
if (length >= 592) {
|
||||
return new Set(WRAP_ALGS)
|
||||
}
|
||||
|
||||
return new Set(['RSA1_5'])
|
||||
}
|
||||
|
||||
// RSA Key Type
|
||||
class RSAKey extends Key {
|
||||
constructor (...args) {
|
||||
|
|
@ -62,10 +79,6 @@ class RSAKey extends Key {
|
|||
}
|
||||
|
||||
algorithms (operation, { use = this.use, alg = this.alg } = {}) {
|
||||
if (this.length < 2048) {
|
||||
return new Set()
|
||||
}
|
||||
|
||||
if (alg) {
|
||||
return new Set(this.algorithms(operation, { alg: null, use }).has(alg) ? [alg] : undefined)
|
||||
}
|
||||
|
|
@ -79,25 +92,25 @@ class RSAKey extends Key {
|
|||
return new Set()
|
||||
}
|
||||
|
||||
return new Set(SIG_ALGS)
|
||||
return sigAlgsAvailableFor(this.length)
|
||||
case 'verify':
|
||||
if (use === 'enc') {
|
||||
return new Set()
|
||||
}
|
||||
|
||||
return new Set(SIG_ALGS)
|
||||
return sigAlgsAvailableFor(this.length)
|
||||
case 'wrapKey':
|
||||
if (use === 'sig') {
|
||||
return new Set()
|
||||
}
|
||||
|
||||
return new Set(WRAP_ALGS)
|
||||
return wrapAlgsAvailableFor(this.length)
|
||||
case 'unwrapKey':
|
||||
if (this.public || use === 'sig') {
|
||||
return new Set()
|
||||
}
|
||||
|
||||
return new Set(WRAP_ALGS)
|
||||
return wrapAlgsAvailableFor(this.length)
|
||||
case undefined:
|
||||
// just the ops needed to return all algs regardless of its use
|
||||
return new Set([
|
||||
|
|
@ -110,7 +123,7 @@ class RSAKey extends Key {
|
|||
}
|
||||
|
||||
static async generate (len = 2048, opts, privat = true) {
|
||||
if (!Number.isSafeInteger(len) || len < 2048 || len % 8 !== 0) {
|
||||
if (!Number.isSafeInteger(len) || len < 512 || len % 8 !== 0) {
|
||||
throw new TypeError('invalid bit length')
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +133,7 @@ class RSAKey extends Key {
|
|||
}
|
||||
|
||||
static generateSync (len = 2048, opts, privat = true) {
|
||||
if (!Number.isSafeInteger(len) || len < 2048 || len % 8 !== 0) {
|
||||
if (!Number.isSafeInteger(len) || len < 512 || len % 8 !== 0) {
|
||||
throw new TypeError('invalid bit length')
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,14 +34,6 @@ test(`RSA key .algorithms invalid operation`, t => {
|
|||
t.deepEqual([...result], ['PS256', 'RS256', 'PS384', 'RS384', 'PS512', 'RS512', 'RSA-OAEP', 'RSA1_5'])
|
||||
})
|
||||
|
||||
test('RSA < 2048 bits does not support any algorithms', t => {
|
||||
const keyObject = createPublicKey(fixtures.RSA_512)
|
||||
const key = new RSAKey(keyObject)
|
||||
const result = key.algorithms()
|
||||
t.is(result.constructor, Set)
|
||||
t.deepEqual([...result], [])
|
||||
})
|
||||
|
||||
test('RSA Private key algorithms (no operation, w/ alg)', t => {
|
||||
const key = new RSAKey(keyObject, { alg: 'RS256' })
|
||||
const result = key.algorithms()
|
||||
|
|
@ -257,4 +249,41 @@ test(`RSA key .algorithms invalid operation`, t => {
|
|||
t.is(result.constructor, Set)
|
||||
t.deepEqual([...result], [])
|
||||
})
|
||||
|
||||
test('any RSA key can do RS256 and RSA1_5', t => {
|
||||
const k = RSAKey.generateSync(512)
|
||||
const result = k.algorithms()
|
||||
t.is(result.constructor, Set)
|
||||
t.deepEqual([...result], ['RS256', 'RSA1_5'])
|
||||
})
|
||||
|
||||
test('RSA key >= 528 bits can do PS256', t => {
|
||||
const k = RSAKey.generateSync(528)
|
||||
t.true(k.algorithms().has('PS256'))
|
||||
})
|
||||
|
||||
test('RSA key >= 592 bits can do RSA-OAEP', t => {
|
||||
const k = RSAKey.generateSync(592)
|
||||
t.true(k.algorithms().has('RSA-OAEP'))
|
||||
})
|
||||
|
||||
test('RSA key >= 624 bits can do RS384', t => {
|
||||
const k = RSAKey.generateSync(624)
|
||||
t.true(k.algorithms().has('RS384'))
|
||||
})
|
||||
|
||||
test('RSA key >= 752 bits can do RS512', t => {
|
||||
const k = RSAKey.generateSync(752)
|
||||
t.true(k.algorithms().has('RS512'))
|
||||
})
|
||||
|
||||
test('RSA key >= 784 bits can do PS384', t => {
|
||||
const k = RSAKey.generateSync(784)
|
||||
t.true(k.algorithms().has('PS384'))
|
||||
})
|
||||
|
||||
test('RSA key >= 1040 bits can do PS512', t => {
|
||||
const k = RSAKey.generateSync(1040)
|
||||
t.true(k.algorithms().has('PS512'))
|
||||
})
|
||||
})()
|
||||
|
|
|
|||
Loading…
Reference in a new issue