Skip to content

Instantly share code, notes, and snippets.

@Creased
Created April 23, 2017 17:25
Show Gist options
  • Save Creased/ab49828928039769f3de2e16a2b04310 to your computer and use it in GitHub Desktop.
Save Creased/ab49828928039769f3de2e16a2b04310 to your computer and use it in GitHub Desktop.
/*!
* Author: Baptiste MOINE <contact@bmoine.fr>
* Project: OTP QR-Code Generator
* Homepage: https://vps.bmoine.fr/totp-qrcode/
* Released: 17/04/2017
*
* Based on http://www.herongyang.com/Encoding/Base32-Encoding-Algorithm.html
*
* Base32 encoding process:
* 0. Get input string + remove carriage return and new line;
* 1. Parse bytes from input string;
* 2. Add padding to divide input bytes to 5-bytes blocks;
* 3. Create 5-bits groups;
* 4. Map each group to one printable character based on the Base32 character set;
* 5. Override characters that aren't based on the input string, but padding;
* 6. (Facultative) Add padding to create 8-chars blocks;
* 7. Return the encoded string.
*/
function b32encode(str, padding) {
var opts = {
'alphabet': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
'pad': '=',
'padding': (padding === true) && true || false
},
str = str && str.toString().split('\r')[0].split('\n')[0] || ''; // 0
var left = str.length % 5; // 5
// 1
var out = (function(str) {
var bits = [];
for (var i = 0; i < str.length; ++i) {
bits[i] = ('000000000' + (str[i].charCodeAt(0).toString(2))).substr(-8);
}
return bits;
})(str.split(''));
// 2
out = (function(bits) {
var len = bits.length,
pad = '00000000';
var left = 5 - (len % 5);
if (left < 5) {
for (var i = 0; i < left; ++i) {
bits[len + i] = pad;
}
}
return bits;
})(out);
// 3
out = (function(bits) {
var len = bits.length,
parts = [];
for (var i = 0; i < len; ++i) {
var j = Math.floor((i / 5));
parts[j] = parts[j] && parts[j].toString() || '';
parts[j] += bits[i];
}
return parts;
})(out.join(''));
// 4
out = (function(bits, alphabet) {
var alphabet = alphabet && alphabet.toString() || 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
len = bits.length;
for (var i = 0; i < len; ++i) {
var j = parseInt(bits[i], 2);
bits[i] = alphabet[j];
}
return bits;
})(out, opts.alphabet);
// 5
var override = 0;
switch (left) {
case 1:
override = 6;
break;
case 2:
override = 4
break;
case 3:
override = 3;
break;
case 4:
override = 1;
break;
}
for (var i = 0; i < override; ++i) {
out.pop();
}
// 6
if (opts.padding) {
for (i = 0; i < override; ++i) {
out.push(opts.pad);
}
}
return out.join('');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment