Deno World
Published in

Deno World

Web crypto APIs in Deno

Introduction

One of the biggest advantage of Deno is providing commonly used functionality through web APIs (wherever possible). A few web APIs were supported since the inception of Deno. Off recently, the number has been increasing at a fast pace. These are the same web APIs that developers have been using in browser. This makes it easier for developers to write code in Deno.

One of the web API is crypto. Till release v1.11, Deno had support for a single web crypto API: getRandomValues. From release v1.11, Deno has expanded web crypto API support with:

  • Subtle digest: Calculate SHA-1/256/384/512
  • random UUID: Generate a random UUID

In this article, we’ll go over the web crypto APIs provided by Deno with some examples.

At the time of writing, v1.11 is the latest Deno release

Crypto Functions

As web crypto APIs are part of the core runtime, there is no need to include anything. To convert the digest to string, there would be a need for a hex to string function from the standard library’s encoding module.

Let’s go over the three crypto functions currently supported by Deno.

getRandomValues

This API takes an integer typed array as input and fills it with cryptographically strong random numbers. The typed array must be an integer typed. It could be signed or unsigned. If it’s signed, the generated random numbers would include negative numbers too.

getRandomValues(
| Int8Array
| Int16Array
| Int32Array
| Uint8Array
| Uint16Array
| Uint32Array
| Uint8ClampedArray);

The input must be integer typed array

crypto.getRandomValues(new Uint32Array(10));
//Uint32Array(10) [48843607, 219863191, 805297834, 375074551, 3716779875, 1845347192, 1133062220, 2082312350, 459410539, 4273261590]

getRandomValues offers cryptographically strong random numbers, but is slower compared to Math.random. There is no predictability in the numbers generated by getRandomValues.

The output can be used anywhere unpredictable random data is required. Like generating keys, long request IDs, etc.

const a=new Uint32Array(10);
crypto.getRandomValues(a);
a.join(""); //36834709454279997522205135369330414075532835960782321112517035145706601528443521354931218994401230

Here are some more examples:

const b=new Uint16Array(5), bs=new Int16Array(5);
crypto.getRandomValues(b); //Uint16Array(5) [ 37648, 25274, 5837, 4397, 23974 ]
crypto.getRandomValues(bs); //Int16Array(5) [ 28244, 11515, -14516, 14045, -8667 ]
const c=new Uint16Array(5), cs=new Int16Array(5);
crypto.getRandomValues(c); //Uint32Array(5) [ 1339403152, 473530254, 2553241448, 1133203190, 3603565761 ]
crypto.getRandomValues(cs); //Int32Array(5) [ -77009087, -208622314, 2107725964, -1779237119, 1434297744 ]
const b=new Uint32Array(10);
crypto.getRandomValues(b);
b.join(""); //308243249111236650121230670332937661885318486139938227383374112662963388624888536138937534001210687

random UUID

The function randomUUID is used to generate RFC 4122 compliant randomly generated V4 UUIDs. This function doesn’t take any inputs. The output is a completely random v4 UUID. The UUIDs are fully random.

function randomUUID(): string

Every call to randomUUID returns a random alphanumeric string:

for(let i=0; i<5; i++)
crypto.randomUUID();
//49d25949-7045-4bdd-a17b-a5b4e3f16be1
0b661bd4-61a3-4d33-bb39-5d30d299d7b0
4ce3bf60-7633-47d1-abce-6a0b83fcae72
27d3c909-3c71-4f0a-a683-c16b11fa1e81
7f3995df-504d-4bc9-bbf2-3338749ab610

digest

The async function digest in crypto.subtle is useful in generating a secure hash on any given data.

There are two inputs to the digest function:

  • Algorithm: This is the hash algorithm (string). Supported algorithms are: SHA-1, SHA-256, SHA-384, and SHA-512. These happen to be the most commonly used hashing algorithms.
  • Data: The data to hash (could be a typed array, or an ArrayBuffer)

