first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,125 @@
# base64
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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
```ts
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.