Skip to content

Latest commit

 

History

History
121 lines (82 loc) · 3.13 KB

README.md

File metadata and controls

121 lines (82 loc) · 3.13 KB

base64url

This is a pure TypeScript Base64-URL encoder/decoder for JavaScript strings with UTF-8 support.

If you've found it, you're already aware that:

  • btoa and atob only work on ASCII strings, and they're not always available in cool new JS runtimes
  • Buffer is only in Node.js
  • TextEncoder only works in browsers

This implementation allows you to encode any JavaScript string (emojis and multi-byte characters allowed!) to and from UTF-8 and then encode it as Base64-URL. It's great for:

  • Working with JWTs on any JS runtime
  • Encoding JavaScript strings to UTF-8 when serializing or parsing binary formats

It's a no-dependencies / no-depends library. Just copy the src/base64url.ts file in your project. It's mostly finished software, so it's unlikely you'll need to update it.

Use

Base64-URL

To encode to Base64-URL:

import { stringToBase64URL } from "./base64url";

stringToBase64URL("This will be encoded to UTF-8 then Base64-URL");

To decode from Base64-URL:

import { stringFromBase64URL } from "./base64url";

stringFromBase64URL(
  "VGhpcyB3aWxsIGJlIGVuY29kZWQgdG8gVVRGLTggdGhlbiBCYXNlNjQtVVJM",
);

UTF-8

To encode a string to UTF-8:

import { stringToUTF8 } from "./base64url";

stringToUTF8("This will be encoded as UTF-8", (byte: number) => {
  // write this byte to a stream or buffer
});

To decode UTF-8 bytes to a string:

import { stringFromUTF8 } from "./base64url";

const result: string[] = [];
const state = { utf8seq: 0, codepoint: 0 };

const onCodepoint = (codepoint: number) => {
  result.push(String.fromCodePoint(codepoint));
};

for (let byte of buffer) {
  // buffer holds all the UTF-8 bytes,
  // call this function for each byte
  stringFromUTF8(byte, state, onCodepoint);
}

const string = result.join("");

Uint8Array and Base64-URL

To convert a Uint8Array to Base64-URL:

import { byteToBase64URL } from "./base64url";

let bytes: Uint8Array;

const result: string[] = [];
const state = { queue: 0, queuedBits: 0 };

const onChar = (char: string) => {
  result.push(char);
};

bytes.map((byte) => byteToBase64URL(byte, state, onChar));

// always call with `null` after processing all bytes
byteToBase64URL(null, state, onChar);

const string = result.join("");

To convert Base64-URL to a Uint8Array:

import { byteFromBase64URL } from "./base64url";

const result: number[] = [];
const state = { queue: 0, queuedBits: 0 };

const onByte = (byte: number) => {
  result.push(byte);
};

for (let i = 0; i < string.length; i += 1) {
  byteFromBase64URL(string.charCodeAt(i), state, onByte);
}

const bytes = new Uint8Array(result);