mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
crypto: ensure expected JWK alg in SubtleCrypto.importKey RSA imports
PR-URL: https://github.com/nodejs/node/pull/57450 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
1 parent
8b41272f79
commit
0cfc471e82
3 files changed
+82
-27
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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,10 @@ async function testImportJwk(
|
||||
}
|
||||
|
||||
{
|
||||
let invalidAlg = name === 'RSA-OAEP' ? name : name === 'RSA-PSS' ? 'PS' : 'RS';
|
||||
switch (name) {
|
||||
case 'RSA-OAEP':
|
||||
if (hash === 'SHA-1')
|
||||
invalidAlg += '-256';
|
||||
break;
|
||||
default:
|
||||
if (hash === 'SHA-256')
|
||||
invalidAlg += '384';
|
||||
else
|
||||
invalidAlg += '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: alg.toLowerCase() },
|
||||
{ name, hash },
|
||||
extractable,
|
||||
publicUsages),
|
||||
@@ -506,7 +509,60 @@ async function testImportJwk(
|
||||
await assert.rejects(
|
||||
subtle.importKey(
|
||||
'jwk',
|
||||
{ ...jwk, alg: invalidAlg },
|
||||
{ ...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')
|
||||
invalidAlgHash += '-256';
|
||||
break;
|
||||
default:
|
||||
if (hash === 'SHA-256')
|
||||
invalidAlgHash += '384';
|
||||
else
|
||||
invalidAlgHash += '256';
|
||||
}
|
||||
await assert.rejects(
|
||||
subtle.importKey(
|
||||
'jwk',
|
||||
{ kty: jwk.kty, n: jwk.n, e: jwk.e, alg: invalidAlgHash },
|
||||
{ name, hash },
|
||||
extractable,
|
||||
publicUsages),
|
||||
{ message: 'JWK "alg" does not match the requested algorithm' });
|
||||
await assert.rejects(
|
||||
subtle.importKey(
|
||||
'jwk',
|
||||
{ ...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),
|
||||
|
||||
Reference in new issue
Block a user