Files
skills/docs/security-stack/crypto/crypto-hash/src/encoding/base64/base64.md
2026-05-29 08:20:56 +01:00

4.2 KiB

base64

(no submodules)

Purpose

Provides pure-TypeScript Base64 encoding and decoding in both standard (RFC 4648 §4) and URL-safe (RFC 4648 §5) variants. Cryptographic output such as JWT payloads, bearer tokens, and encoded public keys is routinely transmitted as Base64Url, while storage formats and MIME payloads use standard Base64. This module implements both without depending on Node.js Buffer or btoa/ atob (which are absent in some edge runtimes), making it safe for all @suaveplan/universal consumers.

Features

  • toBase64(bytes) — standard Base64 with = padding
  • fromBase64(b64) — decode standard Base64; throws HashError on malformed input
  • toBase64Url(bytes) — URL-safe Base64, no padding, - and _ alphabet
  • fromBase64Url(b64url) — decode URL-safe Base64; throws HashError on malformed input
  • Passes RFC 4648 test vectors
  • Pure TypeScript — no Buffer, no btoa/atob, no Node built-ins

Usage: Basic Example

import { toBase64, fromBase64 } from "@suaveplan/crypto-hash/encoding";

const encoder = new TextEncoder();
const bytes   = encoder.encode("hello world");

const b64 = toBase64(bytes);
console.log(b64); // "aGVsbG8gd29ybGQ="

const decoded = fromBase64(b64);
console.log(new TextDecoder().decode(decoded)); // "hello world"

Usage: Advanced Example

import { toBase64Url, fromBase64Url } from "@suaveplan/crypto-hash/encoding";
import { sha256 } from "@suaveplan/crypto-hash/hash";
import { HashError } from "@suaveplan/crypto-hash/errors";

// Build a simple JWT-style header.payload structure
function buildToken(payload: object, sigKey: Uint8Array): string {
    const encoder = new TextEncoder();
    const header  = toBase64Url(encoder.encode(JSON.stringify({ alg: "HS256" })));
    const body    = toBase64Url(encoder.encode(JSON.stringify(payload)));
    return `${header}.${body}`;
}

// Parse and validate a Base64Url segment
function decodeSegment(segment: string): object {
    try {
        const bytes = fromBase64Url(segment);
        return JSON.parse(new TextDecoder().decode(bytes)) as object;
    } catch (err) {
        if (err instanceof HashError) {
            throw new TypeError(`Malformed Base64Url segment: ${err.code}`);
        }
        throw err;
    }
}

const token = buildToken({ sub: "user-123", iat: 1700000000 }, new Uint8Array(32));
console.log(token);

API Reference

toBase64(bytes: Uint8Array): string

Encodes bytes as standard Base64 with = padding.

Parameter Type Description
bytes Uint8Array Byte sequence to encode

Returns: Base64 string of length Math.ceil(bytes.length / 3) * 4.


fromBase64(b64: string): Uint8Array

Decodes a standard Base64 string. Padding (=) is optional.

Parameter Type Description
b64 string Standard Base64 string

Returns: Decoded Uint8Array.

Throws: HashError("HASH.ENCODING.INVALID_INPUT") if any character is outside the standard Base64 alphabet. Context: { encoding: "base64", input }.


toBase64Url(bytes: Uint8Array): string

Encodes bytes as URL-safe Base64 without padding. Uses - and _ in place of + and /.


fromBase64Url(b64url: string): Uint8Array

Decodes a URL-safe Base64 string. + and / characters are rejected.

Throws: HashError("HASH.ENCODING.INVALID_INPUT") on invalid input. Context: { encoding: "base64url", input }.

Implementation Notes

The encoder uses a 64-character alphabet lookup table and processes three bytes at a time, producing four output characters per group. The decoder validates every character code against a 128-entry lookup table before converting, so malformed input is caught in a single pass rather than producing incorrect output silently. The table approach avoids repeated indexOf calls and keeps decoding O(n). Standard and URL-safe alphabets share the same encode/decode pipeline via the chars and table parameters; buildTable is called once at module load time and the resulting Uint8Array tables are module-level constants. No Buffer, btoa, atob, or Node.js built-ins are used.