Skip to content

Instantly share code, notes, and snippets.

@max-mapper
Last active May 17, 2023 06:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save max-mapper/5e8309fad6c6c3ca7df31b63bd0e9a10 to your computer and use it in GitHub Desktop.
Save max-mapper/5e8309fad6c6c3ca7df31b63bd0e9a10 to your computer and use it in GitHub Desktop.
JavaScript Base-40 Class
// based on https://github.com/blockstack/blockstack-core/blob/ff86948ed2f720824cd5e6ece6a63aaaf2bf81ff/blockstack/lib/b40.py
class B40 {
constructor() {
this.B16_CHARS = '0123456789abcdef'
this.B40_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz-_.+'
}
divmod(x, y) {
const div = x / y
const rem = x % y
return [div, rem]
}
intToCharset(val, charset) {
if (val < BigInt(0)) return
if (val === BigInt(0)) return charset[0]
let output = ''
while (val > BigInt(0)) {
let [newval, digit] = this.divmod(val, BigInt(charset.length))
val = newval
output += charset[digit]
}
return output
.split('')
.reverse()
.join('')
}
charsetToInt(str, charset) {
let output = BigInt(0)
str.split('').forEach(function(char) {
output = output * BigInt(charset.length) + BigInt(charset.indexOf(char))
})
return output
}
convertCharset(str, original, target) {
let intermediate = this.charsetToInt(str, original)
return this.intToCharset(intermediate, target)
}
hexPad(x) {
return (x.length % 2) > 0 ? ('0' * (x.length % 2)) + x : x
}
charsetToHex(str, charset) {
return this.hexPad(this.convertCharset(str, charset, this.B16_CHARS))
}
hexToCharset(str, charset) {
return this.convertCharset(str, this.B16_CHARS, charset)
}
base40ToBin(str) {
return Buffer.from(this.charsetToHex(str, this.B40_CHARS), 'hex')
}
binToBase40(buf) {
return this.hexToCharset(buf.toString('hex'), this.B40_CHARS)
}
base40ToHex(str) {
return this.base40ToBin(str).toString('hex')
}
}
export default B40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment