Commit 52b68e01a0e for nodejs

commit 52b68e01a0e49110811e42dc7f96ef3f76139952
Author: Mert Can Altin <mertgold60@gmail.com>
Date:   Sat Oct 3 11:32:22 2026 +0300

    crypto: improve random synchronous number generation performance

    Instead of creating a RandomBytesJob object, it calls CSPRNG()
    directly now.

    Assisted-by: Claude Code
    Signed-off-by: Mert Can Altin <mertgold60@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66348
    Reviewed-By: Filip Skokan <panva.ip@gmail.com>
    Reviewed-By: James M Snell <jasnell@gmail.com>

diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js
index 10bd2627b0b..c53494aed84 100644
--- a/lib/internal/crypto/random.js
+++ b/lib/internal/crypto/random.js
@@ -34,6 +34,7 @@ const {
   CheckPrimeJob,
   kCryptoJobAsync,
   kCryptoJobSync,
+  randomFillSync: randomFillSyncImpl,
   secureBuffer,
 } = internalBinding('crypto');

@@ -175,16 +176,7 @@ function randomFillSync(buf, offset = 0, size) {
   if (size === 0)
     return buf;

-  const job = new RandomBytesJob(
-    kCryptoJobSync,
-    buf,
-    offset,
-    size);
-
-  const err = job.run()[0];
-  if (err)
-    throw err;
-
+  randomFillSyncImpl(buf, offset, size);
   return buf;
 }

diff --git a/src/crypto/crypto_random.cc b/src/crypto/crypto_random.cc
index 0318d9157b9..c80eb2c800a 100644
--- a/src/crypto/crypto_random.cc
+++ b/src/crypto/crypto_random.cc
@@ -214,13 +214,47 @@ MaybeLocal<Value> CheckPrimeTraits::EncodeOutput(Environment* env,
 }

 namespace Random {
+static void RandomFillSync(const FunctionCallbackInfo<Value>& args) {
+  Environment* env = Environment::GetCurrent(args);
+  CHECK(IsAnyBufferSource(args[0]));  // Buffer to fill
+  CHECK(args[1]->IsUint32());         // Offset
+  CHECK(args[2]->IsUint32());         // Size
+
+  ArrayBufferOrViewContents<unsigned char> in(args[0]);
+
+  const uint32_t byte_offset = args[1].As<Uint32>()->Value();
+  const uint32_t size = args[2].As<Uint32>()->Value();
+  CHECK_GE(byte_offset + size, byte_offset);  // Overflow check.
+  CHECK_LE(byte_offset + size, in.size());    // Bounds check.
+
+  env->PrintSyncTrace();
+  if (ERR_peek_error() != 0) ERR_clear_error();
+  if (ncrypto::CSPRNG(in.data() + byte_offset, size)) {
+    if (ERR_peek_error() != 0) ERR_clear_error();
+    return;
+  }
+
+  CryptoErrorStore errors;
+  errors.Capture();
+  if (errors.Empty()) {
+    errors.Insert(NodeCryptoError::DERIVING_BITS_FAILED);
+    errors.SetNodeErrorCode("ERR_CRYPTO_OPERATION_FAILED");
+  }
+  Local<Value> exception;
+  if (errors.ToException(env).ToLocal(&exception)) {
+    env->isolate()->ThrowException(exception);
+  }
+}
+
 void Initialize(Environment* env, Local<Object> target) {
+  SetMethod(env->context(), target, "randomFillSync", RandomFillSync);
   RandomBytesJob::Initialize(env, target);
   RandomPrimeJob::Initialize(env, target);
   CheckPrimeJob::Initialize(env, target);
 }

 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
+  registry->Register(RandomFillSync);
   RandomBytesJob::RegisterExternalReferences(registry);
   RandomPrimeJob::RegisterExternalReferences(registry);
   CheckPrimeJob::RegisterExternalReferences(registry);
diff --git a/test/parallel/test-crypto-randomfillsync-trace-sync-io.js b/test/parallel/test-crypto-randomfillsync-trace-sync-io.js
new file mode 100644
index 00000000000..8f9461f19f3
--- /dev/null
+++ b/test/parallel/test-crypto-randomfillsync-trace-sync-io.js
@@ -0,0 +1,23 @@
+'use strict';
+const common = require('../common');
+if (!common.hasCrypto)
+  common.skip('missing crypto');
+
+const assert = require('assert');
+const { spawnSync } = require('child_process');
+
+// randomFillSync() should be reported by --trace-sync-io when it runs after
+// the first event loop turn.
+
+if (process.argv[2] === 'child') {
+  setImmediate(() => {
+    require('crypto').randomFillSync(Buffer.alloc(16));
+  });
+  return;
+}
+
+const { stderr, status } = spawnSync(process.execPath,
+                                     ['--trace-sync-io', __filename, 'child'],
+                                     { encoding: 'utf8' });
+assert.strictEqual(status, 0);
+assert.match(stderr, /WARNING: Detected use of sync API[\s\S]*randomFillSync/);
diff --git a/typings/internalBinding/crypto.d.ts b/typings/internalBinding/crypto.d.ts
index e12016ec916..22ee303f599 100644
--- a/typings/internalBinding/crypto.d.ts
+++ b/typings/internalBinding/crypto.d.ts
@@ -1002,6 +1002,7 @@ export interface CryptoBinding {
   privateEncrypt: InternalCryptoBinding.PublicKeyCipher;
   publicDecrypt: InternalCryptoBinding.PublicKeyCipher;
   publicEncrypt: InternalCryptoBinding.PublicKeyCipher;
+  randomFillSync(buf: ArrayBufferLike | ArrayBufferView, offset: number, size: number): void;
   resetRootCertStore(): void;
   secureBuffer(length: number): Uint8Array | undefined;
   secureHeapUsed(): bigint | undefined;