Skip to content
LogoLogo

Utilities

  • bytes converts Uint8Arrays to and from hex, joins them, and compares them, with timingSafeEqual for secrets.
  • errors holds the error classes that every package throws, and Errors.is, which checks an error's kind even when an app has two copies of a package. The errors guide shows how to use them.
  • random gives unbiased random integers, strings, and shuffles from crypto.getRandomValues, and a seeded generator for tests.

Check a signature in constant time

Compare secrets with Bytes.timingSafeEqual. An ordinary comparison returns at the first byte that differs, and the time it takes leaks how much of the signature an attacker guessed right.

import * as Bytes from '@portable/bytes';
 
const expected = new Uint8Array(
  await crypto.subtle.sign('HMAC', key, payload),
);
if (!Bytes.timingSafeEqual(expected, Bytes.fromHex(signature))) {
  throw new Error('Bad signature');
}