Initial Commit
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user