Using crypto’s getRandomValues in Deno

Mayank C
Tech Tonic

--

Purpose

Deno follows web standards (https://developer.mozilla.org/en-US/docs/Web/API) wherever possible. This means that Deno attempts to provide access to most of the browser APIs that are developers are already using in front-end development. Deno has implemented a large number of web APIs including fetch, URL, WebSocket, FileReader, crypto, etc.

The purpose of crypto’s getRandomValues function is to generate 8/16/32 bit cryptographically strong random numbers. Here is a description directly from the specification:

Implementations should generate cryptographically random values using well-established cryptographic pseudo-random number generators seeded with high-quality entropy, such as from an operating-system entropy source (e.g., “/dev/urandom”).

Deno’s core runtime comes with an implementation ofgetRandomValues function that can generate strong random numbers efficiently. Internally, Deno uses Rust’s StdRng (https://docs.rs/rand/0.8.3/rand/rngs/struct.StdRng.html) to generate the numbers.

Usage

As per the specification, getRandomValues function takes a typed array as input and fills it with random numbers. Here are the supported types:

  • Int8Array: 8 bit signed random numbers
  • Uint8Array: 8 bit unsigned random numbers
  • Int16Array: 16 bit signed random numbers
  • Uint16Array: 16 bit unsigned random numbers
  • Int32Array: 32bit signed random numbers
  • Uint32Array: 32 bit unsigned random numbers
  • Uint8ClampedArray: 8 bit unsigned random numbers clamped at 255

The getRandomValues function would generate as many random numbers as needed to fill the given array. Here is the function signature:

getRandomValues(Array<Int8Array | Uint8ClampedArray | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array>)

The only limit is that it can fill up to 65536 bytes in a single call. An error is thrown if the input’s byte length is more than 65536. Note that this is not the same as the array length. Here are the typed arrays and max number of random numbers per call.

  • Uint8Array/Int8Array: Max random numbers 65536
  • Uint16Array/Int16Array: Max random numbers is 32768
  • Uint32Array/Int32Array: Max random numbers is 16384

To get cryptographically strong random numbers:

  • Create a typed array of required size
  • Call getRandomValues(typedArray)
  • The typed array will be filled with random numbers

Lastly, getRandomValues is a synchronous function. There is no async variant available.

Examples

Now that we’ve understood the usage, let’s go over examples of each type:

crypto.getRandomValues();
//TypeError: Argument 1 does not implement interface ArrayBufferView
const s:string[]=[];
crypto.getRandomValues(s);
//error: TS2345 [ERROR]: Argument of type 'string[]' is not assignable to parameter of type 'Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | null'
const a=new Uint8Array();
crypto.getRandomValues(a);
//a: Uint8Array(0) []
const a=new Uint8Array(555000);
crypto.getRandomValues(a);
//QuotaExceededError: The ArrayBufferView's byte length (555000) exceeds the number of bytes of entropy available via this API (65536)
const a=new Uint8Array(5);
crypto.getRandomValues(a);
//a: Uint8Array(5) [ 240, 120, 47, 56, 80 ]
const a=new Uint8Array(5000);
crypto.getRandomValues(a);
//a: Uint8Array(5000) [214, 180, 95, 1, 120, 35, 131, 144, 115, 118, 220, 34, 84, 72, 5, 235, 165, 187, 214, 255, 10, 222, 179, 198, 5, 125, 18, 90, 147, 85, 23, 55, 109, 62, 204, 55, 242, 250, 175, 95, 91, 251, 243, 104, 65, 182, 229, 176, 159, 210, 34, 86, 116, 116, 204, 145, 31, 251, 57, 63, 173, 100, 164, 4, 105, 17, 134, 19, 108, 17, 93, 255, 86, 174, 87, 213, 26, 213, 72, 217, 97, 133, 173, 238, 230, 209, 214, 73, 187, 4, 231, 32, 154, 245, 126, 87, 61, 14, 60, 199, ... 4900 more items]
const a=new Int8Array(10);
crypto.getRandomValues(a);
//a: Int8Array(10) [-84, 68, 63, -12, -6, 84, -124, 17, -79, 59]
const a=new Uint16Array(10);
crypto.getRandomValues(a);
//a: Uint16Array(10) [50173, 4222, 10547, 32445, 7291, 28683, 39454, 26341, 55900, 18756]
const a=new Int16Array(10);
crypto.getRandomValues(a);
//a: Int16Array(10) [5837, 7894, 19818, -3946, 31942, -5773, -2129, -23754, 28733, 19067]
const a=new Uint32Array(10);
crypto.getRandomValues(a);
//a: Uint32Array(10) [3783727612, 388524324, 3034572174, 2786620432, 223475394, 2876258946, 4178159678, 46748551, 216119796, 1975456388]
const a=new Int32Array(10);
crypto.getRandomValues(a);
//a: Int32Array(10) [8166113, -701054871, -62577682, 323488204, -850241317, -1312132890, -628785528, 1686233427, 2057854102, 1830609037]

--

--