UNPKG

cesr

Version:

[![NPM Version](https://img.shields.io/npm/v/cesr.svg?style=flat)](https://www.npmjs.com/package/cesr) [![NPM License](https://img.shields.io/npm/l/cesr.svg?style=flat)](https://github.com/lenkan/cesr-js/blob/main/LICENSE)

82 lines (81 loc) 3.06 kB
const B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".split(""); function getBase64Index(char) { if (char === "=") { return 0; } const code = B64_ALPHABET.indexOf(char); if (code === -1) { throw new Error(`Invalid base64 character '${char}'`); } return code; } export function decodeBase64Int(str) { let result = 0; for (let i = str.length - 1; i >= 0; i--) { const character = str.charAt(i); const index = getBase64Index(character); const factor = 64 ** (str.length - i - 1); result += factor * index; } return result; } export function encodeBase64Int(value, length) { if (length !== undefined && value >= 64 ** length) { throw new Error(`value ${value} too big for base64 length ${length}`); } let remainder = value; let result = ""; while (remainder !== 0) { result = B64_ALPHABET[remainder % 64] + result; remainder = Math.floor(remainder / 64); } return result.padStart(length ?? 1, "A"); } export function encodeBase64Url(uint8) { // CREDIT: https://github.com/denoland/std/blob/main/encoding/base64.ts // CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727 let result = ""; let i; const l = uint8.length; for (i = 2; i < l; i += 3) { result += B64_ALPHABET[uint8[i - 2] >> 2]; result += B64_ALPHABET[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)]; result += B64_ALPHABET[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)]; result += B64_ALPHABET[uint8[i] & 0x3f]; } if (i === l + 1) { // 1 octet yet to write result += B64_ALPHABET[uint8[i - 2] >> 2]; result += B64_ALPHABET[(uint8[i - 2] & 0x03) << 4]; } if (i === l) { // 2 octets yet to write result += B64_ALPHABET[uint8[i - 2] >> 2]; result += B64_ALPHABET[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)]; result += B64_ALPHABET[(uint8[i - 1] & 0x0f) << 2]; } return result; } export function decodeBase64Url(input) { if (typeof input !== "string") { throw new Error(`input must be a string`); } if (input.length === 0) { return new Uint8Array(0); } const remainder = input.length % 4; const padSize = remainder > 0 ? 4 - remainder : remainder; const str = input.padEnd(padSize + input.length, "="); const result = new Uint8Array(3 * (str.length / 4)); for (let i = 0, j = 0; i < str.length; i += 4, j += 3) { const sixtet0 = getBase64Index(str.charAt(i)) << 18; const sixtet1 = getBase64Index(str.charAt(i + 1)) << 12; const sixtet2 = getBase64Index(str.charAt(i + 2)) << 6; const sixtet3 = getBase64Index(str.charAt(i + 3)); const chunk = sixtet0 | sixtet1 | sixtet2 | sixtet3; result[j] = chunk >> 16; result[j + 1] = (chunk >> 8) & 0xff; result[j + 2] = chunk & 0xff; } return result.slice(0, result.length - padSize); }