Skip to content

Commit 845633a

Browse files
j0t3xaddaleax
authored andcommitted
crypto: better docs for cases where peer's public key is invalid
changes in c++ are in the computeSecret function, but the thrown exception that was moved to JS land was in BufferToPoint function, here i let the allocation error be thrown so the only value returned is the nullptr that i use later to catch the error in computeSecret, to then construct the exception in JS land. an ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY error was added to errors.js and with that, subsequent changes to docs and tests were made. PR-URL: #16849 Refs: https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf Fixes: #16625 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 31e0dbc commit 845633a

File tree

6 files changed

+41
-9
lines changed

6 files changed

+41
-9
lines changed

doc/api/crypto.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,11 @@ added: v0.11.14
651651
changes:
652652
- version: v6.0.0
653653
pr-url: https://github.com/nodejs/node/pull/5522
654-
description: The default `inputEncoding` changed from `binary` to `utf8`.
654+
description: The default `inputEncoding` changed from `binary` to `utf8`
655+
- version: REPLACEME
656+
pr-url: https://github.com/nodejs/node/pull/16849
657+
description: Changed error format to better support invalid public key
658+
error
655659
-->
656660
- `otherPublicKey` {string | Buffer | TypedArray | DataView}
657661
- `inputEncoding` {string}
@@ -668,6 +672,12 @@ provided, `otherPublicKey` is expected to be a [`Buffer`][], `TypedArray`, or
668672
If `outputEncoding` is given a string will be returned; otherwise a
669673
[`Buffer`][] is returned.
670674

675+
`ecdh.computeSecret` will throw an
676+
`ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY` error when `otherPublicKey`
677+
lies outside of the elliptic curve. Since `otherPublicKey` is
678+
usually supplied from a remote user over an insecure network,
679+
its recommended for developers to handle this exception accordingly.
680+
671681
### ecdh.generateKeys([encoding[, format]])
672682
<!-- YAML
673683
added: v0.11.14

doc/api/errors.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,13 @@ of OpenSSL being used.
676676
An invalid value for the `format` argument was passed to the `crypto.ECDH()`
677677
class `getPublicKey()` method.
678678

679+
<a id="ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY"></a>
680+
### ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
681+
682+
An invalid value for the `key` argument has been passed to the
683+
`crypto.ECDH()` class `computeSecret()` method. It means that the public
684+
key lies outside of the elliptic curve.
685+
679686
<a id="ERR_CRYPTO_ENGINE_UNKNOWN"></a>
680687
### ERR_CRYPTO_ENGINE_UNKNOWN
681688

lib/internal/crypto/diffiehellman.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ function dhComputeSecret(key, inEnc, outEnc) {
9696
inEnc = inEnc || encoding;
9797
outEnc = outEnc || encoding;
9898
var ret = this._handle.computeSecret(toBuf(key, inEnc));
99+
if (typeof ret === 'string')
100+
throw new errors.Error('ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY');
99101
if (outEnc && outEnc !== 'buffer')
100102
ret = ret.toString(outEnc);
101103
return ret;

lib/internal/errors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s');
281281
E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
282282
'Custom engines not supported by this OpenSSL');
283283
E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s');
284+
E('ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
285+
'Public key is not valid for specified curve');
284286
E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found');
285287
E('ERR_CRYPTO_FIPS_FORCED',
286288
'Cannot set FIPS mode, it was forced with --force-fips at startup.');

src/node_crypto.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5220,7 +5220,6 @@ EC_POINT* ECDH::BufferToPoint(char* data, size_t len) {
52205220
len,
52215221
nullptr);
52225222
if (!r) {
5223-
env()->ThrowError("Failed to translate Buffer to a EC_POINT");
52245223
goto fatal;
52255224
}
52265225

@@ -5247,8 +5246,12 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
52475246

52485247
EC_POINT* pub = ecdh->BufferToPoint(Buffer::Data(args[0]),
52495248
Buffer::Length(args[0]));
5250-
if (pub == nullptr)
5249+
if (pub == nullptr) {
5250+
args.GetReturnValue().Set(
5251+
FIXED_ONE_BYTE_STRING(env->isolate(),
5252+
"ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY"));
52515253
return;
5254+
}
52525255

52535256
// NOTE: field_size is in bits
52545257
int field_size = EC_GROUP_get_degree(ecdh->group_);

test/parallel/test-crypto-dh.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,13 @@ if (availableCurves.has('prime256v1') && availableCurves.has('secp256k1')) {
222222
const ecdh3 = crypto.createECDH('secp256k1');
223223
const key3 = ecdh3.generateKeys();
224224

225-
assert.throws(() => {
226-
ecdh2.computeSecret(key3, 'latin1', 'buffer');
227-
}, /^Error: Failed to translate Buffer to a EC_POINT$/);
225+
common.expectsError(
226+
() => ecdh2.computeSecret(key3, 'latin1', 'buffer'),
227+
{
228+
code: 'ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
229+
type: Error,
230+
message: 'Public key is not valid for specified curve'
231+
});
228232

229233
// ECDH should allow .setPrivateKey()/.setPublicKey()
230234
const ecdh4 = crypto.createECDH('prime256v1');
@@ -331,9 +335,13 @@ if (availableCurves.has('prime256v1') && availableHashes.has('sha256')) {
331335
const invalidKey = Buffer.alloc(65);
332336
invalidKey.fill('\0');
333337
curve.generateKeys();
334-
assert.throws(() => {
335-
curve.computeSecret(invalidKey);
336-
}, /^Error: Failed to translate Buffer to a EC_POINT$/);
338+
common.expectsError(
339+
() => curve.computeSecret(invalidKey),
340+
{
341+
code: 'ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
342+
type: Error,
343+
message: 'Public key is not valid for specified curve'
344+
});
337345
// Check that signing operations are not impacted by the above error.
338346
const ecPrivateKey =
339347
'-----BEGIN EC PRIVATE KEY-----\n' +

0 commit comments

Comments
 (0)