diff --git a/lib/internal/crypto/hashnames.js b/lib/internal/crypto/hashnames.js index 49729034facc7c..7af2091d84de39 100644 --- a/lib/internal/crypto/hashnames.js +++ b/lib/internal/crypto/hashnames.js @@ -2,7 +2,6 @@ const { ObjectKeys, - StringPrototypeToLowerCase, } = primordials; const kHashContextNode = 1; @@ -58,8 +57,7 @@ const kHashNames = { for (let n = 0; n < keys.length; n++) { const contexts = ObjectKeys(kHashNames[keys[n]]); for (let i = 0; i < contexts.length; i++) { - const alias = - StringPrototypeToLowerCase(kHashNames[keys[n]][contexts[i]]); + const alias = kHashNames[keys[n]][contexts[i]]; if (kHashNames[alias] === undefined) kHashNames[alias] = kHashNames[keys[n]]; } @@ -67,13 +65,10 @@ const kHashNames = { } function normalizeHashName(name, context = kHashContextNode) { - if (typeof name !== 'string') - return name; - name = StringPrototypeToLowerCase(name); - const alias = kHashNames[name]?.[context]; - return alias || name; + return kHashNames[name]?.[context]; } + normalizeHashName.kContextNode = kHashContextNode; normalizeHashName.kContextWebCrypto = kHashContextWebCrypto; normalizeHashName.kContextJwkRsa = kHashContextJwkRsa; diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js index 74c8af7cf30e5b..a3ef89ed6f2e7e 100644 --- a/lib/internal/crypto/rsa.js +++ b/lib/internal/crypto/rsa.js @@ -275,9 +275,13 @@ function rsaImportKey( } if (keyData.alg !== undefined) { - const hash = - normalizeHashName(keyData.alg, normalizeHashName.kContextWebCrypto); - if (hash !== algorithm.hash.name) + const expected = + normalizeHashName(algorithm.hash.name, + algorithm.name === 'RSASSA-PKCS1-v1_5' ? normalizeHashName.kContextJwkRsa : + algorithm.name === 'RSA-PSS' ? normalizeHashName.kContextJwkRsaPss : + normalizeHashName.kContextJwkRsaOaep); + + if (keyData.alg !== expected) throw lazyDOMException( 'JWK "alg" does not match the requested algorithm', 'DataError'); diff --git a/test/parallel/test-webcrypto-export-import-rsa.js b/test/parallel/test-webcrypto-export-import-rsa.js index 62734c69d5ed77..f1bdaeed4dee8e 100644 --- a/test/parallel/test-webcrypto-export-import-rsa.js +++ b/test/parallel/test-webcrypto-export-import-rsa.js @@ -384,6 +384,19 @@ async function testImportJwk( const jwk = keyData[size].jwk; + let alg; + switch (name) { + case 'RSA-PSS': + alg = `PS${hash === 'SHA-1' ? 1 : hash.substring(4)}`; + break; + case 'RSA-OAEP': + alg = `RSA-OAEP${hash === 'SHA-1' ? '' : hash.substring(3)}`; + break; + case 'RSASSA-PKCS1-v1_5': + alg = `RS${hash === 'SHA-1' ? 1 : hash.substring(4)}`; + break; + } + const [ publicKey, privateKey, @@ -394,14 +407,14 @@ async function testImportJwk( kty: jwk.kty, n: jwk.n, e: jwk.e, - alg: `PS${hash.substring(4)}` + alg, }, { name, hash }, extractable, publicUsages), subtle.importKey( 'jwk', - { ...jwk, alg: `PS${hash.substring(4)}` }, + { ...jwk, alg }, { name, hash }, extractable, privateUsages), @@ -435,6 +448,8 @@ async function testImportJwk( assert.strictEqual(pubJwk.kty, 'RSA'); assert.strictEqual(pvtJwk.kty, 'RSA'); + assert.strictEqual(pubJwk.alg, alg); + assert.strictEqual(pvtJwk.alg, alg); assert.strictEqual(pubJwk.n, jwk.n); assert.strictEqual(pvtJwk.n, jwk.n); assert.strictEqual(pubJwk.e, jwk.e); @@ -483,22 +498,41 @@ async function testImportJwk( } { - let invalidAlg = name === 'RSA-OAEP' ? name : name === 'RSA-PSS' ? 'PS' : 'RS'; + await assert.rejects( + subtle.importKey( + 'jwk', + { kty: jwk.kty, n: jwk.n, e: jwk.e, alg: alg.toLowerCase() }, + { name, hash }, + extractable, + publicUsages), + { message: 'JWK "alg" does not match the requested algorithm' }); + await assert.rejects( + subtle.importKey( + 'jwk', + { ...jwk, alg: alg.toLowerCase() }, + { name, hash }, + extractable, + privateUsages), + { message: 'JWK "alg" does not match the requested algorithm' }); + } + + { + let invalidAlgHash = name === 'RSA-OAEP' ? name : name === 'RSA-PSS' ? 'PS' : 'RS'; switch (name) { case 'RSA-OAEP': if (hash === 'SHA-1') - invalidAlg += '-256'; + invalidAlgHash += '-256'; break; default: if (hash === 'SHA-256') - invalidAlg += '384'; + invalidAlgHash += '384'; else - invalidAlg += '256'; + invalidAlgHash += '256'; } await assert.rejects( subtle.importKey( 'jwk', - { kty: jwk.kty, n: jwk.n, e: jwk.e, alg: invalidAlg }, + { kty: jwk.kty, n: jwk.n, e: jwk.e, alg: invalidAlgHash }, { name, hash }, extractable, publicUsages), @@ -506,7 +540,29 @@ async function testImportJwk( await assert.rejects( subtle.importKey( 'jwk', - { ...jwk, alg: invalidAlg }, + { ...jwk, alg: invalidAlgHash }, + { name, hash }, + extractable, + privateUsages), + { message: 'JWK "alg" does not match the requested algorithm' }); + } + + { + const invalidAlgType = name === 'RSA-PSS' ? `RS${hash.substring(4)}` : `PS${hash.substring(4)}`; + await assert.rejects( + subtle.importKey( + 'jwk', + { kty: jwk.kty, n: jwk.n, e: jwk.e, alg: invalidAlgType }, + { name, hash }, + extractable, + publicUsages), + { message: 'JWK "alg" does not match the requested algorithm' }).catch((e) => { + throw e; + }); + await assert.rejects( + subtle.importKey( + 'jwk', + { ...jwk, alg: invalidAlgType }, { name, hash }, extractable, privateUsages),