type OtpAlgorithm$1 = "SHA1" | "SHA224" | "SHA256" | "SHA384" | "SHA512"; /** * Current TOTP for the given secret. * * @param {string | Buffer | Uint8Array} secret * @param {TotpOptions} [options] * @returns {string} */ declare function totp(secret: string | Buffer | Uint8Array, options?: TotpOptions): string; /** * Seconds remaining before the current TOTP code rolls over. Handy for * the countdown ring most 2FA screens show. * * @param {number} [period=30] * @param {number} [timestamp] ms since epoch, default Date.now(). * @param {number} [t0=0] Epoch offset in seconds (RFC 6238 "T0"). * Pass the same value used at enrollment so * the countdown lines up with `totp`. * @returns {number} Whole seconds in `(0, period]`. */ declare function remainingSeconds(period?: number, timestamp?: number, t0?: number): number; /** * Verify a TOTP code with configurable drift tolerance. * * Returns `true` on success (with optional silent replay guard) or * `false` on any failure. Never throws for user-input problems — * a wrong code is a normal auth-outcome, not an error. * * @param {unknown} code * @param {string | Buffer | Uint8Array} secret * @param {TotpVerifyOptions} [options] * @returns {Promise} */ declare function verifyTotp(code: unknown, secret: string | Buffer | Uint8Array, options?: TotpVerifyOptions): Promise; type OtpAlgorithm = OtpAlgorithm$1; type TotpOptions = { digits?: 6 | 7 | 8 | 9 | 10 | undefined; algorithm?: OtpAlgorithm$1 | undefined; /** * Seconds per code. RFC 6238 default is 30. */ period?: number | undefined; /** * Override "now" in ms since epoch. * Useful for testing; production * code should leave it undefined. */ timestamp?: number | undefined; /** * Epoch offset in seconds — RFC 6238 * calls this "T0". Almost every * deployment leaves it at 0 (Unix * epoch); a handful of legacy SecurID * migrations use a custom start. */ t0?: number | undefined; }; type ReplayGuard = { /** * Any store shaped like the `@exortek/security` rate-limit stores — * memory / Redis / custom all satisfy this duck type. The guard uses * the store's **atomic** `incr` (Redis `INCR`) as a compare-and-set so * two concurrent requests carrying the same code can't both pass — a * `get`-then-`set` pair would leave a TOCTOU window open. */ store: { incr: (key: string, ttlMs: number) => Promise<{ count: number; }>; }; /** * Caller-provided namespace (typically the user id). We compose the * real store key as `otp:used::` — the counter alone * would collide across users. */ key: string; }; type TotpVerifyOptions = { digits?: 6 | 7 | 8 | 9 | 10 | undefined; algorithm?: OtpAlgorithm$1 | undefined; period?: number | undefined; /** * Skew tolerance in periods. `window: 1` accepts `T-1`, `T`, and * `T+1` — the same tolerance Google Authenticator applies internally. * `window: 0` is strict; `window: 2+` gets progressively less * defensive against brute-force. */ window?: number | undefined; /** * Override "now" (ms since epoch). */ timestamp?: number | undefined; /** * Epoch offset in seconds. Match the value * used at enrollment. */ t0?: number | undefined; /** * Opt-in replay defence: after a successful verify we mark that * specific counter as "used" for the remaining validity of the * window, so a stolen code can't be reused inside its slop period. * Requires an async store. */ replay?: ReplayGuard | undefined; }; export { remainingSeconds, totp, verifyTotp }; export type { OtpAlgorithm, ReplayGuard, TotpOptions, TotpVerifyOptions };