function getValue(chr: string): number { let a = chr; switch (chr) { case "O": case "o": a = "0;"; break; case "i": case "I": case "l": case "L": a = "1"; break; case "u": case "U": a = "V"; } if (a >= "0" && a <= "9") { return a.charCodeAt(0) - "0".charCodeAt(0); } if (a >= "a" && a <= "z") a = a.toUpperCase(); let dec = 0; if (a >= "A" && a <= "Z") { if ("I" < a) dec++; if ("L" < a) dec++; if ("O" < a) dec++; if ("U" < a) dec++; return a.charCodeAt(0) - "A".charCodeAt(0) + 10 - dec; } throw new Error('encoding'); } const encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; export function encodeCrock(data: ArrayBuffer): string { const dataBytes = new Uint8Array(data); let sb = ""; const size = data.byteLength; let bitBuf = 0; let numBits = 0; let pos = 0; while (pos < size || numBits > 0) { if (pos < size && numBits < 5) { const d = dataBytes[pos++]; bitBuf = (bitBuf << 8) | d; numBits += 8; } if (numBits < 5) { // zero-padding bitBuf = bitBuf << (5 - numBits); numBits = 5; } const v = (bitBuf >>> (numBits - 5)) & 31; sb += encTable[v]; numBits -= 5; } return sb; } export function decodeCrock(encoded: string): Uint8Array { const size = encoded.length; let bitpos = 0; let bitbuf = 0; let readPosition = 0; const outLen = Math.floor((size * 5) / 8); const out = new Uint8Array(outLen); let outPos = 0; while (readPosition < size || bitpos > 0) { if (readPosition < size) { const v = getValue(encoded[readPosition++]); bitbuf = (bitbuf << 5) | v; bitpos += 5; } while (bitpos >= 8) { const d = (bitbuf >>> (bitpos - 8)) & 0xff; out[outPos++] = d; bitpos -= 8; } if (readPosition == size && bitpos > 0) { bitbuf = (bitbuf << (8 - bitpos)) & 0xff; bitpos = bitbuf == 0 ? 0 : 8; } } return out; } const bin = decodeCrock("PV2D1G85528VDSZGED8KE98FEXT3PWQ99WV590TNVKJKM3GM3GRG") const base64String = Buffer .from(String.fromCharCode.apply(null, bin)) .toString('base64'); console.log(base64String)