2.2 KiB
range/range-mode.ts
Purpose
Houses the hash-mode dispatch utilities used by checkPassword:
hashSha1Prefix (SHA-1 via @noble/hashes/sha1), hashNtlmPrefix
(MD4-over-UTF-16-LE, supplied by an injectable adapter because not every
runtime ships an MD4 implementation), and buildRangeUrl (assembles the
final /range/<prefix>[?mode=ntlm] URL). The split between hashing and
URL building keeps each function small, testable, and reusable from
both the public checkPassword path and the privacy-leak verification
helpers.
Features
hashSha1Prefix(password)returns{ prefix, suffix, full }with the uppercase 40-char digest and its k-anonymity decomposition.hashNtlmPrefix(password, adapter)accepts a caller-supplied adapter, validating that the returned digest is exactly 40 uppercase hex chars.buildRangeUrl(prefix, mode)appends?mode=ntlmonly when the mode is"ntlm"— SHA-1 mode never sends a query string.RangeModetype alias narrows callers to the two valid values.
Usage: Basic Example
import { buildRangeUrl, hashSha1Prefix } from "@suaveplan/hibp";
const { prefix } = hashSha1Prefix("hunter2");
const url = buildRangeUrl(prefix, "sha1");
Usage: Advanced Example
import { buildRangeUrl, hashNtlmPrefix } from "@suaveplan/hibp";
import { md4 } from "my-ntlm-adapter";
const { prefix } = hashNtlmPrefix("hunter2", (pw) => md4(pw).toUpperCase());
const url = buildRangeUrl(prefix, "ntlm");
API Reference
RangeMode = "sha1" | "ntlm".NtlmHashAdapter = (password: string) => string.hashSha1Prefix(password): { prefix, suffix, full }.hashNtlmPrefix(password, adapter): { prefix, suffix, full }.buildRangeUrl(prefix, mode): string.
Implementation Notes
SHA-1 is sourced from @noble/hashes/sha1 rather than from
@suaveplan/crypto-hash because the crypto-hash package deliberately
omits SHA-1 (collision-broken for security purposes). The HIBP API
requires SHA-1 strictly for k-anonymity bucket selection — never for
security — so the direct noble dependency is the right call.
hashNtlmPrefix validates the adapter output rather than trusting it
because a buggy adapter could produce shorter strings and accidentally
leak unrelated bytes.