fix: restrict RS key algorithms by the key's bit size

This commit is contained in:
Filip Skokan 2019-03-17 17:44:36 +01:00
parent 1dc58fc9a4
commit 9af295bdb2
2 changed files with 68 additions and 26 deletions

View file

@ -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')
}

View file

@ -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'))
})
})()