The output of the digest function is ArrayBuffer. The array can be converted to Uint8Array, and then possibly to a string by converting hex to string.

The length of hash output is fixed:

  • SHA-1: 20 bytes
  • SHA-256: 32 bytes
  • SHA-384: 48 bytes
  • SHA-512: 64 bytes
function digest(
algorithm: AlgorithmIdentifier,//SHA-1, SHA-256, SHA-384, SHA-512
data:
| Int8Array
| Int16Array
| Int32Array
| Uint8Array
| Uint16Array
| Uint32Array
| Uint8ClampedArray
| Float32Array
| Float64Array
| DataView
| ArrayBuffer,
): Promise<ArrayBuffer>;

If an unrecognized algorithm is provided, a NotSupportedError would be raised.

await crypto.subtle.digest('sha-1', new Uint8Array(10).fill(50));
//ArrayBuffer {}
await crypto.subtle.digest('sha-11', new Uint8Array(10).fill(50));
//NotSupportedError: Unrecognized algorithm name

Here are some examples of the digests:

import { encodeToString } from "https://deno.land/std/encoding/hex.ts";//common input for all functions
const i=Uint8Array.from({length: 50}, () => Math.floor(Math.random() * 50));
//SHA-1new Uint8Array(await crypto.subtle.digest('sha-1', i));
//Uint8Array(20) [87, 55, 240, 228, 250, 122, 3, 204, 85, 72, 125, 85, 159, 198, 81, 239, 35, 254, 77, 27]
encodeToString(new Uint8Array(await crypto.subtle.digest('sha-1', i)));
//df3ed451c9ea86ab10ff7583874ad1bd4813c3e0
//SHA-256new Uint8Array(await crypto.subtle.digest('sha-256', i));
//Uint8Array(32) [197, 138, 201, 31, 201, 218, 169, 117, 12, 31, 16, 116, 230, 169, 44, 154, 108, 120, 28, 123, 64, 183, 162, 129, 196, 82, 114, 116, 245, 211, 116, 122]
encodeToString(new Uint8Array(await crypto.subtle.digest('sha-256', i)));
//c58ac91fc9daa9750c1f1074e6a92c9a6c781c7b40b7a281c4527274f5d3747a
//SHA-384new Uint8Array(await crypto.subtle.digest('sha-384', i));
//Uint8Array(48) [72, 183, 141, 243, 202, 146, 234, 12, 199, 105, 108, 145, 37, 170, 47, 121, 203, 166, 4, 170, 33, 1, 13, 33, 23, 243, 148, 58, 137, 107, 243, 74, 127, 49, 200, 62, 30, 62, 54, 63, 167, 251, 139, 102, 120, 17, 3, 7]
encodeToString(new Uint8Array(await crypto.subtle.digest('sha-384', i)));
//48b78df3ca92ea0cc7696c9125aa2f79cba604aa21010d2117f3943a896bf34a7f31c83e1e3e363fa7fb8b6678110307
//SHA-512new Uint8Array(await crypto.subtle.digest('sha-512', i));
//Uint8Array(64) [114, 18, 60, 52, 57, 109, 160, 248, 102, 239, 118, 250, 222, 76, 187, 139, 250, 239, 232, 179, 31, 144, 192, 174, 39, 73, 17, 211, 237, 236, 93, 143, 12, 33, 234, 172, 70, 22, 96, 110, 120, 151, 207, 228, 250, 96, 114, 88, 158, 63, 122, 120, 198, 210, 221, 118, 28, 19, 99, 162, 145, 236, 182, 184]
encodeToString(new Uint8Array(await crypto.subtle.digest('sha-512', i)));
//72123c34396da0f866ef76fade4cbb8bfaefe8b31f90c0ae274911d3edec5d8f0c21eaac4616606e7897cfe4fa6072589e3f7a78c6d2dd761c1363a291ecb6b8

This story is a part of the exclusive medium publication on Deno: Deno World.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store