Last active
October 3, 2022 02:21
-
-
Save CMCDragonkai/bcfdf2a40b520e92180aec3371d14e46 to your computer and use it in GitHub Desktop.
Get Random Bytes from Webcrypto #webcrypto #js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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 | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.