summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit_node/internal/_randomFill_test.ts7
-rw-r--r--ext/node/crypto/mod.rs12
-rw-r--r--ext/node/lib.rs1
-rw-r--r--ext/node/polyfills/internal/crypto/_randomFill.ts24
-rw-r--r--ext/node/polyfills/internal/crypto/_randomInt.ts11
5 files changed, 37 insertions, 18 deletions
diff --git a/cli/tests/unit_node/internal/_randomFill_test.ts b/cli/tests/unit_node/internal/_randomFill_test.ts
index 00ff029cc..5e2e154c8 100644
--- a/cli/tests/unit_node/internal/_randomFill_test.ts
+++ b/cli/tests/unit_node/internal/_randomFill_test.ts
@@ -6,6 +6,7 @@ import {
assertNotEquals,
assertThrows,
} from "../../../../test_util/std/testing/asserts.ts";
+import { deferred } from "../../../../test_util/std/async/deferred.ts";
const validateNonZero = (buf: Buffer) => {
if (!buf.some((ch) => ch > 0)) throw new Error("Error");
@@ -15,14 +16,18 @@ const validateZero = (buf: Buffer) => {
buf.forEach((val) => assertEquals(val, 0));
};
-Deno.test("[node/crypto.randomFill]", () => {
+Deno.test("[node/crypto.randomFill]", async () => {
+ const promise = deferred();
const buf = Buffer.alloc(10);
const before = buf.toString("hex");
randomFill(buf, 5, 5, (_err, bufTwo) => {
const after = bufTwo?.toString("hex");
assertEquals(before.slice(0, 10), after?.slice(0, 10));
+ promise.resolve(true);
});
+
+ await promise;
});
Deno.test("[node/crypto.randomFillSync]", () => {
diff --git a/ext/node/crypto/mod.rs b/ext/node/crypto/mod.rs
index 55a7a5870..f818b96af 100644
--- a/ext/node/crypto/mod.rs
+++ b/ext/node/crypto/mod.rs
@@ -9,6 +9,8 @@ use deno_core::StringOrBuffer;
use deno_core::ZeroCopyBuf;
use hkdf::Hkdf;
use num_bigint::BigInt;
+use rand::distributions::Distribution;
+use rand::distributions::Uniform;
use rand::Rng;
use std::future::Future;
use std::rc::Rc;
@@ -478,3 +480,13 @@ pub async fn op_node_hkdf_async(
})
.await?
}
+
+#[op]
+pub fn op_node_random_int(min: i32, max: i32) -> Result<i32, AnyError> {
+ let mut rng = rand::thread_rng();
+ // Uniform distribution is required to avoid Modulo Bias
+ // https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#Modulo_bias
+ let dist = Uniform::from(min..max);
+
+ Ok(dist.sample(&mut rng))
+}
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 3ef761cb7..b73c3366f 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -194,6 +194,7 @@ deno_core::extension!(deno_node,
crypto::op_node_generate_secret,
crypto::op_node_generate_secret_async,
crypto::op_node_sign,
+ crypto::op_node_random_int,
crypto::x509::op_node_x509_parse,
crypto::x509::op_node_x509_ca,
crypto::x509::op_node_x509_check_email,
diff --git a/ext/node/polyfills/internal/crypto/_randomFill.ts b/ext/node/polyfills/internal/crypto/_randomFill.ts
index ba8b9cbec..89c374c02 100644
--- a/ext/node/polyfills/internal/crypto/_randomFill.ts
+++ b/ext/node/polyfills/internal/crypto/_randomFill.ts
@@ -1,8 +1,10 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-import randomBytes, {
+import {
MAX_SIZE as kMaxUint32,
} from "ext:deno_node/internal/crypto/_randomBytes.ts";
import { Buffer } from "ext:deno_node/buffer.ts";
+const { core } = globalThis.__bootstrap;
+const { ops } = core;
const kBufferMaxLength = 0x7fffffff;
@@ -62,11 +64,14 @@ export default function randomFill(
assertOffset(offset as number, buf.length);
assertSize(size as number, offset as number, buf.length);
- randomBytes(size as number, (err, bytes) => {
- if (err) return cb!(err, buf);
- bytes?.copy(buf, offset as number);
- cb!(null, buf);
- });
+ core.opAsync("op_node_generate_secret_async", Math.floor(size as number))
+ .then(
+ (randomData: Uint8Array) => {
+ const randomBuf = Buffer.from(randomData.buffer);
+ randomBuf.copy(buf, offset as number, 0, size as number);
+ cb!(null, buf);
+ },
+ );
}
export function randomFillSync(buf: Buffer, offset = 0, size?: number) {
@@ -76,9 +81,10 @@ export function randomFillSync(buf: Buffer, offset = 0, size?: number) {
assertSize(size, offset, buf.length);
- const bytes = randomBytes(size);
-
- bytes.copy(buf, offset);
+ const bytes: Uint8Array = new Uint8Array(Math.floor(size));
+ ops.op_node_generate_secret(bytes);
+ const bytesBuf: Buffer = Buffer.from(bytes.buffer);
+ bytesBuf.copy(buf, offset, 0, size);
return buf;
}
diff --git a/ext/node/polyfills/internal/crypto/_randomInt.ts b/ext/node/polyfills/internal/crypto/_randomInt.ts
index 637251541..4e55eba9d 100644
--- a/ext/node/polyfills/internal/crypto/_randomInt.ts
+++ b/ext/node/polyfills/internal/crypto/_randomInt.ts
@@ -1,4 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+const ops = globalThis.Deno.core.ops;
+
export default function randomInt(max: number): number;
export default function randomInt(min: number, max: number): number;
export default function randomInt(
@@ -40,16 +42,9 @@ export default function randomInt(
throw new Error("Min is bigger than Max!");
}
- const randomBuffer = new Uint32Array(1);
-
- globalThis.crypto.getRandomValues(randomBuffer);
-
- const randomNumber = randomBuffer[0] / (0xffffffff + 1);
-
min = Math.ceil(min);
max = Math.floor(max);
-
- const result = Math.floor(randomNumber * (max - min)) + min;
+ const result = ops.op_node_random_int(min, max);
if (cb) {
cb(null, result);