Skip to content

Instantly share code, notes, and snippets.

@neonphog
Created February 5, 2019 03:48
Show Gist options
  • Select an option

  • Save neonphog/6b255064381d54a7a81510657d70f782 to your computer and use it in GitHub Desktop.

Select an option

Save neonphog/6b255064381d54a7a81510657d70f782 to your computer and use it in GitHub Desktop.
special base58 encoded holochain agent ids (signing key only)
/*
* Base58 encoded 32 byte public key
* includes 7 parity characters (can correct 3 mistyped characters)
* includes 4 prefix characters (Hkey)
* is 63 characters long, so can be a dns segment
*
* To run this, put it in a directory, and:
* npm install base-x
* npm install @holochain/n-bch-rs
*
* Will output something like:
* test buffer: b53a2f27fe96fbbdee9fe23ee11808af1515bc1ae9162d974070a514986eaed3
* id: Hkey1DCSFbieX39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWE3584ECF21DBFE
* corrupt start: HZcy1DCSFbieX39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWE3584ECF21DBFE
* corrupt mid: Hkey1DCSFbAAA39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWE3584ECF21DBFE
* corrupt end: Hkey1DCSFbieX39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWEAAA4ECF21DBFE
* corrupt all: Akey1DCSFbAeX39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWEA584ECF21DBFE
* corrupt bad: HkeyAAAAFbieX39njvHxm6k98N8bM5kqGx4J5tbKa8SLz5ZGWE3584ECF21DBFE
* all decode success
*/
const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
const baseX = require('base-x')
const base58 = baseX(ALPHABET)
const base16 = baseX(ALPHABET.substr(0, 16))
const rs = require('@holochain/n-bch-rs')
const enc = new rs.Encoder(7)
const dec = new rs.Decoder(7)
function baseToBuf (k) {
const buf = Buffer.alloc(k.length)
for (let i = 0; i < 52; ++i) {
buf[i] = ALPHABET.indexOf(k[i])
}
return buf
}
function bufToBase (k) {
const out = []
for (let i = 0; i < k.byteLength; ++i) {
if (k[i] < 0 || k[i] >= ALPHABET.length) {
throw new Error('byte out of base58 range')
}
out.push(ALPHABET[k[i]])
}
return out.join('')
}
function encode (buffer) {
let tmp
tmp = base58.encode(buffer)
while (tmp.length < 45) {
tmp = ALPHABET[0] + tmp
}
const key = 'Hkey' + tmp
tmp = baseToBuf(key)
tmp = enc.encode(tmp)
tmp = tmp.slice(49)
const parity = base16.encode(tmp)
return key + parity
}
function decode (id) {
let tmp
tmp = Buffer.concat([
baseToBuf(id.substr(0, 49)),
base16.decode(id.substr(49))
])
tmp = dec.correct(tmp)
tmp = tmp.slice(0, 49)
tmp = bufToBase(tmp).slice(4)
tmp = base58.decode(tmp)
while (tmp.byteLength > 32) {
tmp = tmp.slice(1)
}
return tmp
}
const crypto = require('crypto')
function main () {
const testBuf = crypto.randomBytes(32)
console.log(' test buffer:', testBuf.toString('hex'))
const id = encode(testBuf)
console.log(' id:', id)
const res = decode(id).toString('hex')
if (res !== testBuf.toString('hex')) {
throw new Error('bad decode: ' + res)
}
const test = (tag, id) => {
console.log(('corrupt ' + tag + ':').padStart(14), id)
const res = decode(id).toString('hex')
if (res !== testBuf.toString('hex')) {
throw new Error('bad decode: ' + res)
}
}
test('start', 'HZc' + id.slice(3))
test('mid', id.slice(0, 10) + 'AAA' + id.slice(13))
test('end', id.slice(0, 50) + 'AAA' + id.slice(53))
test('all',
'A' + id.slice(1, 10) + 'A' + id.slice(11, 50) + 'A' + id.slice(51))
;(() => {
try {
const badId = ['H', 'k', 'e', 'y']
let count = 0
for (let i of id.slice(4)) {
if (i === 'A') {
badId.push('A')
} else if (count < 4) {
badId.push('A')
++count
} else {
badId.push(i)
}
}
test('bad', badId.join(''))
} catch (e) {
return
}
throw new Error('expected exception, got success')
})()
console.log('all decode success')
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment