Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Hex to Base32-encoding

I'm having issues converting something I know works in Ruby to Javascript (node.js in this case, but I'd like a browser supported solution, if possible)

Given a hex formatted sha256 digest of:

"0b08dfe80a49490ae0722b9306ff53c5ab3552d17905814e6688ee62c373"

Convert it to a base32 representation that looks like this:

"BMEN72AKJFEQVYDSFOJQN72TYWVTKUWRPECYCTTGRDXGFQ3T"

I can do this in ruby by running a quick routine that converts the hex to a character code string, then base32 encoding that. I can't seem to find a similar approach in JavaScript. There don't seem to be solid approaches for getting the character codes or Base32 encoding.

Ruby code as an example, I'm just chunking the hex out 1 character at a time, and doing a quick hex-> decimal -> character conversion:

s = "0b08dfe80a49490ae0722b9306ff53c5ab3552d17905814e6688ee62c373"
s2 = s.scan(/../).map { |x| x.hex.chr }.join
s3 = Base32.encode(s2)

The intermediary string looks like this:

"\v\b\xDF\xE8\nII\n\xE0r+\x93\x06\xFFS\xC5\xAB5R\xD1y\x05\x81Nf\x88\xEEb\xC3s\x8AM"
like image 670
Chris C. Avatar asked Feb 08 '23 12:02

Chris C.


1 Answers

Bear in mind that there are several base32 specifications.

It looks like you're using RFC 4648 "base32", but most JS implementations I know use either RFC 4648 "base32hex" or Douglas Crockfords Base32.

The only JS implementation of RFC 4648 "base32" I know is hi-base32.

Here is an example of converting hex (a.k.a. base16) string to RFC 4648 base32 with it:

var base32 = require('hi-base32');

var s = "0b08dfe80a49490ae0722b9306ff53c5ab3552d17905814e6688ee62c373";
var s2 = base32.encode(new Buffer(s, 'hex'));
// => 'BMEN72AKJFEQVYDSFOJQN72TYWVTKUWRPECYCTTGRDXGFQ3T'

But if you want to use hi-base32 in a browser you'll have to convert your hex string to bytes array yourself:

var s = "0b08dfe80a49490ae0722b9306ff53c5ab3552d17905814e6688ee62c373";
if (s.length % 2 !== 0) {
  // odd number of characters
  s = '0' + s;
}
var bytes = [];
for (var i = 0; i < s.length; i = i + 2) {
  bytes.push(parseInt(s.slice(i, i + 2), 16));
}
var s2 = base32.encode(bytes);
like image 169
Leonid Beschastny Avatar answered Feb 12 '23 12:02

Leonid Beschastny