Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const {
InternalCryptoKey,
SecretKeyObject,
createSecretKey,
kAlgorithm,
} = require('internal/crypto/keys');

const {
Expand Down Expand Up @@ -108,7 +109,7 @@ function asyncAesCtrCipher(mode, key, data, algorithm) {
mode,
key[kKeyObject][kHandle],
data,
getVariant('AES-CTR', key.algorithm.length),
getVariant('AES-CTR', key[kAlgorithm].length),
algorithm.counter,
algorithm.length));
}
Expand All @@ -119,7 +120,7 @@ function asyncAesCbcCipher(mode, key, data, algorithm) {
mode,
key[kKeyObject][kHandle],
data,
getVariant('AES-CBC', key.algorithm.length),
getVariant('AES-CBC', key[kAlgorithm].length),
algorithm.iv));
}

Expand All @@ -129,7 +130,7 @@ function asyncAesKwCipher(mode, key, data) {
mode,
key[kKeyObject][kHandle],
data,
getVariant('AES-KW', key.algorithm.length)));
getVariant('AES-KW', key[kAlgorithm].length)));
}

function asyncAesGcmCipher(mode, key, data, algorithm) {
Expand Down Expand Up @@ -166,7 +167,7 @@ function asyncAesGcmCipher(mode, key, data, algorithm) {
mode,
key[kKeyObject][kHandle],
data,
getVariant('AES-GCM', key.algorithm.length),
getVariant('AES-GCM', key[kAlgorithm].length),
algorithm.iv,
tag,
algorithm.additionalData));
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/crypto/cfrg.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const {
PublicKeyObject,
createPrivateKey,
createPublicKey,
kKeyType,
} = require('internal/crypto/keys');

