mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
crypto: check ed/x webcrypto key import algorithm names
PR-URL: https://github.com/nodejs/node/pull/37305 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
committed by
Antoine du Hamel
parent
83cce8717f
commit
8ddee73efc
@@ -1697,8 +1697,8 @@ added: v15.8.0
|
||||
|
||||
* Type: {boolean}
|
||||
|
||||
The `public` parameter is used to specify that the key is to be interpreted
|
||||
as a public key.
|
||||
The `public` parameter is used to specify that the `'raw'` format key is to be
|
||||
interpreted as a public key. **Default:** `false`.
|
||||
|
||||
### `NODE-SCRYPT` Algorithm
|
||||
<!-- YAML
|
||||
|
||||
@@ -253,10 +253,6 @@ async function ecImportKey(
|
||||
namedCurve,
|
||||
'algorithm.namedCurve',
|
||||
ObjectKeys(kNamedCurveAliases));
|
||||
// Only used for NODE-EDnnnn key variants to distinguish between
|
||||
// importing a raw public key or raw private key.
|
||||
if (algorithm.public !== undefined)
|
||||
validateBoolean(algorithm.public, 'algorithm.public');
|
||||
let keyObject;
|
||||
const usagesSet = new SafeSet(keyUsages);
|
||||
let checkNamedCurve = true;
|
||||
@@ -266,6 +262,24 @@ async function ecImportKey(
|
||||
throw new ERR_INVALID_ARG_TYPE('keyData', 'KeyObject', keyData);
|
||||
if (keyData.type === 'secret')
|
||||
throw lazyDOMException('Invalid key type', 'InvalidAccessException');
|
||||
|
||||
switch (namedCurve) {
|
||||
case 'NODE-X25519':
|
||||
// Fall through
|
||||
case 'NODE-X448':
|
||||
checkNamedCurve = false;
|
||||
if (algorithm.name !== 'ECDH')
|
||||
throw lazyDOMException('Invalid algorithm name.', 'DataError');
|
||||
break;
|
||||
case 'NODE-ED25519':
|
||||
// Fall through
|
||||
case 'NODE-ED448':
|
||||
checkNamedCurve = false;
|
||||
if (algorithm.name !== namedCurve)
|
||||
throw lazyDOMException('Invalid algorithm name.', 'DataError');
|
||||
break;
|
||||
}
|
||||
|
||||
verifyAcceptableEcKeyUse(name, keyData.type, usagesSet);
|
||||
keyObject = keyData;
|
||||
break;
|
||||
@@ -296,8 +310,24 @@ async function ecImportKey(
|
||||
case 'OKP': {
|
||||
checkNamedCurve = false;
|
||||
const isPublic = keyData.d === undefined;
|
||||
const type =
|
||||
namedCurve === 'NODE-X25519' || 'NODE-X448' ? 'ECDH' : 'ECDSA';
|
||||
|
||||
let type;
|
||||
switch (namedCurve) {
|
||||
case 'NODE-ED25519':
|
||||
// Fall through
|
||||
case 'NODE-ED448':
|
||||
type = `NODE-${keyData.crv.toUpperCase()}`;
|
||||
break;
|
||||
case 'NODE-X25519':
|
||||
// Fall through
|
||||
case 'NODE-X448':
|
||||
type = 'ECDH';
|
||||
break;
|
||||
}
|
||||
|
||||
if (algorithm.name !== type)
|
||||
throw lazyDOMException('Invalid algorithm name.', 'DataError');
|
||||
|
||||
verifyAcceptableEcKeyUse(
|
||||
type,
|
||||
isPublic ? 'public' : 'private',
|
||||
@@ -364,8 +394,12 @@ async function ecImportKey(
|
||||
// Fall through
|
||||
case 'NODE-X448':
|
||||
checkNamedCurve = false;
|
||||
if (algorithm.public !== undefined)
|
||||
validateBoolean(algorithm.public, 'algorithm.public');
|
||||
if (algorithm.name !== 'ECDH')
|
||||
throw lazyDOMException('Invalid algorithm name.', 'DataError');
|
||||
verifyAcceptableEcKeyUse(
|
||||
'ECDH',
|
||||
algorithm.name,
|
||||
algorithm.public === true ? 'public' : 'private',
|
||||
usagesSet);
|
||||
keyObject = createECRawKey(namedCurve, keyData, algorithm.public);
|
||||
@@ -374,8 +408,12 @@ async function ecImportKey(
|
||||
// Fall through
|
||||
case 'NODE-ED448':
|
||||
checkNamedCurve = false;
|
||||
if (algorithm.public !== undefined)
|
||||
validateBoolean(algorithm.public, 'algorithm.public');
|
||||
if (algorithm.name !== namedCurve)
|
||||
throw lazyDOMException('Invalid algorithm name.', 'DataError');
|
||||
verifyAcceptableEcKeyUse(
|
||||
'ECDSA',
|
||||
algorithm.name,
|
||||
algorithm.public === true ? 'public' : 'private',
|
||||
usagesSet);
|
||||
keyObject = createECRawKey(namedCurve, keyData, algorithm.public);
|
||||
|
||||
@@ -6,7 +6,10 @@ if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { subtle } = require('crypto').webcrypto;
|
||||
const {
|
||||
generateKeyPairSync,
|
||||
webcrypto: { subtle }
|
||||
} = require('crypto');
|
||||
|
||||
async function generateKey(namedCurve) {
|
||||
return subtle.generateKey(
|
||||
@@ -365,3 +368,52 @@ assert.rejects(
|
||||
{
|
||||
message: /Unsupported named curves for ECDSA/
|
||||
});
|
||||
|
||||
{
|
||||
for (const asymmetricKeyType of ['ed25519', 'ed448']) {
|
||||
const { publicKey, privateKey } = generateKeyPairSync(asymmetricKeyType);
|
||||
for (const keyObject of [publicKey, privateKey]) {
|
||||
const namedCurve = `NODE-${asymmetricKeyType.toUpperCase()}`;
|
||||
subtle.importKey(
|
||||
'node.keyObject',
|
||||
keyObject,
|
||||
{ name: namedCurve, namedCurve },
|
||||
true,
|
||||
keyObject.type === 'private' ? ['sign'] : ['verify'],
|
||||
).then((cryptoKey) => {
|
||||
assert.strictEqual(cryptoKey.type, keyObject.type);
|
||||
assert.strictEqual(cryptoKey.algorithm.name, namedCurve);
|
||||
}, common.mustNotCall());
|
||||
|
||||
assert.rejects(
|
||||
subtle.importKey(
|
||||
'node.keyObject',
|
||||
keyObject,
|
||||
{
|
||||
name: 'ECDSA',
|
||||
namedCurve,
|
||||
},
|
||||
true,
|
||||
keyObject.type === 'private' ? ['sign'] : ['verify']
|
||||
),
|
||||
{
|
||||
message: /Invalid algorithm name/
|
||||
});
|
||||
|
||||
assert.rejects(
|
||||
subtle.importKey(
|
||||
'node.keyObject',
|
||||
keyObject,
|
||||
{
|
||||
name: 'ECDH',
|
||||
namedCurve,
|
||||
},
|
||||
true,
|
||||
keyObject.type === 'private' ? ['deriveBits', 'deriveKey'] : [],
|
||||
),
|
||||
{
|
||||
message: /Invalid algorithm name/
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,11 @@ if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { subtle } = require('crypto').webcrypto;
|
||||
|
||||
const {
|
||||
generateKeyPairSync,
|
||||
webcrypto: { subtle }
|
||||
} = require('crypto');
|
||||
|
||||
// X25519 and X448 are ECDH named curves that should work
|
||||
// with the existing ECDH mechanisms with no additional
|
||||
@@ -260,7 +264,7 @@ assert.rejects(
|
||||
namedCurve: 'NODE-X25519'
|
||||
},
|
||||
true,
|
||||
['deriveBits']).then(common.mustCall());
|
||||
['deriveBits']).then(common.mustCall(), common.mustNotCall());
|
||||
|
||||
// Public JWK import
|
||||
subtle.importKey(
|
||||
@@ -275,5 +279,22 @@ assert.rejects(
|
||||
namedCurve: 'NODE-X25519'
|
||||
},
|
||||
true,
|
||||
[]).then(common.mustCall());
|
||||
[]).then(common.mustCall(), common.mustNotCall());
|
||||
|
||||
for (const asymmetricKeyType of ['x25519', 'x448']) {
|
||||
const { publicKey, privateKey } = generateKeyPairSync(asymmetricKeyType);
|
||||
for (const keyObject of [publicKey, privateKey]) {
|
||||
const namedCurve = `NODE-${asymmetricKeyType.toUpperCase()}`;
|
||||
subtle.importKey(
|
||||
'node.keyObject',
|
||||
keyObject,
|
||||
{ name: 'ECDH', namedCurve },
|
||||
true,
|
||||
keyObject.type === 'private' ? ['deriveBits', 'deriveKey'] : [],
|
||||
).then((cryptoKey) => {
|
||||
assert.strictEqual(cryptoKey.type, keyObject.type);
|
||||
assert.strictEqual(cryptoKey.algorithm.name, 'ECDH');
|
||||
}, common.mustNotCall());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user