UNPKG

shamirs-secret-sharing-ts

Version:

A simple implementation of Shamir's Secret Sharing configured to use a finite field in GF(2^8) with 128 bit padding

79 lines (78 loc) 2.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const points_1 = require("./points"); const random_1 = require("./random"); const codec = require("./codec"); const constants_1 = require("./constants"); // n = MAX_SHARES // x = 0 ... n // y = n ... 2n const scratch = new Array(2 * constants_1.MAX_SHARES); /** * Split a secret into a set of distinct shares with a configured threshold * of shares needed for construction. * @public * @param {String|Buffer} secret * @param {Object} opts * @param {Object} opts.shares * @param {Object} opts.threshold * @param {?(Function)} opts.random * @returns {Array<Buffer>} * @throws TypeError * @throws RangeError */ function split(secret, opts) { if (!secret || (secret && 0 === secret.length)) { throw new TypeError('Secret cannot be empty.'); } if ('string' === typeof secret) { secret = Buffer.from(secret); } if (false === Buffer.isBuffer(secret)) { throw new TypeError('Expecting secret to be a buffer.'); } if (!opts || 'object' !== typeof opts) { throw new TypeError('Expecting options to be an object.'); } if ('number' !== typeof opts.shares) { throw new TypeError('Expecting shares to be a number.'); } if (!opts.shares || opts.shares < 0 || opts.shares > constants_1.MAX_SHARES) { throw new RangeError(`Shares must be 0 < shares <= ${constants_1.MAX_SHARES}.`); } if ('number' !== typeof opts.threshold) { throw new TypeError('Expecting threshold to be a number.'); } if (!opts.threshold || opts.threshold < 0 || opts.threshold > opts.shares) { throw new RangeError(`Threshold must be 0 < threshold <= ${opts.shares}.`); } if (!opts.random || 'function' !== typeof opts.random) { opts.random = random_1.random; } const hex = codec.hex(secret); const bin = codec.bin(hex, 16); // prepend 1 to get extra padding, we'll account for this later const parts = codec.split('1' + bin, constants_1.BIT_PADDING, 2); for (let i = 0; i < parts.length; ++i) { const p = points_1.points(parts[i], opts); for (let j = 0; j < opts.shares; ++j) { if (!scratch[j]) { scratch[j] = p[j].x.toString(16); } const z = p[j].y.toString(2); const y = scratch[j + constants_1.MAX_SHARES] || ''; // y[j] = p[j][y] + y[j] scratch[j + constants_1.MAX_SHARES] = codec.pad(z) + y; } } for (let i = 0; i < opts.shares; ++i) { const x = scratch[i]; const y = codec.hex(scratch[i + constants_1.MAX_SHARES], constants_1.BIN_ENCODING); scratch[i] = codec.encode(x, y); scratch[i] = Buffer.from('0' + scratch[i], 'hex'); } const result = scratch.slice(0, opts.shares); scratch.fill(0); return result; } exports.split = split;