Files
skills/docs/security-stack/security/otp/src/base32/base32.md
2026-05-29 08:20:56 +01:00

2.0 KiB
Raw Blame History

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

import { base32Decode, base32Encode } from "@suaveplan/otp/base32";

const bytes = base32Decode("JBSWY3DPEHPK3PXP");
const back = base32Encode(bytes);

Usage: Advanced Example

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.