GeezerVison is showing github.com — crypto: add optional callback to crypto.diffieHellman · nodejs/node@053cef7
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/crypto.md +11-2Lines changed: 11 additions & 2 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -3527,23 +3527,32 @@ the corresponding digest algorithm. This does not work for all signature | 3527 | 3527 | algorithms, such as `'ecdsa-with-SHA256'`, so it is best to always use digest | 3528 | 3528 | algorithm names. | 3529 | 3529 |
| 3530 | | -### `crypto.diffieHellman(options)` | | 3530 | +### `crypto.diffieHellman(options[, callback])` | 3531 | 3531 |
| 3532 | 3532 | <!-- YAML | 3533 | 3533 | added: | 3534 | 3534 | - v13.9.0 | 3535 | 3535 | - v12.17.0 | | 3536 | +changes: | | 3537 | + - version: REPLACEME | | 3538 | + pr-url: https://github.com/nodejs/node/pull/57274 | | 3539 | + description: Optional callback argument added. | 3536 | 3540 | --> | 3537 | 3541 |
| 3538 | 3542 | * `options`: {Object} | 3539 | 3543 | * `privateKey`: {KeyObject} | 3540 | 3544 | * `publicKey`: {KeyObject} | 3541 | | -* Returns: {Buffer} | | 3545 | +* `callback` {Function} | | 3546 | + * `err` {Error} | | 3547 | + * `secret` {Buffer} | | 3548 | +* Returns: {Buffer} if the `callback` function is not provided. | 3542 | 3549 |
| 3543 | 3550 | Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`. | 3544 | 3551 | Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'` | 3545 | 3552 | (for Diffie-Hellman), `'ec'`, `'x448'`, or `'x25519'` (for ECDH). | 3546 | 3553 |
| | 3554 | +If the `callback` function is provided this function uses libuv's threadpool. | | 3555 | + | 3547 | 3556 | ### `crypto.fips` | 3548 | 3557 |
| 3549 | 3558 | <!-- YAML | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/diffiehellman.js +26-3Lines changed: 26 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | const { | 4 | 4 | ArrayBufferPrototypeSlice, | | 5 | + FunctionPrototypeCall, | 5 | 6 | MathCeil, | 6 | 7 | ObjectDefineProperty, | 7 | 8 | SafeSet, | @@ -11,13 +12,14 @@ const { | 11 | 12 | const { Buffer } = require('buffer'); | 12 | 13 |
| 13 | 14 | const { | | 15 | + DHBitsJob, | 14 | 16 | DiffieHellman: _DiffieHellman, | 15 | 17 | DiffieHellmanGroup: _DiffieHellmanGroup, | 16 | 18 | ECDH: _ECDH, | 17 | 19 | ECDHBitsJob, | 18 | 20 | ECDHConvertKey: _ECDHConvertKey, | 19 | | - statelessDH, | 20 | 21 | kCryptoJobAsync, | | 22 | + kCryptoJobSync, | 21 | 23 | } = internalBinding('crypto'); | 22 | 24 |
| 23 | 25 | const { | @@ -32,6 +34,7 @@ const { | 32 | 34 | } = require('internal/errors'); | 33 | 35 |
| 34 | 36 | const { | | 37 | + validateFunction, | 35 | 38 | validateInt32, | 36 | 39 | validateObject, | 37 | 40 | validateString, | @@ -268,9 +271,12 @@ function getFormat(format) { | 268 | 271 |
| 269 | 272 | const dhEnabledKeyTypes = new SafeSet(['dh', 'ec', 'x448', 'x25519']); | 270 | 273 |
| 271 | | -function diffieHellman(options) { | | 274 | +function diffieHellman(options, callback) { | 272 | 275 | validateObject(options, 'options'); | 273 | 276 |
| | 277 | + if (callback !== undefined) | | 278 | + validateFunction(callback, 'callback'); | | 279 | + | 274 | 280 | const { privateKey, publicKey } = options; | 275 | 281 | if (!(privateKey instanceof KeyObject)) | 276 | 282 | throw new ERR_INVALID_ARG_VALUE('options.privateKey', privateKey); | @@ -293,7 +299,24 @@ function diffieHellman(options) { | 293 | 299 | `${privateType} and ${publicType}`); | 294 | 300 | } | 295 | 301 |
| 296 | | - return statelessDH(privateKey[kHandle], publicKey[kHandle]); | | 302 | + const job = new DHBitsJob( | | 303 | + callback ? kCryptoJobAsync : kCryptoJobSync, | | 304 | + publicKey[kHandle], | | 305 | + privateKey[kHandle]); | | 306 | + | | 307 | + if (!callback) { | | 308 | + const { 0: err, 1: secret } = job.run(); | | 309 | + if (err !== undefined) | | 310 | + throw err; | | 311 | + | | 312 | + return Buffer.from(secret); | | 313 | + } | | 314 | + | | 315 | + job.ondone = (error, secret) => { | | 316 | + if (error) return FunctionPrototypeCall(callback, job, error); | | 317 | + FunctionPrototypeCall(callback, job, null, Buffer.from(secret)); | | 318 | + }; | | 319 | + job.run(); | 297 | 320 | } | 298 | 321 |
| 299 | 322 | let masks; | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_dh.cc +16-47Lines changed: 16 additions & 47 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -483,49 +483,11 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport( | 483 | 483 | } | 484 | 484 | } | 485 | 485 |
| 486 | | -namespace { | 487 | | -ByteSource StatelessDiffieHellmanThreadsafe(const EVPKeyPointer& our_key, | 488 | | - const EVPKeyPointer& their_key) { | 489 | | - auto dp = DHPointer::stateless(our_key, their_key); | 490 | | - if (!dp) return {}; | 491 | | - DCHECK(!dp.isSecure()); | 492 | | - | 493 | | - return ByteSource::Allocated(dp.release()); | 494 | | -} | 495 | | - | 496 | | -void Stateless(const FunctionCallbackInfo<Value>& args) { | 497 | | - Environment* env = Environment::GetCurrent(args); | 498 | | - | 499 | | - CHECK(args[0]->IsObject() && args[1]->IsObject()); | 500 | | - KeyObjectHandle* our_key_object; | 501 | | - ASSIGN_OR_RETURN_UNWRAP(&our_key_object, args[0].As<Object>()); | 502 | | - CHECK_EQ(our_key_object->Data().GetKeyType(), kKeyTypePrivate); | 503 | | - KeyObjectHandle* their_key_object; | 504 | | - ASSIGN_OR_RETURN_UNWRAP(&their_key_object, args[1].As<Object>()); | 505 | | - CHECK_NE(their_key_object->Data().GetKeyType(), kKeyTypeSecret); | 506 | | - | 507 | | - const auto& our_key = our_key_object->Data().GetAsymmetricKey(); | 508 | | - const auto& their_key = their_key_object->Data().GetAsymmetricKey(); | 509 | | - | 510 | | - Local<Value> out; | 511 | | - if (!StatelessDiffieHellmanThreadsafe(our_key, their_key) | 512 | | - .ToBuffer(env) | 513 | | - .ToLocal(&out)) return; | 514 | | - | 515 | | - if (Buffer::Length(out) == 0) | 516 | | - return ThrowCryptoError(env, ERR_get_error(), "diffieHellman failed"); | 517 | | - | 518 | | - args.GetReturnValue().Set(out); | 519 | | -} | 520 | | -} // namespace | 521 | | - | 522 | 486 | Maybe<void> DHBitsTraits::AdditionalConfig( | 523 | 487 | CryptoJobMode mode, | 524 | 488 | const FunctionCallbackInfo<Value>& args, | 525 | 489 | unsigned int offset, | 526 | 490 | DHBitsConfig* params) { | 527 | | - Environment* env = Environment::GetCurrent(args); | 528 | | - | 529 | 491 | CHECK(args[offset]->IsObject()); // public key | 530 | 492 | CHECK(args[offset + 1]->IsObject()); // private key | 531 | 493 |
| @@ -535,11 +497,8 @@ Maybe<void> DHBitsTraits::AdditionalConfig( | 535 | 497 | ASSIGN_OR_RETURN_UNWRAP(&public_key, args[offset], Nothing<void>()); | 536 | 498 | ASSIGN_OR_RETURN_UNWRAP(&private_key, args[offset + 1], Nothing<void>()); | 537 | 499 |
| 538 | | - if (private_key->Data().GetKeyType() != kKeyTypePrivate || | 539 | | - public_key->Data().GetKeyType() != kKeyTypePublic) { | 540 | | - THROW_ERR_CRYPTO_INVALID_KEYTYPE(env); | 541 | | - return Nothing<void>(); | 542 | | - } | | 500 | + CHECK(private_key->Data().GetKeyType() == kKeyTypePrivate); | | 501 | + CHECK(public_key->Data().GetKeyType() != kKeyTypeSecret); | 543 | 502 |
| 544 | 503 | params->public_key = public_key->Data().addRef(); | 545 | 504 | params->private_key = private_key->Data().addRef(); | @@ -557,8 +516,20 @@ bool DHBitsTraits::DeriveBits( | 557 | 516 | Environment* env, | 558 | 517 | const DHBitsConfig& params, | 559 | 518 | ByteSource* out) { | 560 | | - *out = StatelessDiffieHellmanThreadsafe(params.private_key.GetAsymmetricKey(), | 561 | | - params.public_key.GetAsymmetricKey()); | | 519 | + auto dp = DHPointer::stateless(params.private_key.GetAsymmetricKey(), | | 520 | + params.public_key.GetAsymmetricKey()); | | 521 | + if (!dp) { | | 522 | + bool can_throw = | | 523 | + per_process::v8_initialized && Isolate::TryGetCurrent() != nullptr; | | 524 | + if (can_throw) { | | 525 | + unsigned long err = ERR_get_error(); // NOLINT(runtime/int) | | 526 | + if (err) ThrowCryptoError(env, err, "diffieHellman failed"); | | 527 | + } | | 528 | + return false; | | 529 | + } | | 530 | + | | 531 | + *out = ByteSource::Allocated(dp.release()); | | 532 | + CHECK(!out->empty()); | 562 | 533 | return true; | 563 | 534 | } | 564 | 535 |
| @@ -611,7 +582,6 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target) { | 611 | 582 | make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellmanGroup"), | 612 | 583 | DiffieHellmanGroup); | 613 | 584 |
| 614 | | - SetMethodNoSideEffect(context, target, "statelessDH", Stateless); | 615 | 585 | DHKeyPairGenJob::Initialize(env, target); | 616 | 586 | DHKeyExportJob::Initialize(env, target); | 617 | 587 | DHBitsJob::Initialize(env, target); | @@ -632,7 +602,6 @@ void DiffieHellman::RegisterExternalReferences( | 632 | 602 | registry->Register(SetPrivateKey); | 633 | 603 |
| 634 | 604 | registry->Register(Check); | 635 | | - registry->Register(Stateless); | 636 | 605 |
| 637 | 606 | DHKeyPairGenJob::RegisterExternalReferences(registry); | 638 | 607 | DHKeyExportJob::RegisterExternalReferences(registry); | |
|