import { timingSafeEqualStrings } from "./crypto";
const BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
const SECRET_BYTES = 20;
const STEP_SECONDS = 30;
const DIGITS = 6;
const DRIFT_STEPS = 1;
const BASE32_BITS = 5;
const BYTE_BITS = 8;
export function base32Encode(bytes: Uint8Array): string {
let bits = 0;
let value = 0;
let out = "";
for (const byte of bytes) {
value = (value << BYTE_BITS) | byte;
bits += BYTE_BITS;
while (bits >= BASE32_BITS) {
out += BASE32_ALPHABET[(value >>> (bits - BASE32_BITS)) & 31];
bits -= BASE32_BITS;
}
}
if (bits > 0) out += BASE32_ALPHABET[(value << (BASE32_BITS - bits)) & 31];
return out;
}
export function base32Decode(input: string): Uint8Array<ArrayBuffer> {
const clean = input.toUpperCase().replace(/[\s=]/g, "");
const out: number[] = [];
let bits = 0;
let value = 0;
for (const char of clean) {
const index = BASE32_ALPHABET.indexOf(char);
if (index === -1) throw new Error("Invalid base32");
value = (value << BASE32_BITS) | index;
bits += BASE32_BITS;
if (bits >= BYTE_BITS) {
out.push((value >>> (bits - BYTE_BITS)) & 255);
bits -= BYTE_BITS;
}