# `base32/base32` _(no submodules)_ ## Purpose RFC 4648 §6 base32 encode + decode. The OTP profile defaults to **unpadded** output to match the Google Authenticator Key URI Format (`secret=...` is unpadded in the wild); spec-strict consumers can opt in via `padding: true`. Decode is case-insensitive and tolerates whitespace between groups so QR-code URLs that wrap long secrets round-trip cleanly. ## Features - `base32Encode(bytes, opts?)` — bit-packed five-at-a-time encode. - `base32Decode(input)` — single-pass reverse-table decode. - 32-character alphabet `A–Z2–7` per RFC 4648 §6. - Lower-case alias only for letters (digits 2–7 are case-invariant). - `OTP.BASE32_INVALID` raised on non-alphabet character. ## Usage: Basic Example ```ts import { base32Decode, base32Encode } from "@suaveplan/otp/base32"; const bytes = base32Decode("JBSWY3DPEHPK3PXP"); const back = base32Encode(bytes); ``` ## Usage: Advanced Example ```ts import { base32Encode } from "@suaveplan/otp/base32"; // Spec-strict consumer that needs `=` padding. const padded = base32Encode(new Uint8Array([0x66, 0x6f, 0x6f]), { padding: true, }); // padded === "MZXW6===" ``` ## API Reference - `base32Encode(bytes: Uint8Array, opts?: { padding?: boolean }): string` — returns the base32 form. `padding` defaults to `false`. - `base32Decode(input: string): Uint8Array` — decodes padded or unpadded input; whitespace is stripped; case-insensitive; non-alphabet characters raise `OtpError(OTP.BASE32_INVALID)` with the offending position. ## Implementation Notes The decode table is a 128-entry `Int8Array` indexed by char-code. Letters are aliased to their lower-case slots; digits are not aliased because '2'+32 ='R' which would otherwise overwrite the letter slot for `R`. The encoder emits unpadded output by default to match the prevailing Google Authenticator wire format; `padding: true` makes the output multiple-of-eight characters and RFC-4648-compliant for spec-strict consumers.