first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
# `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.