import { OTP_CODES, otpError } from "../errors/codes.js"; const MAX_U64 = (1n << 64n) - 1n; /** * Encode an HOTP counter as the 8-byte big-endian block required by RFC 4226 * §5.1. `bigint` is the canonical input type — `Number` loses precision past * `2^53` and the RFC permits counters up to `2^64 - 1`. Negative counters and * counters past `2^64 - 1` raise `OtpError(OTP.INVALID_OPTIONS)`. */ export function encodeCounter(counter: bigint): Uint8Array { if (counter < 0n) { throw otpError( OTP_CODES.INVALID_OPTIONS, "HOTP counter must be non-negative (RFC 4226 §5.1)" ); } if (counter > MAX_U64) { throw otpError( OTP_CODES.INVALID_OPTIONS, "HOTP counter exceeds 2^64-1 (RFC 4226 §5.1 mandates an 8-byte big-endian block)" ); } const out = new Uint8Array(8); let v = counter; for (let i = 7; i >= 0; i -= 1) { out[i] = Number(v & 0xffn); v >>= 8n; } return out; }