Native BigInts and Base64 in JavaScript
Published 2018-12-14It's been native BigInts all week long, all week strong and today I'm tying it all in a nice pretty bow with the final installment: How to encode BigInts to Base64, and back again.
If you need to handle signed big ints look at the two articles on converting to and from hex below, that's where all of that is.
With that said, this is a pretty easy - and it's old school. Despite all the advances in JS most of the old thorns remain and, somewhat surprisingly, hex and binary strings are still the easiest way to get some of the most basic stuff done.
Note: For example's sake we're going to use small numbers here, but don't let that fool you, these tiny functions are built for the big ones!
Base64 to BigInt
From Base64 to binary string to hex to BigInt:
function b64ToBn(b64) {
var bin = atob(b64);
var hex = [];
bin.split('').forEach(function (ch) {
var h = ch.charCodeAt(0).toString(16);
if (h.length % 2) { h = '0' + h; }
hex.push(h);
});
return BigInt('0x' + hex.join(''));
}
Usage:
b64ToBn("AQAB");
// 65537n
atob for node:
// ASCII (base64) to Binary string
function atob(b64) {
return Buffer.from(b64, 'base64').toString('binary');
}
BigInt to Base64
From BigInt to hex to binary string to Base64:
function bnToB64(bn) {
var hex = BigInt(bn).toString(16);
if (hex.length % 2) { hex = '0' + hex; }
var bin = [];
var i = 0;
var d;
var b;
while (i < hex.length) {
d = parseInt(hex.slice(i, i + 2), 16);
b = String.fromCharCode(d);
bin.push(b);
i += 2;
}
return btoa(bin.join(''));
}
Usage:
bnToB64("65537");
// "AQAB"
btoa for node:
// Binary string to ASCII (base64)
function btoa(bin) {
return Buffer.from(bin, 'binary').toString('base64');
}
URL Safe Base64
If you're BigInts for JWKs you'll need to convert base64 to URL Safe Base64 and back as well.
That's also easy:
function base64ToUrlBase64(str) {
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
function urlBase64ToBase64(str) {
var r = str % 4;
if (2 === r) {
str += '==';
} else if (3 === r) {
str += '=';
}
return str.replace(/-/g, '+').replace(/_/g, '/');
}
Articles in my JS BigInt Series
- BigInts land in Chrome and node.js
- Big Number to Hex Conversion in JavaScript
- Hex to (signed) Big Int in JS
- Going between JS BigInts and TypedArrays
- A Primer to Big Int Encoding
By AJ ONeal
Did I make your day?
Buy me a coffee
(you can learn about the bigger picture I'm working towards on my patreon page )