diff --git a/README.md b/README.md index 9e89a14809..424c021669 100644 --- a/README.md +++ b/README.md @@ -300,7 +300,7 @@ jose.JWE.decrypt( | AES | ✓ | A128KW[1], A192KW[1], A256KW[1] | | AES GCM | ✓ | A128GCMKW, A192GCMKW, A256GCMKW | | Direct Key Agreement | ✓ | dir | -| RSAES OAEP | ✓ | RSA-OAEP, RSA-OAEP-256[3] | +| RSAES OAEP | ✓ | RSA-OAEP, RSA-OAEP-256[3], RSA-OAEP-384[3], RSA-OAEP-512[3] | | RSAES-PKCS1-v1_5 | ✓ | RSA1_5 | | PBES2 | ✓ | PBES2-HS256+A128KW[1], PBES2-HS384+A192KW[1], PBES2-HS512+A256KW[1] | | ECDH-ES (for all EC keys) | ✓ | ECDH-ES, ECDH-ES+A128KW[1], ECDH-ES+A192KW[1], ECDH-ES+A256KW[1] | @@ -330,7 +330,7 @@ Legend: 2 Unsecured JWS is [supported][documentation-none] for the JWS and JWT sign and verify operations but it is an entirely opt-in behaviour, downgrade attacks are prevented by the required use of a special `JWK.Key`-like object that cannot be instantiated through the key import API -3 RSA-OAEP-256 is only supported when Node.js >= 12.9.0 runtime is detected +3 RSAES OAEP using SHA-2 and MGF1 with SHA-2 is only supported when Node.js >= 12.9.0 runtime is detected ## FAQ diff --git a/lib/jwa/rsaes.js b/lib/jwa/rsaes.js index a7277123f6..f688543ee5 100644 --- a/lib/jwa/rsaes.js +++ b/lib/jwa/rsaes.js @@ -6,8 +6,10 @@ const { asInput } = require('../help/key_object') const resolvePadding = (alg) => { switch (alg) { - case 'RSA-OAEP-256': case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': return constants.RSA_PKCS1_OAEP_PADDING case 'RSA1_5': return constants.RSA_PKCS1_PADDING @@ -16,10 +18,14 @@ const resolvePadding = (alg) => { const resolveOaepHash = (alg) => { switch (alg) { - case 'RSA-OAEP-256': - return 'sha256' case 'RSA-OAEP': return 'sha1' + case 'RSA-OAEP-256': + return 'sha256' + case 'RSA-OAEP-384': + return 'sha384' + case 'RSA-OAEP-512': + return 'sha512' default: return undefined } @@ -38,14 +44,16 @@ const unwrapKey = (padding, oaepHash, { [KEYOBJECT]: keyObject }, payload) => { const LENGTHS = { RSA1_5: 0, 'RSA-OAEP': 592, - 'RSA-OAEP-256': 784 + 'RSA-OAEP-256': 784, + 'RSA-OAEP-384': 1040, + 'RSA-OAEP-512': 1296 } module.exports = (JWA, JWK) => { const algs = ['RSA-OAEP', 'RSA1_5'] if (oaepHashSupported) { - algs.splice(1, 0, 'RSA-OAEP-256') + algs.splice(1, 0, 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512') } algs.forEach((jwaAlg) => { diff --git a/test/jwk/rsa.test.js b/test/jwk/rsa.test.js index 43dbca9fe1..84bb21e9f6 100644 --- a/test/jwk/rsa.test.js +++ b/test/jwk/rsa.test.js @@ -36,7 +36,7 @@ test('RSA key .algorithms invalid operation', t => { test('RSA Private key algorithms (no operation)', t => { const result = key.algorithms() t.is(result.constructor, Set) - t.deepEqual([...result], ['PS256', 'PS384', 'PS512', 'RS256', 'RS384', 'RS512', 'RSA-OAEP', 'RSA-OAEP-256', 'RSA1_5']) + t.deepEqual([...result], ['PS256', 'PS384', 'PS512', 'RS256', 'RS384', 'RS512', 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512', 'RSA1_5']) }) } else { test('RSA Private key algorithms (no operation)', t => { @@ -129,7 +129,7 @@ test('RSA key .algorithms invalid operation', t => { test('RSA Private key .algorithms("wrapKey")', t => { const result = key.algorithms('wrapKey') t.is(result.constructor, Set) - t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA1_5']) + t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512', 'RSA1_5']) }) } else { test('RSA Private key .algorithms("wrapKey")', t => { @@ -150,7 +150,7 @@ test('RSA key .algorithms invalid operation', t => { test('RSA Private key .algorithms("unwrapKey")', t => { const result = key.algorithms('unwrapKey') t.is(result.constructor, Set) - t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA1_5']) + t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512', 'RSA1_5']) }) } else { test('RSA Private key .algorithms("unwrapKey")', t => { @@ -192,7 +192,7 @@ test('RSA key .algorithms invalid operation', t => { test('RSA EC Public key algorithms (no operation)', t => { const result = key.algorithms() t.is(result.constructor, Set) - t.deepEqual([...result], ['PS256', 'PS384', 'PS512', 'RS256', 'RS384', 'RS512', 'RSA-OAEP', 'RSA-OAEP-256', 'RSA1_5']) + t.deepEqual([...result], ['PS256', 'PS384', 'PS512', 'RS256', 'RS384', 'RS512', 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512', 'RSA1_5']) }) } else { test('RSA EC Public key algorithms (no operation)', t => { @@ -285,7 +285,7 @@ test('RSA key .algorithms invalid operation', t => { test('RSA Public key .algorithms("wrapKey")', t => { const result = key.algorithms('wrapKey') t.is(result.constructor, Set) - t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA1_5']) + t.deepEqual([...result], ['RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', 'RSA-OAEP-512', 'RSA1_5']) }) } else { test('RSA Public key .algorithms("wrapKey")', t => { @@ -341,6 +341,16 @@ test('RSA key .algorithms invalid operation', t => { const k = generateSync('RSA', 784) t.true(k.algorithms().has('RSA-OAEP-256')) }) + + test('RSA key >= 1040 bits can do RSA-OAEP-256', t => { + const k = generateSync('RSA', 1040) + t.true(k.algorithms().has('RSA-OAEP-384')) + }) + + test('RSA key >= 1296 bits can do RSA-OAEP-256', t => { + const k = generateSync('RSA', 1296) + t.true(k.algorithms().has('RSA-OAEP-512')) + }) } test('RSA key >= 784 bits can do PS384', t => { @@ -375,6 +385,16 @@ test('RSA key .algorithms invalid operation', t => { const k = generateSync('RSA', 896) t.true(k.algorithms().has('RSA-OAEP-256')) }) + + test('RSA key >= 1040 bits can do RSA-OAEP-256', t => { + const k = generateSync('RSA', 1152) + t.true(k.algorithms().has('RSA-OAEP-384')) + }) + + test('RSA key >= 1408 bits can do RSA-OAEP-256', t => { + const k = generateSync('RSA', 1408) + t.true(k.algorithms().has('RSA-OAEP-512')) + }) } test('RSA key >= 1152 bits can do PS512', t => {