totp.ts

1.1 KB · raw

1import { TOTP, URI } from "otpauth";23export type TOTPAlgorithm = "SHA1" | "SHA256" | "SHA512";45export interface TOTPParams {6  secret: string;7  algorithm?: TOTPAlgorithm;8  digits?: number;9  period?: number;10}1112export function generateTOTP(13  base32Secret: string,14  algorithm: TOTPAlgorithm = "SHA1",15  digits: number = 6,16  period: number = 3017): { code: string; remaining: number } {18  // PCH-01-019: honour the entry's stored algorithm/digits/period; absent19  // params (undefined) fall through to the RFC defaults (SHA-1 / 6 / 30 s).20  const totp = new TOTP({ secret: base32Secret, digits, period, algorithm });21  const code = totp.generate();22  const remaining = period - (Math.floor(Date.now() / 1000) % period);23  return { code, remaining };24}2526export function parseOtpauthURI(uri: string): TOTPParams | null {27  try {28    const parsed = URI.parse(uri);29    if (parsed instanceof TOTP) {30      return {31        secret: parsed.secret.base32,32        algorithm: parsed.algorithm as TOTPAlgorithm,33        digits: parsed.digits,34        period: parsed.period,35      };36    }37    return null;38  } catch {39    return null;40  }41}