diff options
-rw-r--r-- | cli/tests/unit_node/crypto/crypto_hash_test.ts | 18 | ||||
-rw-r--r-- | ext/node/lib.rs | 2 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/_randomFill.mjs | 90 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/_randomFill.ts | 94 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/random.ts | 4 | ||||
-rw-r--r-- | tools/core_import_map.json | 2 |
6 files changed, 111 insertions, 99 deletions
diff --git a/cli/tests/unit_node/crypto/crypto_hash_test.ts b/cli/tests/unit_node/crypto/crypto_hash_test.ts index e140765ec..4b0aedf03 100644 --- a/cli/tests/unit_node/crypto/crypto_hash_test.ts +++ b/cli/tests/unit_node/crypto/crypto_hash_test.ts @@ -1,5 +1,11 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -import { createHash, createHmac, getHashes, randomUUID } from "node:crypto"; +import { + createHash, + createHmac, + getHashes, + randomFillSync, + randomUUID, +} from "node:crypto"; import { Buffer } from "node:buffer"; import { Readable } from "node:stream"; import { @@ -124,3 +130,13 @@ Deno.test("[node/crypto.getRandomUUID] works the same way as Web Crypto API", () assertEquals(randomUUID().length, crypto.randomUUID().length); assertEquals(typeof randomUUID(), typeof crypto.randomUUID()); }); + +Deno.test("[node/crypto.randomFillSync] supported arguments", () => { + const buf = new Uint8Array(10); + + assert(randomFillSync(buf)); + assert(randomFillSync(buf, 0)); + // @ts-ignore: arraybuffer arguments are valid. + assert(randomFillSync(buf.buffer)); + assert(randomFillSync(new DataView(buf.buffer))); +}); diff --git a/ext/node/lib.rs b/ext/node/lib.rs index fbc1c9ffd..c7ca2ca72 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -388,7 +388,7 @@ deno_core::extension!(deno_node, "internal/constants.ts", "internal/crypto/_keys.ts", "internal/crypto/_randomBytes.ts", - "internal/crypto/_randomFill.ts", + "internal/crypto/_randomFill.mjs", "internal/crypto/_randomInt.ts", "internal/crypto/certificate.ts", "internal/crypto/cipher.ts", diff --git a/ext/node/polyfills/internal/crypto/_randomFill.mjs b/ext/node/polyfills/internal/crypto/_randomFill.mjs new file mode 100644 index 000000000..6afc654b4 --- /dev/null +++ b/ext/node/polyfills/internal/crypto/_randomFill.mjs @@ -0,0 +1,90 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +// TODO(petamoriken): enable prefer-primordials for node polyfills +// deno-lint-ignore-file prefer-primordials + +import { + MAX_SIZE as kMaxUint32, +} from "ext:deno_node/internal/crypto/_randomBytes.ts"; +import { Buffer } from "node:buffer"; +import { isAnyArrayBuffer, isArrayBufferView } from "node:util/types"; +import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; +const { core } = globalThis.__bootstrap; +const { ops } = core; + +const kBufferMaxLength = 0x7fffffff; + +function assertOffset(offset, length) { + if (offset > kMaxUint32 || offset < 0) { + throw new TypeError("offset must be a uint32"); + } + + if (offset > kBufferMaxLength || offset > length) { + throw new RangeError("offset out of range"); + } +} + +function assertSize(size, offset, length) { + if (size > kMaxUint32 || size < 0) { + throw new TypeError("size must be a uint32"); + } + + if (size + offset > length || size > kBufferMaxLength) { + throw new RangeError("buffer too small"); + } +} + +export default function randomFill( + buf, + offset, + size, + cb, +) { + if (typeof offset === "function") { + cb = offset; + offset = 0; + size = buf.length; + } else if (typeof size === "function") { + cb = size; + size = buf.length - Number(offset); + } + + assertOffset(offset, buf.length); + assertSize(size, offset, buf.length); + + core.opAsync("op_node_generate_secret_async", Math.floor(size)) + .then( + (randomData) => { + const randomBuf = Buffer.from(randomData.buffer); + randomBuf.copy(buf, offset, 0, size); + cb(null, buf); + }, + ); +} + +export function randomFillSync(buf, offset = 0, size) { + if (!isAnyArrayBuffer(buf) && !isArrayBufferView(buf)) { + throw new ERR_INVALID_ARG_TYPE( + "buf", + ["ArrayBuffer", "ArrayBufferView"], + buf, + ); + } + + assertOffset(offset, buf.byteLength); + + if (size === undefined) { + size = buf.byteLength - offset; + } else { + assertSize(size, offset, buf.byteLength); + } + + if (size === 0) { + return buf; + } + + const bytes = new Uint8Array(buf.buffer ? buf.buffer : buf, offset, size); + ops.op_node_generate_secret(bytes); + + return buf; +} diff --git a/ext/node/polyfills/internal/crypto/_randomFill.ts b/ext/node/polyfills/internal/crypto/_randomFill.ts deleted file mode 100644 index 927acaf8d..000000000 --- a/ext/node/polyfills/internal/crypto/_randomFill.ts +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials - -import { - MAX_SIZE as kMaxUint32, -} from "ext:deno_node/internal/crypto/_randomBytes.ts"; -import { Buffer } from "node:buffer"; -const { core } = globalThis.__bootstrap; -const { ops } = core; - -const kBufferMaxLength = 0x7fffffff; - -function assertOffset(offset: number, length: number) { - if (offset > kMaxUint32 || offset < 0) { - throw new TypeError("offset must be a uint32"); - } - - if (offset > kBufferMaxLength || offset > length) { - throw new RangeError("offset out of range"); - } -} - -function assertSize(size: number, offset: number, length: number) { - if (size > kMaxUint32 || size < 0) { - throw new TypeError("size must be a uint32"); - } - - if (size + offset > length || size > kBufferMaxLength) { - throw new RangeError("buffer too small"); - } -} - -export default function randomFill( - buf: Buffer, - cb: (err: Error | null, buf: Buffer) => void, -): void; - -export default function randomFill( - buf: Buffer, - offset: number, - cb: (err: Error | null, buf: Buffer) => void, -): void; - -export default function randomFill( - buf: Buffer, - offset: number, - size: number, - cb: (err: Error | null, buf: Buffer) => void, -): void; - -export default function randomFill( - buf: Buffer, - offset?: number | ((err: Error | null, buf: Buffer) => void), - size?: number | ((err: Error | null, buf: Buffer) => void), - cb?: (err: Error | null, buf: Buffer) => void, -) { - if (typeof offset === "function") { - cb = offset; - offset = 0; - size = buf.length; - } else if (typeof size === "function") { - cb = size; - size = buf.length - Number(offset as number); - } - - assertOffset(offset as number, buf.length); - assertSize(size as number, offset as number, buf.length); - - 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) { - assertOffset(offset, buf.length); - - if (size === undefined) size = buf.length - offset; - - assertSize(size, offset, buf.length); - - 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/random.ts b/ext/node/polyfills/internal/crypto/random.ts index a02d232e8..e8776cdf0 100644 --- a/ext/node/polyfills/internal/crypto/random.ts +++ b/ext/node/polyfills/internal/crypto/random.ts @@ -8,7 +8,7 @@ import { notImplemented } from "ext:deno_node/_utils.ts"; import randomBytes from "ext:deno_node/internal/crypto/_randomBytes.ts"; import randomFill, { randomFillSync, -} from "ext:deno_node/internal/crypto/_randomFill.ts"; +} from "ext:deno_node/internal/crypto/_randomFill.mjs"; import randomInt from "ext:deno_node/internal/crypto/_randomInt.ts"; import { validateBoolean, @@ -29,7 +29,7 @@ export { default as randomBytes } from "ext:deno_node/internal/crypto/_randomByt export { default as randomFill, randomFillSync, -} from "ext:deno_node/internal/crypto/_randomFill.ts"; +} from "ext:deno_node/internal/crypto/_randomFill.mjs"; export { default as randomInt } from "ext:deno_node/internal/crypto/_randomInt.ts"; const primordials = globalThis.__bootstrap.primordials; diff --git a/tools/core_import_map.json b/tools/core_import_map.json index b75c3a9bb..3c1d65f93 100644 --- a/tools/core_import_map.json +++ b/tools/core_import_map.json @@ -105,7 +105,7 @@ "ext:deno_node/internal/constants.ts": "../ext/node/polyfills/internal/constants.ts", "ext:deno_node/internal/crypto/_keys.ts": "../ext/node/polyfills/internal/crypto/_keys.ts", "ext:deno_node/internal/crypto/_randomBytes.ts": "../ext/node/polyfills/internal/crypto/_randomBytes.ts", - "ext:deno_node/internal/crypto/_randomFill.ts": "../ext/node/polyfills/internal/crypto/_randomFill.ts", + "ext:deno_node/internal/crypto/_randomFill.mjs": "../ext/node/polyfills/internal/crypto/_randomFill.mjs", "ext:deno_node/internal/crypto/_randomInt.ts": "../ext/node/polyfills/internal/crypto/_randomInt.ts", "ext:deno_node/internal/crypto/certificate.ts": "../ext/node/polyfills/internal/crypto/certificate.ts", "ext:deno_node/internal/crypto/cipher.ts": "../ext/node/polyfills/internal/crypto/cipher.ts", |