up8-ticket

Securely generate UP8-compatible, @q-encoded master tickets.
Log | Files | Refs | README | LICENSE

commit 0111c7a1b26f9c3a7ebf8b7ea64bc466627a4ca6
parent 9494ab7b1dcd761fbc07ca04302a37eb5374eb4c
Author: Jared Tobin <jared@jtobin.io>
Date:   Tue, 22 Sep 2020 20:33:52 -0230

up8-ticket: fix missing consts, add test suite

Diffstat:
Msrc/index.js | 5+++--
Atest/test.js | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/src/index.js b/src/index.js @@ -12,6 +12,7 @@ const GALOIS_BITSIZE = 8 */ const unpad = str => { if (!(str.slice(0, 1) === '0')) { + /* istanbul ignore next */ throw new Error('nonzero leading digit -- please report this as a bug!') } @@ -103,7 +104,7 @@ const gen_ticket_more = (nbits, addl) => { * @param {Number} k the desired threshold value, smaller than 'n' * @return {Array<String>} an array of 'n' @q-encoded shards */ -shard = (ticket, n, k) => { +const shard = (ticket, n, k) => { if (!ob.isValidPatq(ticket)) { throw new Error('input is not @q-encoded') } @@ -125,7 +126,7 @@ shard = (ticket, n, k) => { * @param {Array<String>} shards an array of @q-encoded shards * @return {String} a @q-encoded ticket */ -combine = shards => { +const combine = shards => { const hexshards = shards.map(ob.patq2hex).map(unpad) const hexticket = secrets.combine(hexshards) return ob.hex2patq(hexticket) diff --git a/test/test.js b/test/test.js @@ -0,0 +1,109 @@ +const { expect } = require('chai') +const jsc = require('jsverify') +const ob = require('urbit-ob') + +const mtg = require('../src') + +// mocha, jsverify stuff + +// needs to be required explicitly +global.crypto = require('crypto') + +const ticket_bytes = jsc.elements([8, 16, 24, 32, 40, 48, 56, 64]) + +// tests + +describe('gen_ticket_simple', () => { + + it('produces tickets of the correct bitlength', () => { + let prop = jsc.forall(ticket_bytes, bytes => { + let bits = bytes * 8 + let ticket = mtg.gen_ticket_simple(bits) + let hex = ob.patq2hex(ticket) + let nbits = hex.length * 4 + return (bits === nbits) + }) + + jsc.assert(prop) + }) + +}) + +describe('gen_ticket_more', () => { + + it('produces tickets of the correct bitlength', async () => { + let given_bits = 384 + let ticket = await mtg.gen_ticket_more(given_bits) + let hex = ob.patq2hex(ticket) + let expected_bits = hex.length * 4 + expect(expected_bits).to.equal(given_bits) + }) + +}) + +describe('shard', () => { + + it('throws on non-@q input', () => { + expect(() => mtg.shard('flubblub', 3, 2)).to.throw() + }) + + it("using 3/2 sharding, produces shards that are recombinable", () => { + let prop = jsc.forall(ticket_bytes, bytes => { + let bits = bytes * 8 + let ticket = mtg.gen_ticket_simple(bits) + let shards = mtg.shard(ticket, 3, 2) + let combined0 = mtg.combine(shards.slice(0, 2)) + let combined1 = mtg.combine(shards.slice(1, 3)) + let combined2 = mtg.combine([shards[0], shards[2]]) + let combined3 = mtg.combine(shards) + + return ( + (ticket === combined0) && + (ticket === combined1) && + (ticket === combined2) && + (ticket === combined3) + ) + }) + + jsc.assert(prop) + }) + + it("using 5/3 sharding, produces shards that are recombinable", () => { + let prop = jsc.forall(ticket_bytes, bytes => { + let bits = bytes * 8 + let ticket = mtg.gen_ticket_simple(bits) + let shards = mtg.shard(ticket, 5, 3) + + let combined0 = mtg.combine([shards[0], shards[1], shards[2]]) + let combined1 = mtg.combine([shards[0], shards[1], shards[3]]) + let combined2 = mtg.combine([shards[0], shards[1], shards[4]]) + + let combined3 = mtg.combine([shards[0], shards[2], shards[3]]) + let combined4 = mtg.combine([shards[0], shards[2], shards[4]]) + + let combined5 = mtg.combine([shards[1], shards[2], shards[3]]) + let combined6 = mtg.combine([shards[1], shards[2], shards[4]]) + + let combined7 = mtg.combine([shards[2], shards[3], shards[4]]) + + let combined8 = mtg.combine(shards) + + return ( + (ticket === combined0) && + (ticket === combined1) && + (ticket === combined2) && + (ticket === combined3) && + (ticket === combined4) && + (ticket === combined5) && + (ticket === combined6) && + (ticket === combined7) && + (ticket === combined8) + ) + }) + + jsc.assert(prop) + }) + +}) + +