Base32 Encoding and Decoding for UTF-8 Text

Encode UTF-8 text with the RFC 4648 Base32 alphabet, add correct padding, and decode back while rejecting invalid characters.

JavascriptSecurity Boundaries

Code

snippet
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

export function base32Encode(input) {
  if (typeof input !== "string") throw new TypeError("input must be a string");
  const bytes = new TextEncoder().encode(input);
  let bits = 0;
  let value = 0;
  let output = "";
  for (const byte of bytes) {
    value = (value << 8) | byte;
    bits += 8;
    while (bits >= 5) {
      output += ALPHABET[(value >>> (bits - 5)) & 31];
      bits -= 5;
    }
  }
  if (bits > 0) output += ALPHABET[(value << (5 - bits)) & 31];
  while (output.length % 8 !== 0) output += "=";
  return output;
}

export function base32Decode(input) {
  if (typeof input !== "string") throw new TypeError("input must be a string");
  const normalized = input.toUpperCase().replace(/=+$/, "");
  if (!/^[A-Z2-7]*$/.test(normalized)) {
    throw new RangeError("invalid base32 characters");
  }
  let bits = 0;
  let value = 0;
  const bytes = [];
  for (const char of normalized) {
    const index = ALPHABET.indexOf(char);
    value = (value << 5) | index;
    bits += 5;
    if (bits >= 8) {
      bytes.push((value >>> (bits - 8)) & 255);
      bits -= 8;
    }
  }
  return new TextDecoder().decode(new Uint8Array(bytes));
}