167 lines
4.5 KiB
JavaScript
167 lines
4.5 KiB
JavaScript
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)
|
|
}
|