diff options
Diffstat (limited to 'ext/node/polyfills/internal/crypto/_randomFill.mjs')
-rw-r--r-- | ext/node/polyfills/internal/crypto/_randomFill.mjs | 90 |
1 files changed, 90 insertions, 0 deletions
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; +} |