Created
February 5, 2019 03:48
-
-
Save neonphog/6b255064381d54a7a81510657d70f782 to your computer and use it in GitHub Desktop.
special base58 encoded holochain agent ids (signing key only)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * 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