Files
skills/docs/security-stack/security/otp/src/hotp/hmac.md
2026-05-29 08:20:56 +01:00

2.1 KiB

hotp/hmac

Purpose

Algorithm-routing HMAC façade for the OTP family. SHA-256 and SHA-512 route through @suaveplan/crypto-hash (the canonical platform HMAC); SHA-1 routes through @noble/hashes/sha1 directly because crypto-hash deliberately does not expose SHA-1 — it is mandated only by legacy OTP RFCs and must not be presented as a general-purpose option elsewhere in the platform.

Features

  • Three algorithms: SHA-1, SHA-256, SHA-512.
  • SHA-1 isolated to the OTP family — no leakage into the wider crypto API.
  • Returns a freshly-allocated Uint8Array of the algorithm's digest size.

Usage: Basic Example

import { hmacFor } from "@suaveplan/otp";

const tag = hmacFor("SHA1", key, message);

Usage: Advanced Example

import { hmacFor } from "@suaveplan/otp";

// Build the OCRA HMAC input directly — useful for KAT-driven test fixtures.
const tag = hmacFor("SHA256", key, suiteAsciiPlusZeroPlusDataInput);

API Reference

  • hmacFor(algorithm: HotpAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array — returns the HMAC tag.
  • HotpAlgorithm = "SHA1" | "SHA256" | "SHA512".

Implementation Notes

Routing inside this module rather than at the call site keeps the SHA-1 exception local to OTP. The crypto-hash boundary uses dashed names ("SHA-256"); this module accepts the OTP-RFC-style undashed names ("SHA256") and translates internally. Adding a new algorithm here is the only change required — hotp.ts, totp.ts, and ocra.ts all consume this single dispatch point.

The SHA-1 routing decision is intentional: @suaveplan/crypto-hash is the canonical platform façade for hashing across the project, and exposing SHA-1 there would invite consumers to use it for non-OTP purposes. By isolating the SHA-1 dependency to the OTP module, the rest of the platform keeps a no-SHA-1 posture without breaking RFC 4226 / 6238 / 6287 compliance. The noble HMAC primitive used here is the same implementation crypto-hash routes through under the hood for SHA-256 / SHA-512, so the two paths behave identically apart from the chosen hash.