UNPKG

exp-net

Version:
193 lines (161 loc) 3.91 kB
/*! * base32.js - base32 for bcoin * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const assert = require('assert'); /* * Constants */ const base32 = 'abcdefghijklmnopqrstuvwxyz234567'; const padding = [0, 6, 4, 3, 1]; const unbase32 = {}; for (let i = 0; i < base32.length; i++) unbase32[base32[i]] = i; /** * Encode a base32 string. * @param {Buffer} data * @returns {String} */ exports.encode = function encode(data) { assert(Buffer.isBuffer(data)); let str = ''; let mode = 0; let left = 0; for (let i = 0; i < data.length; i++) { const ch = data[i]; switch (mode) { case 0: str += base32[ch >>> 3]; left = (ch & 7) << 2; mode = 1; break; case 1: str += base32[left | (ch >>> 6)]; str += base32[(ch >>> 1) & 31]; left = (ch & 1) << 4; mode = 2; break; case 2: str += base32[left | (ch >>> 4)]; left = (ch & 15) << 1; mode = 3; break; case 3: str += base32[left | (ch >>> 7)]; str += base32[(ch >>> 2) & 31]; left = (ch & 3) << 3; mode = 4; break; case 4: str += base32[left | (ch >>> 5)]; str += base32[ch & 31]; mode = 0; break; } } if (mode > 0) { str += base32[left]; for (let i = 0; i < padding[mode]; i++) str += '='; } return str; }; /** * Decode a base32 string. * @param {String} str * @returns {Buffer} */ exports.decode = function decode(str) { assert(typeof str === 'string'); const data = Buffer.allocUnsafe(str.length * 5 / 8 | 0); let mode = 0; let left = 0; let j = 0; let i; for (i = 0; i < str.length; i++) { const ch = unbase32[str[i]]; if (ch == null) break; switch (mode) { case 0: left = ch; mode = 1; break; case 1: data[j++] = (left << 3) | (ch >>> 2); left = ch & 3; mode = 2; break; case 2: left = left << 5 | ch; mode = 3; break; case 3: data[j++] = (left << 1) | (ch >>> 4); left = ch & 15; mode = 4; break; case 4: data[j++] = (left << 4) | (ch >>> 1); left = ch & 1; mode = 5; break; case 5: left = left << 5 | ch; mode = 6; break; case 6: data[j++] = (left << 2) | (ch >>> 3); left = ch & 7; mode = 7; break; case 7: data[j++] = (left << 5) | ch; mode = 0; break; } } switch (mode) { case 0: break; case 1: case 3: case 6: throw new Error('Invalid base32 string.'); case 2: if (left > 0) throw new Error('Invalid padding.'); if (str.slice(i, i + 6) !== '======') throw new Error('Invalid base32 character.'); if (unbase32[str[i + 6]] != null) throw new Error('Invalid padding.'); break; case 4: if (left > 0) throw new Error('Invalid padding.'); if (str.slice(i, i + 4) !== '====') throw new Error('Invalid base32 character.'); if (unbase32[str[i + 4]] != null) throw new Error('Invalid padding.'); break; case 5: if (left > 0) throw new Error('Invalid padding.'); if (str.slice(i, i + 3) !== '===') throw new Error('Invalid base32 character.'); if (unbase32[str[i + 3]] != null) throw new Error('Invalid padding.'); break; case 7: if (left > 0) throw new Error('Invalid padding.'); if (str[i] !== '=') throw new Error('Invalid base32 character.'); if (unbase32[str[i + 1]] != null) throw new Error('Invalid padding.'); break; } return data.slice(0, j); };