240 lines
5.5 KiB
JavaScript
240 lines
5.5 KiB
JavaScript
export function encodeBase64(bytes) {
|
|
return encodeBase64_internal(bytes, base64Alphabet, EncodingPadding.Include);
|
|
}
|
|
export function encodeBase64NoPadding(bytes) {
|
|
return encodeBase64_internal(bytes, base64Alphabet, EncodingPadding.None);
|
|
}
|
|
export function encodeBase64url(bytes) {
|
|
return encodeBase64_internal(bytes, base64urlAlphabet, EncodingPadding.Include);
|
|
}
|
|
export function encodeBase64urlNoPadding(bytes) {
|
|
return encodeBase64_internal(bytes, base64urlAlphabet, EncodingPadding.None);
|
|
}
|
|
function encodeBase64_internal(bytes, alphabet, padding) {
|
|
let result = "";
|
|
for (let i = 0; i < bytes.byteLength; i += 3) {
|
|
let buffer = 0;
|
|
let bufferBitSize = 0;
|
|
for (let j = 0; j < 3 && i + j < bytes.byteLength; j++) {
|
|
buffer = (buffer << 8) | bytes[i + j];
|
|
bufferBitSize += 8;
|
|
}
|
|
for (let j = 0; j < 4; j++) {
|
|
if (bufferBitSize >= 6) {
|
|
result += alphabet[(buffer >> (bufferBitSize - 6)) & 0x3f];
|
|
bufferBitSize -= 6;
|
|
}
|
|
else if (bufferBitSize > 0) {
|
|
result += alphabet[(buffer << (6 - bufferBitSize)) & 0x3f];
|
|
bufferBitSize = 0;
|
|
}
|
|
else if (padding === EncodingPadding.Include) {
|
|
result += "=";
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
const base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
const base64urlAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
export function decodeBase64(encoded) {
|
|
return decodeBase64_internal(encoded, base64DecodeMap, DecodingPadding.Required);
|
|
}
|
|
export function decodeBase64IgnorePadding(encoded) {
|
|
return decodeBase64_internal(encoded, base64DecodeMap, DecodingPadding.Ignore);
|
|
}
|
|
export function decodeBase64url(encoded) {
|
|
return decodeBase64_internal(encoded, base64urlDecodeMap, DecodingPadding.Required);
|
|
}
|
|
export function decodeBase64urlIgnorePadding(encoded) {
|
|
return decodeBase64_internal(encoded, base64urlDecodeMap, DecodingPadding.Ignore);
|
|
}
|
|
function decodeBase64_internal(encoded, decodeMap, padding) {
|
|
const result = new Uint8Array(Math.ceil(encoded.length / 4) * 3);
|
|
let totalBytes = 0;
|
|
for (let i = 0; i < encoded.length; i += 4) {
|
|
let chunk = 0;
|
|
let bitsRead = 0;
|
|
for (let j = 0; j < 4; j++) {
|
|
if (padding === DecodingPadding.Required && encoded[i + j] === "=") {
|
|
continue;
|
|
}
|
|
if (padding === DecodingPadding.Ignore &&
|
|
(i + j >= encoded.length || encoded[i + j] === "=")) {
|
|
continue;
|
|
}
|
|
if (j > 0 && encoded[i + j - 1] === "=") {
|
|
throw new Error("Invalid padding");
|
|
}
|
|
if (!(encoded[i + j] in decodeMap)) {
|
|
throw new Error("Invalid character");
|
|
}
|
|
chunk |= decodeMap[encoded[i + j]] << ((3 - j) * 6);
|
|
bitsRead += 6;
|
|
}
|
|
if (bitsRead < 24) {
|
|
let unused;
|
|
if (bitsRead === 12) {
|
|
unused = chunk & 0xffff;
|
|
}
|
|
else if (bitsRead === 18) {
|
|
unused = chunk & 0xff;
|
|
}
|
|
else {
|
|
throw new Error("Invalid padding");
|
|
}
|
|
if (unused !== 0) {
|
|
throw new Error("Invalid padding");
|
|
}
|
|
}
|
|
const byteLength = Math.floor(bitsRead / 8);
|
|
for (let i = 0; i < byteLength; i++) {
|
|
result[totalBytes] = (chunk >> (16 - i * 8)) & 0xff;
|
|
totalBytes++;
|
|
}
|
|
}
|
|
return result.slice(0, totalBytes);
|
|
}
|
|
var EncodingPadding;
|
|
(function (EncodingPadding) {
|
|
EncodingPadding[EncodingPadding["Include"] = 0] = "Include";
|
|
EncodingPadding[EncodingPadding["None"] = 1] = "None";
|
|
})(EncodingPadding || (EncodingPadding = {}));
|
|
var DecodingPadding;
|
|
(function (DecodingPadding) {
|
|
DecodingPadding[DecodingPadding["Required"] = 0] = "Required";
|
|
DecodingPadding[DecodingPadding["Ignore"] = 1] = "Ignore";
|
|
})(DecodingPadding || (DecodingPadding = {}));
|
|
const base64DecodeMap = {
|
|
"0": 52,
|
|
"1": 53,
|
|
"2": 54,
|
|
"3": 55,
|
|
"4": 56,
|
|
"5": 57,
|
|
"6": 58,
|
|
"7": 59,
|
|
"8": 60,
|
|
"9": 61,
|
|
A: 0,
|
|
B: 1,
|
|
C: 2,
|
|
D: 3,
|
|
E: 4,
|
|
F: 5,
|
|
G: 6,
|
|
H: 7,
|
|
I: 8,
|
|
J: 9,
|
|
K: 10,
|
|
L: 11,
|
|
M: 12,
|
|
N: 13,
|
|
O: 14,
|
|
P: 15,
|
|
Q: 16,
|
|
R: 17,
|
|
S: 18,
|
|
T: 19,
|
|
U: 20,
|
|
V: 21,
|
|
W: 22,
|
|
X: 23,
|
|
Y: 24,
|
|
Z: 25,
|
|
a: 26,
|
|
b: 27,
|
|
c: 28,
|
|
d: 29,
|
|
e: 30,
|
|
f: 31,
|
|
g: 32,
|
|
h: 33,
|
|
i: 34,
|
|
j: 35,
|
|
k: 36,
|
|
l: 37,
|
|
m: 38,
|
|
n: 39,
|
|
o: 40,
|
|
p: 41,
|
|
q: 42,
|
|
r: 43,
|
|
s: 44,
|
|
t: 45,
|
|
u: 46,
|
|
v: 47,
|
|
w: 48,
|
|
x: 49,
|
|
y: 50,
|
|
z: 51,
|
|
"+": 62,
|
|
"/": 63
|
|
};
|
|
const base64urlDecodeMap = {
|
|
"0": 52,
|
|
"1": 53,
|
|
"2": 54,
|
|
"3": 55,
|
|
"4": 56,
|
|
"5": 57,
|
|
"6": 58,
|
|
"7": 59,
|
|
"8": 60,
|
|
"9": 61,
|
|
A: 0,
|
|
B: 1,
|
|
C: 2,
|
|
D: 3,
|
|
E: 4,
|
|
F: 5,
|
|
G: 6,
|
|
H: 7,
|
|
I: 8,
|
|
J: 9,
|
|
K: 10,
|
|
L: 11,
|
|
M: 12,
|
|
N: 13,
|
|
O: 14,
|
|
P: 15,
|
|
Q: 16,
|
|
R: 17,
|
|
S: 18,
|
|
T: 19,
|
|
U: 20,
|
|
V: 21,
|
|
W: 22,
|
|
X: 23,
|
|
Y: 24,
|
|
Z: 25,
|
|
a: 26,
|
|
b: 27,
|
|
c: 28,
|
|
d: 29,
|
|
e: 30,
|
|
f: 31,
|
|
g: 32,
|
|
h: 33,
|
|
i: 34,
|
|
j: 35,
|
|
k: 36,
|
|
l: 37,
|
|
m: 38,
|
|
n: 39,
|
|
o: 40,
|
|
p: 41,
|
|
q: 42,
|
|
r: 43,
|
|
s: 44,
|
|
t: 45,
|
|
u: 46,
|
|
v: 47,
|
|
w: 48,
|
|
x: 49,
|
|
y: 50,
|
|
z: 51,
|
|
"-": 62,
|
|
_: 63
|
|
};
|