const generateKeyPair = promisify(_generateKeyPair);
Expand Down Expand Up @@ -343,7 +344,7 @@ function eddsaSignVerify(key, data, algorithm, signature) {
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
const type = mode === kSignJobModeSign ? 'private' : 'public';

if (key.type !== type)
if (key[kKeyType] !== type)
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');

return jobPromise(() => new SignJob(
Expand Down
10 changes: 6 additions & 4 deletions lib/internal/crypto/diffiehellman.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const {

const {
KeyObject,
kAlgorithm,
kKeyType,
} = require('internal/crypto/keys');

const {
Expand Down Expand Up @@ -328,20 +330,20 @@ let masks;
async function ecdhDeriveBits(algorithm, baseKey, length) {
const { 'public': key } = algorithm;

if (baseKey.type !== 'private') {
if (baseKey[kKeyType] !== 'private') {
throw lazyDOMException(
'baseKey must be a private key', 'InvalidAccessError');
}

if (key.algorithm.name !== baseKey.algorithm.name) {
if (key[kAlgorithm].name !== baseKey[kAlgorithm].name) {
throw lazyDOMException(
'The public and private keys must be of the same type',
'InvalidAccessError');
}

if (
key.algorithm.name === 'ECDH' &&
key.algorithm.namedCurve !== baseKey.algorithm.namedCurve
key[kAlgorithm].name === 'ECDH' &&
key[kAlgorithm].namedCurve !== baseKey[kAlgorithm].namedCurve
) {
throw lazyDOMException('Named curve mismatch', 'InvalidAccessError');
}
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/crypto/ec.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const {
PublicKeyObject,
createPrivateKey,
createPublicKey,
kKeyType,
} = require('internal/crypto/keys');

const generateKeyPair = promisify(_generateKeyPair);
Expand Down Expand Up @@ -284,7 +285,7 @@ function ecdsaSignVerify(key, data, { name, hash }, signature) {
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
const type = mode === kSignJobModeSign ? 'private' : 'public';

if (key.type !== type)
if (key[kKeyType] !== type)
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');

const hashname = normalizeHashName(hash.name);
Expand Down
41 changes: 29 additions & 12 deletions lib/internal/crypto/keys.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayFrom,
ArrayPrototypeSlice,
ObjectDefineProperties,
ObjectDefineProperty,
Expand Down Expand Up @@ -81,6 +82,8 @@ const kAlgorithm = Symbol('kAlgorithm');
const kExtractable = Symbol('kExtractable');
const kKeyType = Symbol('kKeyType');
const kKeyUsages = Symbol('kKeyUsages');
const kCachedAlgorithm = Symbol('kCachedAlgorithm');
const kCachedKeyUsages = Symbol('kCachedKeyUsages');

// Key input contexts.
const kConsumePublic = 0;
Expand Down Expand Up @@ -217,7 +220,7 @@ const {
throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
}

if (result.usages.length === 0) {
if (result[kKeyUsages].length === 0) {
throw lazyDOMException(
`Usages cannot be empty when importing a ${result.type} key.`,
'SyntaxError');
Expand Down Expand Up @@ -309,7 +312,7 @@ const {
throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
}

if (result.type === 'private' && result.usages.length === 0) {
if (result.type === 'private' && result[kKeyUsages].length === 0) {
throw lazyDOMException(
`Usages cannot be empty when importing a ${result.type} key.`,
'SyntaxError');
Expand Down Expand Up @@ -735,8 +738,8 @@ function prepareSecretKey(key, encoding, bufferOnly = false) {
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret');
return key[kHandle];
} else if (isCryptoKey(key)) {
if (key.type !== 'secret')
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret');
if (key[kKeyType] !== 'secret')
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key[kKeyType], 'secret');
return key[kKeyObject][kHandle];
}
}
Expand Down Expand Up @@ -785,7 +788,7 @@ function createPrivateKey(key) {
}

function isKeyObject(obj) {
return obj != null && obj[kKeyType] !== undefined;
return obj != null && obj[kKeyType] !== undefined && obj[kKeyObject] === undefined;
}

// Our implementation of CryptoKey is a simple wrapper around a KeyObject
Expand All @@ -809,17 +812,21 @@ class CryptoKey {
};

return `CryptoKey ${inspect({
type: this.type,
extractable: this.extractable,
algorithm: this.algorithm,
usages: this.usages,
type: this[kKeyType],
extractable: this[kExtractable],
algorithm: this[kAlgorithm],
usages: this[kKeyUsages],
}, opts)}`;
}

get [kKeyType]() {
return this[kKeyObject].type;
}

get type() {
if (!(this instanceof CryptoKey))
throw new ERR_INVALID_THIS('CryptoKey');
return this[kKeyObject].type;
return this[kKeyType];
}

get extractable() {
Expand All @@ -831,13 +838,19 @@ class CryptoKey {
get algorithm() {
if (!(this instanceof CryptoKey))
throw new ERR_INVALID_THIS('CryptoKey');
return this[kAlgorithm];
if (!this[kCachedAlgorithm]) {
this[kCachedAlgorithm] ??= { ...this[kAlgorithm] };
this[kCachedAlgorithm].hash &&= { ...this[kCachedAlgorithm].hash };
this[kCachedAlgorithm].publicExponent &&= new Uint8Array(this[kCachedAlgorithm].publicExponent);
}
return this[kCachedAlgorithm];
}

get usages() {
if (!(this instanceof CryptoKey))
throw new ERR_INVALID_THIS('CryptoKey');
return this[kKeyUsages];
this[kCachedKeyUsages] ??= ArrayFrom(this[kKeyUsages]);
return this[kCachedKeyUsages];
}
}

Expand Down Expand Up @@ -1008,4 +1021,8 @@ module.exports = {
isKeyObject,
isCryptoKey,
importGenericSecretKey,
kAlgorithm,
kExtractable,
kKeyType,
kKeyUsages,
};
3 changes: 2 additions & 1 deletion lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const {
InternalCryptoKey,
SecretKeyObject,
createSecretKey,
kAlgorithm,
} = require('internal/crypto/keys');

const generateKey = promisify(_generateKey);
Expand Down Expand Up @@ -161,7 +162,7 @@ function hmacSignVerify(key, data, algorithm, signature) {
return jobPromise(() => new HmacJob(
kCryptoJobAsync,
mode,
normalizeHashName(key.algorithm.hash.name),
normalizeHashName(key[kAlgorithm].hash.name),
key[kKeyObject][kHandle],
data,
signature));
Expand Down
8 changes: 5 additions & 3 deletions lib/internal/crypto/ml_dsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const {
PublicKeyObject,
createPrivateKey,
createPublicKey,
kAlgorithm,
kKeyType,
} = require('internal/crypto/keys');

const generateKeyPair = promisify(_generateKeyPair);
Expand Down Expand Up @@ -116,7 +118,7 @@ function mlDsaExportKey(key, format) {
try {
switch (format) {
case kWebCryptoKeyFormatRaw: {
if (key.type === 'private') {
if (key[kKeyType] === 'private') {
const { priv } = key[kKeyObject][kHandle].exportJwk({}, false);
return Buffer.alloc(32, priv, 'base64url').buffer;
}
Expand All @@ -136,7 +138,7 @@ function mlDsaExportKey(key, format) {
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x03, 0x00, 0x04, 0x22, 0x80, 0x20,
], 0);
switch (key.algorithm.name) {
switch (key[kAlgorithm].name) {
case 'ML-DSA-44':
buffer.set([0x11], 17);
break;
Expand Down Expand Up @@ -292,7 +294,7 @@ function mlDsaSignVerify(key, data, algorithm, signature) {
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
const type = mode === kSignJobModeSign ? 'private' : 'public';

if (key.type !== type)
if (key[kKeyType] !== type)
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');

return jobPromise(() => new SignJob(
Expand Down
18 changes: 10 additions & 8 deletions lib/internal/crypto/rsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ const {
PublicKeyObject,
createPublicKey,
createPrivateKey,
kAlgorithm,
kKeyType,
} = require('internal/crypto/keys');

const {
Expand Down Expand Up @@ -95,7 +97,7 @@ function rsaOaepCipher(mode, key, data, algorithm) {
validateRsaOaepAlgorithm(algorithm);

const type = mode === kWebCryptoCipherEncrypt ? 'public' : 'private';
if (key.type !== type) {
if (key[kKeyType] !== type) {
throw lazyDOMException(
'The requested operation is not valid for the provided key',
'InvalidAccessError');
Expand All @@ -107,7 +109,7 @@ function rsaOaepCipher(mode, key, data, algorithm) {
key[kKeyObject][kHandle],
data,
kKeyVariantRSA_OAEP,
normalizeHashName(key.algorithm.hash.name),
normalizeHashName(key[kAlgorithm].hash.name),
algorithm.label));
}

Expand Down Expand Up @@ -201,7 +203,7 @@ function rsaExportKey(key, format) {
kCryptoJobAsync,
format,
key[kKeyObject][kHandle],
kRsaVariants[key.algorithm.name]));
kRsaVariants[key[kAlgorithm].name]));
}

function rsaImportKey(
Expand Down Expand Up @@ -329,16 +331,16 @@ function rsaSignVerify(key, data, { saltLength }, signature) {
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
const type = mode === kSignJobModeSign ? 'private' : 'public';

if (key.type !== type)
if (key[kKeyType] !== type)
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');

return jobPromise(() => {
if (key.algorithm.name === 'RSA-PSS') {
if (key[kAlgorithm].name === 'RSA-PSS') {
validateInt32(
saltLength,
'algorithm.saltLength',
0,
MathCeil((key.algorithm.modulusLength - 1) / 8) - getDigestSizeInBytes(key.algorithm.hash.name) - 2);
MathCeil((key[kAlgorithm].modulusLength - 1) / 8) - getDigestSizeInBytes(key[kAlgorithm].hash.name) - 2);
}

return new SignJob(
Expand All @@ -349,9 +351,9 @@ function rsaSignVerify(key, data, { saltLength }, signature) {
undefined,
undefined,
data,
normalizeHashName(key.algorithm.hash.name),
normalizeHashName(key[kAlgorithm].hash.name),
saltLength,
key.algorithm.name === 'RSA-PSS' ? RSA_PKCS1_PSS_PADDING : undefined,
key[kAlgorithm].name === 'RSA-PSS' ? RSA_PKCS1_PSS_PADDING : undefined,
undefined,
signature);
});
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,9 @@ const kSupportedAlgorithms = createSupportedAlgorithms(kAlgorithmDefinitions);

const simpleAlgorithmDictionaries = {
AeadParams: { iv: 'BufferSource', additionalData: 'BufferSource' },
RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier' },
// publicExponent is not strictly a BufferSource but it is a Uint8Array that we normalize
// this way
RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier', publicExponent: 'BufferSource' },
EcKeyGenParams: {},
HmacKeyGenParams: { hash: 'HashAlgorithmIdentifier' },
RsaPssParams: {},
Expand Down
Loading
Loading