Skip to content

Commit 9af295b

Browse files
committed
fix: restrict RS key algorithms by the key's bit size
1 parent 1dc58fc commit 9af295b

File tree

2 files changed

+68
-26
lines changed

2 files changed

+68
-26
lines changed

lib/jwk/key/rsa.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@ const { THUMBPRINT_MATERIAL, PUBLIC_MEMBERS, PRIVATE_MEMBERS, JWK_MEMBERS } = re
66
const Key = require('./base')
77

88
const generateKeyPair = promisify(async)
9-
const SIG_ALGS = new Set([
10-
'PS256',
11-
'RS256',
12-
'PS384',
13-
'RS384',
14-
'PS512',
15-
'RS512'
16-
])
179

1810
const WRAP_ALGS = new Set([
1911
'RSA-OAEP',
@@ -25,6 +17,31 @@ Object.freeze(RSA_PUBLIC)
2517
const RSA_PRIVATE = new Set([...RSA_PUBLIC, 'd', 'p', 'q', 'dp', 'dq', 'qi'])
2618
Object.freeze(RSA_PRIVATE)
2719

20+
const sigAlgsAvailableFor = (length) => {
21+
switch (true) {
22+
case length >= 1040:
23+
return new Set(['PS256', 'RS256', 'PS384', 'RS384', 'PS512', 'RS512'])
24+
case length >= 784:
25+
return new Set(['PS256', 'RS256', 'PS384', 'RS384', 'RS512'])
26+
case length >= 752:
27+
return new Set(['PS256', 'RS256', 'RS384', 'RS512'])
28+
case length >= 624:
29+
return new Set(['PS256', 'RS256', 'RS384'])
30+
case length >= 528:
31+
return new Set(['PS256', 'RS256'])
32+
default:
33+
return new Set(['RS256'])
34+
}
35+
}
36+
37+
const wrapAlgsAvailableFor = (length) => {
38+
if (length >= 592) {
39+
return new Set(WRAP_ALGS)
40+
}
41+
42+
return new Set(['RSA1_5'])
43+
}
44+
2845
// RSA Key Type
2946
class RSAKey extends Key {
3047
constructor (...args) {
@@ -62,10 +79,6 @@ class RSAKey extends Key {
6279
}
6380

6481
algorithms (operation, { use = this.use, alg = this.alg } = {}) {
65-
if (this.length < 2048) {
66-
return new Set()
67-
}
68-
6982
if (alg) {
7083
return new Set(this.algorithms(operation, { alg: null, use }).has(alg) ? [alg] : undefined)
7184
}
@@ -79,25 +92,25 @@ class RSAKey extends Key {
7992
return new Set()
8093
}
8194

82-
return new Set(SIG_ALGS)
95+
return sigAlgsAvailableFor(this.length)
8396
case 'verify':
8497
if (use === 'enc') {
8598
return new Set()
8699
}
87100

88-
return new Set(SIG_ALGS)
101+
return sigAlgsAvailableFor(this.length)
89102
case 'wrapKey':
90103
if (use === 'sig') {
91104
return new Set()
92105
}
93106

94-
return new Set(WRAP_ALGS)
107+
return wrapAlgsAvailableFor(this.length)
95108
case 'unwrapKey':
96109
if (this.public || use === 'sig') {
97110
return new Set()
98111
}
99112

100-
return new Set(WRAP_ALGS)
113+
return wrapAlgsAvailableFor(this.length)
101114
case undefined:
102115
// just the ops needed to return all algs regardless of its use
103116
return new Set([
@@ -110,7 +123,7 @@ class RSAKey extends Key {
110123
}
111124

112125
static async generate (len = 2048, opts, privat = true) {
113-
if (!Number.isSafeInteger(len) || len < 2048 || len % 8 !== 0) {
126+
if (!Number.isSafeInteger(len) || len < 512 || len % 8 !== 0) {
114127
throw new TypeError('invalid bit length')
115128
}
116129

@@ -120,7 +133,7 @@ class RSAKey extends Key {
120133
}
121134

122135
static generateSync (len = 2048, opts, privat = true) {
123-
if (!Number.isSafeInteger(len) || len < 2048 || len % 8 !== 0) {
136+
if (!Number.isSafeInteger(len) || len < 512 || len % 8 !== 0) {
124137
throw new TypeError('invalid bit length')
125138
}
126139

test/jwk/rsa.test.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ test(`RSA key .algorithms invalid operation`, t => {
3434
t.deepEqual([...result], ['PS256', 'RS256', 'PS384', 'RS384', 'PS512', 'RS512', 'RSA-OAEP', 'RSA1_5'])
3535
})
3636

37-
test('RSA < 2048 bits does not support any algorithms', t => {
38-
const keyObject = createPublicKey(fixtures.RSA_512)
39-
const key = new RSAKey(keyObject)
40-
const result = key.algorithms()
41-
t.is(result.constructor, Set)
42-
t.deepEqual([...result], [])
43-
})
44-
4537
test('RSA Private key algorithms (no operation, w/ alg)', t => {
4638
const key = new RSAKey(keyObject, { alg: 'RS256' })
4739
const result = key.algorithms()
@@ -257,4 +249,41 @@ test(`RSA key .algorithms invalid operation`, t => {
257249
t.is(result.constructor, Set)
258250
t.deepEqual([...result], [])
259251
})
252+
253+
test('any RSA key can do RS256 and RSA1_5', t => {
254+
const k = RSAKey.generateSync(512)
255+
const result = k.algorithms()
256+
t.is(result.constructor, Set)
257+
t.deepEqual([...result], ['RS256', 'RSA1_5'])
258+
})
259+
260+
test('RSA key >= 528 bits can do PS256', t => {
261+
const k = RSAKey.generateSync(528)
262+
t.true(k.algorithms().has('PS256'))
263+
})
264+
265+
test('RSA key >= 592 bits can do RSA-OAEP', t => {
266+
const k = RSAKey.generateSync(592)
267+
t.true(k.algorithms().has('RSA-OAEP'))
268+
})
269+
270+
test('RSA key >= 624 bits can do RS384', t => {
271+
const k = RSAKey.generateSync(624)
272+
t.true(k.algorithms().has('RS384'))
273+
})
274+
275+
test('RSA key >= 752 bits can do RS512', t => {
276+
const k = RSAKey.generateSync(752)
277+
t.true(k.algorithms().has('RS512'))
278+
})
279+
280+
test('RSA key >= 784 bits can do PS384', t => {
281+
const k = RSAKey.generateSync(784)
282+
t.true(k.algorithms().has('PS384'))
283+
})
284+
285+
test('RSA key >= 1040 bits can do PS512', t => {
286+
const k = RSAKey.generateSync(1040)
287+
t.true(k.algorithms().has('PS512'))
288+
})
260289
})()

0 commit comments

Comments
 (0)