# `hotp/encode-counter` ## Purpose Encode an HOTP counter as the 8-byte big-endian block required by RFC 4226 §5.1. `bigint` is the canonical input type because `Number` loses precision past `2^53` and the RFC permits counters up to `2^64 − 1`. Shared by HOTP itself, by OCRA's optional `C` directive, and by OCRA's `T` timestamp block (which is also written as an 8-byte big-endian integer per RFC 6287 §5.1). ## Features - BigInt input — no precision loss across the full 0..2^64-1 range. - Range guard: negative counters and counters past `2^64-1` raise `OtpError(OTP.INVALID_OPTIONS)`. - Pure: returns a freshly-allocated `Uint8Array(8)` per call. ## Usage: Basic Example ```ts import { encodeCounter } from "@suaveplan/otp"; const block = encodeCounter(1n); // block === Uint8Array([0, 0, 0, 0, 0, 0, 0, 1]) ``` ## Usage: Advanced Example ```ts import { encodeCounter } from "@suaveplan/otp"; // Counter past Number.MAX_SAFE_INTEGER round-trips losslessly. const block = encodeCounter((1n << 53n) + 1n); // `block` is exactly 8 bytes; the high bytes carry the counter's high bits. ``` ## API Reference - `encodeCounter(counter: bigint): Uint8Array` — returns an 8-byte big-endian block. Negative input raises `OtpError(OTP.INVALID_OPTIONS)`; values >= 2^64 raise the same code. ## Implementation Notes The function loops from byte index 7 back to 0 shifting `counter` right by 8 bits each step. The mask `0xffn` keeps the operation inside the `bigint` domain so no implicit `Number` conversion can lose precision. The function is the single source of truth for big-endian counter framing — both HOTP and OCRA route through it so any future endianness change propagates atomically. The upper-bound check `counter > MAX_U64` catches the niche case where a caller passes a programmatically-generated counter past the RFC 4226 limit. Without the check the encoder would silently truncate the high bits and produce two distinct counters that hash to the same byte block, which would silently break the per-counter uniqueness invariant HOTP relies on. The lower-bound check on negative counters covers the symmetric case for callers who derive counters via `BigInt()` arithmetic that may go negative under bug conditions.