Skip to content

Instantly share code, notes, and snippets.

@CMCDragonkai
Last active October 3, 2022 02:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CMCDragonkai/bcfdf2a40b520e92180aec3371d14e46 to your computer and use it in GitHub Desktop.
Save CMCDragonkai/bcfdf2a40b520e92180aec3371d14e46 to your computer and use it in GitHub Desktop.
Get Random Bytes from Webcrypto #webcrypto #js
/**
* Webcrypto random bytes is limited to 65,536 in one call.
* The below functions will make repeated calls to acquire random bytes.
*/
const webcrypto = globalThis.crypto?.webcrypto || globalThis.window?.crypto;
async function sleep(ms: number): Promise<void> {
return await new Promise<void>((r) => setTimeout(r, ms));
}
/**
* Get random bytes asynchronously.
* This yields the event loop each 65,536 bytes.
*/
async function getRandomBytes(size: number): Promise<Buffer> {
const randomBytes = Buffer.allocUnsafe(size);
let i = 0;
while (size > 0) {
// Webcrypto limits a max 65,536 random bytes at a time
const chunkSize = Math.min(size, 65536);
const chunk = randomBytes.slice(i, chunkSize);
webcrypto.getRandomValues(chunk);
i += chunkSize;
size -= chunkSize;
if (size > 0) {
await sleep(0);
}
}
return randomBytes;
}
/**
* Get random bytes synchronously.
* This loops each 65,536 bytes until the buffer is filled.
*/
function getRandomBytesSync(size: number): Buffer {
const randomBytes = Buffer.allocUnsafe(size);
let i = 0;
while (size > 0) {
const chunkSize = Math.min(size, 65536);
const chunk = randomBytes.slice(i, chunkSize);
webcrypto.getRandomValues(chunk);
i += chunkSize;
size -= chunkSize;
}
return randomBytes;
}
export {
getRandomBytes,
getRandomBytesSync
};
@CMCDragonkai
Copy link
Author

I'm using libsodium now which doesn't have this limitation, so we don't really need an async and sync functions and we can produce as much data as we want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment