Functional Weave
Code in TypeScript

crypto.hmac-sha256@1.0.0

impl/typescript.ts

1,319 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { sha256 } from "./crypto_sha256.ts";  ← from crypto.sha256 ^1.0.0 · built alongside by fune

const BLOCK = 64;

function checkBytes(value: readonly number[], name: string): void {
  if (!Array.isArray(value) && !(value instanceof Uint8Array)) {
    throw new TypeError(`${name} must be a list of integers from 0 to 255`);
  }
  for (let i = 0; i < value.length; i++) {
    const b = value[i];
    if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
      throw new RangeError(`${name} must be a list of integers from 0 to 255`);
    }
  }
}

/**
 * HMAC-SHA256 (RFC 2104): H((K ^ opad) || H((K ^ ipad) || message)), with a
 * key longer than the 64-byte block hashed down to 32 bytes first.
 */
export function hmacSha256(key: readonly number[], message: readonly number[]): readonly number[] {
  checkBytes(key, "key");
  checkBytes(message, "message");
  const k = key.length > BLOCK ? sha256(key) : key;
  const inner: number[] = new Array(BLOCK + message.length);
  const outer: number[] = new Array(BLOCK + 32);
  for (let i = 0; i < BLOCK; i++) {
    const b = i < k.length ? k[i] : 0;
    inner[i] = b ^ 0x36;
    outer[i] = b ^ 0x5c;
  }
  for (let i = 0; i < message.length; i++) inner[BLOCK + i] = message[i];
  const innerHash = sha256(inner);
  for (let i = 0; i < 32; i++) outer[BLOCK + i] = innerHash[i];
  return sha256(outer);
}