crypto: accept key data in crypto.diffieHellman() and cleanup DH jobs by panva · Pull Request #62527 · nodejs/node · GitHub
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
29 changes: 19 additions & 10 deletions doc/api/crypto.md
13 changes: 7 additions & 6 deletions lib/internal/crypto/cipher.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ const { normalizeEncoding } = require('internal/util');
const { StringDecoder } = require('string_decoder');

function rsaFunctionFor(method, defaultPadding, keyType) {
return (options, buffer) => {
const keyName = keyType === 'private' ? 'privateKey' : undefined;
return (key, buffer) => {
const { format, type, data, passphrase, namedCurve } =
keyType === 'private' ?
preparePrivateKey(options) :
preparePublicOrPrivateKey(options);
const padding = options.padding || defaultPadding;
const { oaepHash, encoding } = options;
let { oaepLabel } = options;
preparePrivateKey(key, keyName) :
preparePublicOrPrivateKey(key, keyName);
const padding = key.padding || defaultPadding;
const { oaepHash, encoding } = key;
let { oaepLabel } = key;
if (oaepHash !== undefined)
validateString(oaepHash, 'key.oaepHash');
if (oaepLabel !== undefined)
Expand Down
79 changes: 61 additions & 18 deletions lib/internal/crypto/diffiehellman.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const {
DiffieHellman: _DiffieHellman,
DiffieHellmanGroup: _DiffieHellmanGroup,
ECDH: _ECDH,
ECDHBitsJob,
ECDHConvertKey: _ECDHConvertKey,
kCryptoJobAsync,
kCryptoJobSync,
Expand Down Expand Up @@ -52,9 +51,11 @@ const {
} = require('internal/util');

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

const {
Expand Down Expand Up @@ -284,31 +285,65 @@ function diffieHellman(options, callback) {
validateFunction(callback, 'callback');

const { privateKey, publicKey } = options;
if (!(privateKey instanceof KeyObject))

// TODO(@panva): remove these non-semver-major error code preserving measures
// in a semver-major followup, the final state is just preparePublicOrPrivateKey
// and preparePrivateKey
if (privateKey == null)
throw new ERR_INVALID_ARG_VALUE('options.privateKey', privateKey);

if (!(publicKey instanceof KeyObject))
if (publicKey == null)
throw new ERR_INVALID_ARG_VALUE('options.publicKey', publicKey);

if (privateKey.type !== 'private')
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(privateKey.type, 'private');
if (isKeyObject(privateKey)) {
if (privateKey.type !== 'private')
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(privateKey.type, 'private');
}

if (publicKey.type !== 'public' && publicKey.type !== 'private') {
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(publicKey.type,
'private or public');
if (isKeyObject(publicKey)) {
if (publicKey.type !== 'public' && publicKey.type !== 'private') {
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(publicKey.type,
'private or public');
}
}

const privateType = privateKey.asymmetricKeyType;
const publicType = publicKey.asymmetricKeyType;
if (privateType !== publicType || !dhEnabledKeyTypes.has(privateType)) {
throw new ERR_CRYPTO_INCOMPATIBLE_KEY('key types for Diffie-Hellman',
`${privateType} and ${publicType}`);
if (isKeyObject(privateKey) && isKeyObject(publicKey)) {
const privateType = privateKey.asymmetricKeyType;
const publicType = publicKey.asymmetricKeyType;
if (privateType !== publicType || !dhEnabledKeyTypes.has(privateType)) {
throw new ERR_CRYPTO_INCOMPATIBLE_KEY('key types for Diffie-Hellman',
`${privateType} and ${publicType}`);
}
}

const {
data: pubData,
format: pubFormat,
type: pubType,
passphrase: pubPassphrase,
namedCurve: pubNamedCurve,
} = preparePublicOrPrivateKey(publicKey, 'options.publicKey');

const {
data: privData,
format: privFormat,
type: privType,
passphrase: privPassphrase,
namedCurve: privNamedCurve,
} = preparePrivateKey(privateKey, 'options.privateKey');

const job = new DHBitsJob(
callback ? kCryptoJobAsync : kCryptoJobSync,
publicKey[kHandle],
privateKey[kHandle]);
pubData,
pubFormat,
pubType,
pubPassphrase,
pubNamedCurve,
privData,
privFormat,
privType,
privPassphrase,
privNamedCurve);

if (!callback) {
const { 0: err, 1: secret } = job.run();
Expand Down Expand Up @@ -349,10 +384,18 @@ async function ecdhDeriveBits(algorithm, baseKey, length) {
throw lazyDOMException('Named curve mismatch', 'InvalidAccessError');
}

const bits = await jobPromise(() => new ECDHBitsJob(
const bits = await jobPromise(() => new DHBitsJob(
kCryptoJobAsync,
key[kKeyObject][kHandle],
baseKey[kKeyObject][kHandle]));
undefined,
undefined,
undefined,
undefined,
baseKey[kKeyObject][kHandle],
undefined,
undefined,
undefined,
undefined));

// If a length is not specified, return the full derived secret
if (length === null)
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ function parseKeyEncoding(keyType, options = kEmptyObject) {
format: publicFormat,
type: publicType,
} = parsePublicKeyEncoding(publicKeyEncoding, keyType,
'publicKeyEncoding'));
'options.publicKeyEncoding'));
} else {
throw new ERR_INVALID_ARG_VALUE('options.publicKeyEncoding',
publicKeyEncoding);
Expand All @@ -164,7 +164,7 @@ function parseKeyEncoding(keyType, options = kEmptyObject) {
cipher,
passphrase,
} = parsePrivateKeyEncoding(privateKeyEncoding, keyType,
'privateKeyEncoding'));
'options.privateKeyEncoding'));
} else {
throw new ERR_INVALID_ARG_VALUE('options.privateKeyEncoding',
privateKeyEncoding);
Expand Down
38 changes: 19 additions & 19 deletions lib/internal/crypto/keys.js
Loading
Loading