Skip to content

Instantly share code, notes, and snippets.

@skizhak
Created January 22, 2019 22:17
Show Gist options
  • Select an option

  • Save skizhak/62be154f649b4d7a67982ec108aa1a07 to your computer and use it in GitHub Desktop.

Select an option

Save skizhak/62be154f649b4d7a67982ec108aa1a07 to your computer and use it in GitHub Desktop.
Base64 encode/decode in JS
// base64 encode/decode shamelessly taken from Google Closure and modified.
// https://github.com/google/closure-library/blob/28d9db61f5dc639c010be74e4d61682121d2dbd7/closure/goog/crypt/base64.js
var base64 = {
ENCODED_VALS: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
encode: (data) => base64.encodeByteArray(base64.stringToByteArray(data)),
decode: (data) => base64.byteArrayToString(base64.decodeStringToByteArray(data)),
byteToCharMap_: '',
charToByteMap_: '',
init_: () => {
if (base64.byteToCharMap_ == '') {
base64.byteToCharMap_ = {};
base64.charToByteMap_ = {};
// We want quick mappings back and forth, so we precompute two maps.
for (var i = 0; i < base64.ENCODED_VALS.length; i++) {
base64.byteToCharMap_[i] = base64.ENCODED_VALS.charAt(i);
base64.charToByteMap_[base64.byteToCharMap_[i]] = i;
}
}
},
stringToByteArray: (str) => {
var output = [], p = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
while (c > 0xff) {
output[p++] = c & 0xff;
c >>= 8;
}
output[p++] = c;
}
return output;
},
byteArrayToString: (bytes) => {
var CHUNK_SIZE = 8192;
// Special-case the simple case for speed's sake.
if (bytes.length <= CHUNK_SIZE) {
return String.fromCharCode.apply(null, bytes);
}
// The remaining logic splits conversion by chunks since
// Function#apply() has a maximum parameter count.
// See discussion: http://goo.gl/LrWmZ9
var str = '';
for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
var chunk = bytes.slice(i, i + CHUNK_SIZE);
str += String.fromCharCode.apply(null, chunk);
}
return str;
},
encodeByteArray: (input) => {
base64.init_();
var output = [];
for (var i = 0; i < input.length; i += 3) {
var byte1 = input[i];
var haveByte2 = i + 1 < input.length;
var byte2 = haveByte2 ? input[i + 1] : 0;
var haveByte3 = i + 2 < input.length;
var byte3 = haveByte3 ? input[i + 2] : 0;
var outByte1 = byte1 >> 2;
var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
var outByte4 = byte3 & 0x3F;
if (!haveByte3) {
outByte4 = 64;
if (!haveByte2) {
outByte3 = 64;
}
}
output.push(base64.byteToCharMap_[outByte1],
base64.byteToCharMap_[outByte2],
base64.byteToCharMap_[outByte3],
base64.byteToCharMap_[outByte4]);
}
return output.join('');
},
decodeStringToByteArray: (input) => {
base64.init_();
var output = [];
for (var i = 0; i < input.length; ) {
var byte1 = base64.charToByteMap_[input.charAt(i++)];
var haveByte2 = i < input.length;
var byte2 = haveByte2 ? base64.charToByteMap_[input.charAt(i)] : 0;
++i;
var haveByte3 = i < input.length;
var byte3 = haveByte3 ? base64.charToByteMap_[input.charAt(i)] : 64;
++i;
var haveByte4 = i < input.length;
var byte4 = haveByte4 ? base64.charToByteMap_[input.charAt(i)] : 64;
++i;
if (byte1 == null || byte2 == null ||
byte3 == null || byte4 == null) {
throw Error();
}
var outByte1 = (byte1 << 2) | (byte2 >> 4);
output.push(outByte1);
if (byte3 != 64) {
var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2);
output.push(outByte2);
if (byte4 != 64) {
var outByte3 = ((byte3 << 6) & 0xC0) | byte4;
output.push(outByte3);
}
}
}
return output;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment