diff options
author | Tobias Nießen <tniessen@tnie.de> | 2020-01-03 12:01:34 +0100 |
---|---|---|
committer | Tobias Nießen <tniessen@tnie.de> | 2020-01-21 10:49:20 -0400 |
commit | b4f8537cdc6f894c5e90bb8bf29a90a2db1438ca (patch) | |
tree | 41c24bf11d787366304cb64239344bdc1c55230b /lib | |
parent | c6f8ea8d6578fd1f167bc943272eca5806224d2f (diff) | |
download | node-new-b4f8537cdc6f894c5e90bb8bf29a90a2db1438ca.tar.gz |
crypto: add crypto.diffieHellman
Currently, Node.js has separate (stateful) APIs for DH/ECDH, and no
support for ECDH-ES. This commit adds a single stateless function to
compute the DH/ECDH/ECDH-ES secret based on two KeyObjects.
PR-URL: https://github.com/nodejs/node/pull/31178
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/crypto.js | 4 | ||||
-rw-r--r-- | lib/internal/crypto/diffiehellman.js | 44 | ||||
-rw-r--r-- | lib/internal/errors.js | 1 |
3 files changed, 45 insertions, 4 deletions
diff --git a/lib/crypto.js b/lib/crypto.js index e2d1875d8d..cec0b2c094 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -70,7 +70,8 @@ const { const { DiffieHellman, DiffieHellmanGroup, - ECDH + ECDH, + diffieHellman } = require('internal/crypto/diffiehellman'); const { Cipher, @@ -163,6 +164,7 @@ module.exports = { createSecretKey, createSign, createVerify, + diffieHellman, getCiphers, getCurves, getDiffieHellman: createDiffieHellmanGroup, diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index da8f87bf16..ae6b68b73b 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -2,16 +2,21 @@ const { ObjectDefineProperty, + Set } = primordials; const { Buffer } = require('buffer'); const { ERR_CRYPTO_ECDH_INVALID_FORMAT, ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY, - ERR_INVALID_ARG_TYPE + ERR_CRYPTO_INCOMPATIBLE_KEY, + ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_OPT_VALUE } = require('internal/errors').codes; const { validateString } = require('internal/validators'); const { isArrayBufferView } = require('internal/util/types'); +const { KeyObject } = require('internal/crypto/keys'); const { getDefaultEncoding, kHandle, @@ -21,7 +26,8 @@ const { DiffieHellman: _DiffieHellman, DiffieHellmanGroup: _DiffieHellmanGroup, ECDH: _ECDH, - ECDHConvertKey: _ECDHConvertKey + ECDHConvertKey: _ECDHConvertKey, + statelessDH } = internalBinding('crypto'); const { POINT_CONVERSION_COMPRESSED, @@ -232,8 +238,40 @@ function getFormat(format) { return POINT_CONVERSION_UNCOMPRESSED; } +const dhEnabledKeyTypes = new Set(['dh', 'ec', 'x448', 'x25519']); + +function diffieHellman(options) { + if (typeof options !== 'object') + throw new ERR_INVALID_ARG_TYPE('options', 'object', options); + + const { privateKey, publicKey } = options; + if (!(privateKey instanceof KeyObject)) + throw new ERR_INVALID_OPT_VALUE('privateKey', privateKey); + + if (!(publicKey instanceof KeyObject)) + throw new ERR_INVALID_OPT_VALUE('publicKey', publicKey); + + 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'); + } + + 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}`); + } + + return statelessDH(privateKey[kHandle], publicKey[kHandle]); +} + module.exports = { DiffieHellman, DiffieHellmanGroup, - ECDH + ECDH, + diffieHellman }; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 936a5253c7..edd286a20a 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -767,6 +767,7 @@ E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.', Error); E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error); E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error); +E('ERR_CRYPTO_INCOMPATIBLE_KEY', 'Incompatible %s: %s', Error); E('ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS', 'The selected key encoding %s %s.', Error); E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s', TypeError); |