const encodeTable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'.split('') const decodeTable = {} for (const idx in encodeTable) { decodeTable[encodeTable[idx]] = idx } const base32 = {} module.exports = base32 /** * encode byte data to string * @param {ArrayBuffer} b buffer data * @return {string} */ base32.encodeToString = (b) => { if (!(b instanceof Buffer)) throw new Error('input not Buffer') if (b.length === 0) return '' let str = '' const len = b.length let v1, v2, v3, v4, v5 const count = parseInt(len / 5) * 5 let i = 0 while (i < count) { v1 = b[i++] v2 = b[i++] v3 = b[i++] v4 = b[i++] v5 = b[i++] str += encodeTable[v1 >>> 3] + encodeTable[(v1 << 2 | v2 >>> 6) & 31] + encodeTable[(v2 >>> 1) & 31] + encodeTable[(v2 << 4 | v3 >>> 4) & 31] + encodeTable[(v3 << 1 | v4 >>> 7) & 31] + encodeTable[(v4 >>> 2) & 31] + encodeTable[(v4 << 3 | v5 >>> 5) & 31] + encodeTable[v5 & 31] } const remain = len - count switch (remain) { case 1: v1 = b[i] str += encodeTable[v1 >>> 3] + encodeTable[(v1 << 2) & 31] + '======' break case 2: v1 = b[i++] v2 = b[i] str += encodeTable[v1 >>> 3] + encodeTable[(v1 << 2 | v2 >>> 6) & 31] + encodeTable[(v2 >>> 1) & 31] + encodeTable[(v2 << 4) & 31] + '====' break case 3: v1 = b[i++] v2 = b[i++] v3 = b[i] str += encodeTable[v1 >>> 3] + encodeTable[(v1 << 2 | v2 >>> 6) & 31] + encodeTable[(v2 >>> 1) & 31] + encodeTable[(v2 << 4 | v3 >>> 4) & 31] + encodeTable[(v3 << 1) & 31] + '===' break case 4: v1 = b[i++] v2 = b[i++] v3 = b[i++] v4 = b[i] str += encodeTable[v1 >>> 3] + encodeTable[(v1 << 2 | v2 >>> 6) & 31] + encodeTable[(v2 >>> 1) & 31] + encodeTable[(v2 << 4 | v3 >>> 4) & 31] + encodeTable[(v3 << 1 | v4 >>> 7) & 31] + encodeTable[(v4 >>> 2) & 31] + encodeTable[(v4 << 3) & 31] + '=' break } return str } /** * decode base32 string to byte * @param {string} str * @return {ArrayBuffer} */ base32.decodeFromString = (str) => { if (typeof str !== 'string' || str.length === 0) throw new Error('input not string or empty') if (!/^[A-Z2-7=]+$/.test(str)) throw new Error('Invalid base32 characters') str = str.toUpperCase().replace(/=/g, '') let v = [] const buf = [] const len = str.length const count = len >> 3 << 3 let i = 0 while (i < count) { v[0] = decodeTable[str.charAt(i++)] v[1] = decodeTable[str.charAt(i++)] v[2] = decodeTable[str.charAt(i++)] v[3] = decodeTable[str.charAt(i++)] v[4] = decodeTable[str.charAt(i++)] v[5] = decodeTable[str.charAt(i++)] v[6] = decodeTable[str.charAt(i++)] v[7] = decodeTable[str.charAt(i++)] buf.push( (v[0] << 3 | v[1] >>> 2) & 0xff, (v[1] << 6 | v[2] << 1 | v[3] >>> 4) & 0xff, (v[3] << 4 | v[4] >>> 1) & 0xff, (v[4] << 7 | v[5] << 2 | v[6] >>> 3) & 0xff, (v[6] << 5 | v[7]) & 0xff ) } switch (len - count) { case 2: v[0] = decodeTable[str.charAt(i++)] v[1] = decodeTable[str.charAt(i++)] buf.push( (v[0] << 3 | v[1] >>> 2) & 0xff ) break case 4: v[0] = decodeTable[str.charAt(i++)] v[1] = decodeTable[str.charAt(i++)] v[2] = decodeTable[str.charAt(i++)] v[3] = decodeTable[str.charAt(i++)] buf.push( (v[0] << 3 | v[1] >>> 2) & 0xff, (v[1] << 6 | v[2] << 1 | v[3] >>> 4) & 0xff ) break case 5: v[0] = decodeTable[str.charAt(i++)] v[1] = decodeTable[str.charAt(i++)] v[2] = decodeTable[str.charAt(i++)] v[3] = decodeTable[str.charAt(i++)] v[4] = decodeTable[str.charAt(i++)] buf.push( (v[0] << 3 | v[1] >>> 2) & 0xff, (v[1] << 6 | v[2] << 1 | v[3] >>> 4) & 0xff, (v[3] << 4 | v[4] >>> 1) & 0xff ) break case 7: v[0] = decodeTable[str.charAt(i++)] v[1] = decodeTable[str.charAt(i++)] v[2] = decodeTable[str.charAt(i++)] v[3] = decodeTable[str.charAt(i++)] v[4] = decodeTable[str.charAt(i++)] v[5] = decodeTable[str.charAt(i++)] v[6] = decodeTable[str.charAt(i++)] buf.push( (v[0] << 3 | v[1] >>> 2) & 0xff, (v[1] << 6 | v[2] << 1 | v[3] >>> 4) & 0xff, (v[3] << 4 | v[4] >>> 1) & 0xff, (v[4] << 7 | v[5] << 2 | v[6] >>> 3) & 0xff ) break } return Buffer.from(buf) }