Skip to main content
Module

std/crypto/timing_safe_equal.ts

The Deno Standard Library
Latest
File
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.// This module is browser compatible.
import { assert } from "../assert/assert.ts";
/** * When checking the values of cryptographic hashes are equal, default * comparisons can be susceptible to timing based attacks, where attacker is * able to find out information about the host system by repeatedly checking * response times to equality comparisons of values. * * It is likely some form of timing safe equality will make its way to the * WebCrypto standard (see: * {@link https://github.com/w3c/webcrypto/issues/270 | w3c/webcrypto#270}), but until * that time, `timingSafeEqual()` is provided: * * ```ts * import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts"; * import { assert } from "https://deno.land/std@$STD_VERSION/assert/assert.ts"; * * const a = await crypto.subtle.digest( * "SHA-384", * new TextEncoder().encode("hello world"), * ); * const b = await crypto.subtle.digest( * "SHA-384", * new TextEncoder().encode("hello world"), * ); * * assert(timingSafeEqual(a, b)); * ``` */export function timingSafeEqual( a: ArrayBufferView | ArrayBufferLike | DataView, b: ArrayBufferView | ArrayBufferLike | DataView,): boolean { if (a.byteLength !== b.byteLength) { return false; } if (!(a instanceof DataView)) { a = ArrayBuffer.isView(a) ? new DataView(a.buffer, a.byteOffset, a.byteLength) : new DataView(a); } if (!(b instanceof DataView)) { b = ArrayBuffer.isView(b) ? new DataView(b.buffer, b.byteOffset, b.byteLength) : new DataView(b); } assert(a instanceof DataView); assert(b instanceof DataView); const length = a.byteLength; let out = 0; let i = -1; while (++i < length) { out |= a.getUint8(i) ^ b.getUint8(i); } return out === 0;}