std/crypto
2022-11-08 21:15:44 +09:00
..
_benches BREAKING: remove deprecated std/hash module (#2786) 2022-10-23 11:12:18 -04:00
_fnv feat(crypto): add fnv algorithms (#2200) 2022-06-01 14:42:32 +09:00
_wasm chore: upgrade rust to 0.165.0 and wasmbuild to 0.10.2 (#2850) 2022-11-08 21:15:44 +09:00
_util.ts feat(crypto): createHash utility (#2805) 2022-10-25 15:48:13 -04:00
keystack_test.ts feat(crypto): add KeyStack for rotatable key data signing (#2303) 2022-08-16 15:07:26 +10:00
keystack.ts feat(crypto): add KeyStack for rotatable key data signing (#2303) 2022-08-16 15:07:26 +10:00
mod.ts refactor(crypto): move crypto/_wasm_crypto/ to crypto/_wasm/ (#2845) 2022-11-07 15:53:46 +09:00
README.md feat(crypto): toHashString utility (#2767) 2022-10-21 17:44:32 +09:00
test.ts refactor(crypto): move crypto/_wasm_crypto/ to crypto/_wasm/ (#2845) 2022-11-07 15:53:46 +09:00
timing_safe_equal_test.ts feat(crypto): add subtle.timingSafeEqual() (#2503) 2022-08-11 20:06:26 +10:00
timing_safe_equal.ts feat(crypto): add subtle.timingSafeEqual() (#2503) 2022-08-11 20:06:26 +10:00
util_test.ts feat(crypto): toHashString utility (#2767) 2022-10-21 17:44:32 +09:00
util.ts feat(crypto): toHashString utility (#2767) 2022-10-21 17:44:32 +09:00

crypto

Extensions to the WebCrypto interface, which provides additional encryption algorithms that are not part of the web standard, as well as a subtle.digest(), subtle.digestSync(), and subtle.timingSafeEqual() methods which provide additional functionality not covered by web crypto.

It also includes some utilities for key management.

crypto usage

The crypto export provides an enhanced version of the built-in Web Crypto API providing additional cryptographic algorithms using the same interface as the Web Crypto API, but also delegating to the built in APIs when possible.

import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";

// This will delegate to the runtime's WebCrypto implementation.
console.log(
  new Uint8Array(
    await crypto.subtle.digest(
      "SHA-384",
      new TextEncoder().encode("hello world"),
    ),
  ),
);

// This will use a bundled Wasm/Rust implementation.
console.log(
  new Uint8Array(
    await crypto.subtle.digest(
      "BLAKE3",
      new TextEncoder().encode("hello world"),
    ),
  ),
);

Supported algorithms

Here is a list of supported algorithms. If the algorithm name in WebCrypto and Wasm/Rust is the same, this library prefers to use algorithms that are supported by WebCrypto.

WebCrypto

// https://deno.land/std/crypto/mod.ts
const webCryptoDigestAlgorithms = [
  "SHA-384",
  "SHA-256",
  "SHA-512",
  // insecure (length-extendable and collidable):
  "SHA-1",
] as const;

Wasm/Rust

// https://deno.land/std/_wasm_crypto/mod.ts
export const digestAlgorithms = [
  "BLAKE2B-256",
  "BLAKE2B-384",
  "BLAKE2B",
  "BLAKE2S",
  "BLAKE3",
  "KECCAK-224",
  "KECCAK-256",
  "KECCAK-384",
  "KECCAK-512",
  "SHA-384",
  "SHA3-224",
  "SHA3-256",
  "SHA3-384",
  "SHA3-512",
  "SHAKE128",
  "SHAKE256",
  "TIGER",
  // insecure (length-extendable):
  "RIPEMD-160",
  "SHA-224",
  "SHA-256",
  "SHA-512",
  // insecure (collidable and length-extendable):
  "MD5",
  "SHA-1",
] as const;

Timing safe comparison

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 to equality comparisons of values.

It is likely some form of timing safe equality will make its way to the WebCrypto standard (see: w3c/webcrypto#270), but until that time, timingSafeEqual() is provided:

import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.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"),
);
const c = await crypto.subtle.digest(
  "SHA-384",
  new TextEncoder().encode("hello deno"),
);

assert(crypto.subtle.timingSafeEqual(a, b));
assert(!crypto.subtle.timingSafeEqual(a, c));

In addition to the method being part of the crypto.subtle interface, it is also loadable directly:

import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts";
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.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));

KeyStack usage

The KeyStack export implements the KeyRing interface for managing rotatable keys for signing data to prevent tampering, like with HTTP cookies.

import { KeyStack } from "https://deno.land/std@$STD_VERSION/crypto/keystack.ts";

const keyStack = new KeyStack(["hello", "world"]);
const digest = await keyStack.sign("some data");

const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
await rotatedStack.verify("some data", digest); // true

Convert hash to a string

import {
  crypto,
  toHashString,
} from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";

const hash = await crypto.subtle.digest(
  "SHA-384",
  new TextEncoder().encode("You hear that Mr. Anderson?"),
);

// Hex encoding by default
console.log(toHashString(hash));

// Or with base64 encoding
console.log(toHashString(hash, "base64"));