From 836a9f4bd5cd6fa71924dbaa1eb7d3fbff54a38a Mon Sep 17 00:00:00 2001 From: YuwanXiao <42989502+YuwanXiao@users.noreply.github.com> Date: Tue, 11 Aug 2020 11:10:59 -0400 Subject: [PATCH] npm update --- dist/jiff-client.js | 50072 ++++++++++++++++----------- lib/client/protocols/gmw_bit/IO.js | 7 +- lib/jiff-client.js | 1 + package.json | 80 - 4 files changed, 30154 insertions(+), 20006 deletions(-) delete mode 100644 package.json diff --git a/dist/jiff-client.js b/dist/jiff-client.js index 5b2fad4d3..ae38a89d1 100644 --- a/dist/jiff-client.js +++ b/dist/jiff-client.js @@ -1,8339 +1,9313 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JIFFClient = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i] - the base operation id to use when generating unique ids for communication - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length here will be max(|bits|, |constant|) + 1 - * in case of potential overflow / carry - */ - jiffClient.protocols.bits.cadd = arithmetic.cadd.bind(null, jiffClient); - /** - * Compute [secret bits] - [constant bits] - * @method - * @memberof bits - * @param {number} constant - the constant - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - jiffClient.protocols.bits.csubl = arithmetic.csubl.bind(null, jiffClient); - /** - * Compute [constant bits] - [secret bits] - * @method - * @memberof bits - * @param {number} constant - the constant - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - jiffClient.protocols.bits.csubr = arithmetic.csubr.bind(null, jiffClient); - /** - * - * Compute [secret bits1] + [secret bits2] - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - the first bitwise shared number: array of secrets with index 0 being least significant bit - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number (length may be different) - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit - */ - jiffClient.protocols.bits.sadd = arithmetic.sadd.bind(null, jiffClient); - /** - * Compute [secret bits1] - [secret bits2] - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - first bitwise secret shared number: lower indices represent less significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - second bitwise secret shared number (length may be different) - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - jiffClient.protocols.bits.ssub = arithmetic.ssub.bind(null, jiffClient); - /** - * Compute [secret bits] * constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - bitwise shared secret to multiply: lower indices represent less significant bits - * @param {number} constant - constant to multiply with - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits.length + ceil(log2(constant)), except - * if constant is zero, the result will then be [ zero share ] - */ - jiffClient.protocols.bits.cmult = arithmetic.cmult.bind(null, jiffClient); - /** - * Compute [secret bits1] * [secret bits2] - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - bitwise shared secret to multiply: lower indices represent less significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - bitwise shared secret to multiply - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits1.length + bits2.length - */ - jiffClient.protocols.bits.smult = arithmetic.smult.bind(null, jiffClient); - /** - * Computes integer division of [secret bits 1] / [secret bits 2] - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as bits1, - * and the remainder array has the same length as bits2 or bits1, whichever is smaller. - * Note: if bits2 represent 0, the returned result is the maximum - * number that fits in the number of bits (all 1), and the remainder - * is equal to bits1 - */ - jiffClient.protocols.bits.sdiv = arithmetic.sdiv.bind(null, jiffClient); - /** - * Computes integer division of [secret bits] / constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - numerator: an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the denominator number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as bits, - * and the remainder array has the same length as - * constant or bits, whichever is smaller - * @throws if constant is 0. - */ - jiffClient.protocols.bits.cdivl = arithmetic.cdivl.bind(null, jiffClient); - /** - * Computes integer division of constant / [secret bits] - * @method - * @memberof bits - * @param {number} constant - the numerator number - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - denominator: an array of secret shares of bits, starting from least to most significant bits - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as the number of bits in constant, - * and the remainder array has the same length as bits or constant, whichever is smaller. - * Note: if bits represent 0, the returned result is the maximum - * number that fits in its bits (all 1), and the remainder - * is equal to constant - */ - jiffClient.protocols.bits.cdivr = arithmetic.cdivr.bind(null, jiffClient); - - /** - * Checks whether the given bitwise secret shared number and numeric constant are equal - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if parameters are equal, 0 otherwise. If result is known - * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.ceq = comparison.ceq.bind(null, jiffClient); - /** - * Checks whether the given bitwise secret shared number and numeric constant are not equal - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if parameters are not equal, 0 otherwise. If result is known - * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.cneq = comparison.cneq.bind(null, jiffClient); - /** - * Checks whether given secret shared bits are greater than the given constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are greater than constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.cgt = comparison.cgt.bind(null, jiffClient); - /** - * Checks whether given secret shared bits are greater or equal to the given constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are greater or equal to constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit or constant is zero), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.cgteq = comparison.cgteq.bind(null, jiffClient); - /** - * Checks whether given secret shared bits are less than the given constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are less than the constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.clt = comparison.clt.bind(null, jiffClient); - /** - * Checks whether given secret shared bits are less or equal to the given constant - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are less or equal to constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - jiffClient.protocols.bits.clteq = comparison.clteq.bind(null, jiffClient); - /** - * Checks whether the two given bitwise secret shared numbers are equal - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are equal, 0 otherwise - */ - jiffClient.protocols.bits.seq = comparison.seq.bind(null, jiffClient); - /** - * Checks whether the two given bitwise secret shared numbers are not equal - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are not equal, 0 otherwise - */ - jiffClient.protocols.bits.sneq = comparison.sneq.bind(null, jiffClient); - /** - * Checks whether the first given bitwise secret shared number is greater than the second bitwise secret shared number - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater than the second, 0 otherwise - */ - jiffClient.protocols.bits.sgt = comparison.sgt.bind(null, jiffClient); - /** - * Checks whether the first given bitwise secret shared number is greater than or equal to the second bitwise secret shared number - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater or equal to the second, 0 otherwise - */ - jiffClient.protocols.bits.sgteq = comparison.sgteq.bind(null, jiffClient); - /** - * Checks whether the first given bitwise secret shared number is less than the second bitwise secret shared number - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than the second, 0 otherwise - */ - jiffClient.protocols.bits.slt = comparison.slt.bind(null, jiffClient); - /** - * Checks whether the first given bitwise secret shared number is less or equal to the second bitwise secret shared number - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than or equal to the second, 0 otherwise - */ - jiffClient.protocols.bits.slteq = comparison.slteq.bind(null, jiffClient); - - /** - * Retrieves preprocessed rejection_sampling bits or performs the rejection sampling on the fly if crypto_provider is enabled - * @method - * @memberof bits - * @param {number} lower_bound - the lower bound, included (can be a bigNumber if using bigNumber extension) - * @param {number} upper_bound - the upper bound, excluded (can be a bigNumber if using bigNumber extension) - * @param {number} [threshold=parties.length] - the threshold of the resulting shares after sampling - * @param {Array} [parties=all_parties] - array of party ids that want to receive (or compute if needed) the sampling shares, by default, this includes all parties - * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly - * @returns {SecretShare[]} an array of secret shares, each representing a bit from the sampled value (from least to most significant) - */ - jiffClient.protocols.bits.rejection_sampling = otherProtocols.rejection_sampling.bind(null, jiffClient); - - /** - * Creates a secret share of the number represented by the given array of secret shared bits. - * Requires no communication, only local operations - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits. - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of the number represented by bits. - */ - jiffClient.protocols.bits.bit_composition = otherProtocols.bit_composition; - - /** - * Share a number as an array of secret bits - * This takes the same parameters as jiff-instance.share, but returns an array of secret bit shares per sending party. - * Each bit array starts with the least significant bit at index 0, and most significant bit at index length-1 - * @method - * @memberof bits - * @param {number} secret - the number to share (this party's input) - * @param {number} [bit_length=jiff_instance.Zp] - the number of generated bits, if the secret has less bits, it will be - * padded with zeros - * @param {number} [threshold=receivers_list.length] - threshold of each shared bit - * @param {Array} [receivers_list=all_parties] - receivers of every bits - * @param {Array} [senders_list=all_parties] - senders of evey bit - * @param {number} [Zp=jiff_instance.Zp] - the field of sharing for every bit - * @param {string|number} [share_id=auto_gen()] - synchronization id - * @returns {object} a map (of size equal to the number of parties) - * where the key is the party id (from 1 to n) - * and the value is an array of secret shared bits - */ - jiffClient.protocols.bits.share = sharing.share_bits.bind(null, jiffClient); - /** - * Opens the given array of secret shared bits. - * This works regardless of whether the represented value fit inside the corresponding field or not - * @method - * @memberof bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number[]} parties - parties to open (same as jiff_instance.open) - * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open - * @returns {promise} a promise to the number represented by bits - */ - jiffClient.protocols.bits.open = sharing.open_bits.bind(null, jiffClient); - /** - * Receives an opening of an array of secret bits without owning shares of the underlying value. - * Similar to jiff.receive_open() but for bits. - * This works regardless of whether the represented value fit inside the corresponding field or not - * @method - * @memberOf jiff-instance.protocols.bits - * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares - * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result - * @param {number} [count=ceil(log2(Zp))] - the number of bits being opened - * @param {number} [threshold=parties.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders - * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string|number|object} [op_id=auto_gen()] - unique and consistent synchronization id between all parties - * @returns {promise} a (JQuery) promise to the open value of the secret - */ - jiffClient.protocols.bits.receive_open = sharing.receive_open_bits.bind(null, jiffClient); +var arithmetic = require('../protocols/bits/arithmetic.js'); +var comparison = require('../protocols/bits/comparison.js'); +var otherProtocols = require('../protocols/bits/protocols.js'); +var sharing = require('../protocols/bits/sharing.js'); + +/** + * Contains bits protocols (including rejection sampling and bits operations) + * + * Important: bit protocols (including bit_decomposition) are unaware of any extension specific customizations, and will operate as + * on the given shares as if they are natural numbers in Zp. Make sure to take into consideration any magnification/shift transformations + * needed to translate correctly between plain representations and extension representations of bits! + * @alias bits + * @namespace + */ + +module.exports = function (jiffClient) { + /** + * Compute sum of bitwise secret shared number and a constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {number} constant - the constant + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length here will be max(|bits|, |constant|) + 1 + * in case of potential overflow / carry + */ + jiffClient.protocols.bits.cadd = arithmetic.cadd.bind(null, jiffClient); + /** + * Compute [secret bits] - [constant bits] + * @method + * @memberof bits + * @param {number} constant - the constant + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + jiffClient.protocols.bits.csubl = arithmetic.csubl.bind(null, jiffClient); + /** + * Compute [constant bits] - [secret bits] + * @method + * @memberof bits + * @param {number} constant - the constant + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + jiffClient.protocols.bits.csubr = arithmetic.csubr.bind(null, jiffClient); + /** + * + * Compute [secret bits1] + [secret bits2] + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - the first bitwise shared number: array of secrets with index 0 being least significant bit + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number (length may be different) + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit + */ + jiffClient.protocols.bits.sadd = arithmetic.sadd.bind(null, jiffClient); + /** + * Compute [secret bits1] - [secret bits2] + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - first bitwise secret shared number: lower indices represent less significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - second bitwise secret shared number (length may be different) + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + jiffClient.protocols.bits.ssub = arithmetic.ssub.bind(null, jiffClient); + /** + * Compute [secret bits] * constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - bitwise shared secret to multiply: lower indices represent less significant bits + * @param {number} constant - constant to multiply with + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits.length + ceil(log2(constant)), except + * if constant is zero, the result will then be [ zero share ] + */ + jiffClient.protocols.bits.cmult = arithmetic.cmult.bind(null, jiffClient); + /** + * Compute [secret bits1] * [secret bits2] + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - bitwise shared secret to multiply: lower indices represent less significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - bitwise shared secret to multiply + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits1.length + bits2.length + */ + jiffClient.protocols.bits.smult = arithmetic.smult.bind(null, jiffClient); + /** + * Computes integer division of [secret bits 1] / [secret bits 2] + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as bits1, + * and the remainder array has the same length as bits2 or bits1, whichever is smaller. + * Note: if bits2 represent 0, the returned result is the maximum + * number that fits in the number of bits (all 1), and the remainder + * is equal to bits1 + */ + jiffClient.protocols.bits.sdiv = arithmetic.sdiv.bind(null, jiffClient); + /** + * Computes integer division of [secret bits] / constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - numerator: an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the denominator number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as bits, + * and the remainder array has the same length as + * constant or bits, whichever is smaller + * @throws if constant is 0. + */ + jiffClient.protocols.bits.cdivl = arithmetic.cdivl.bind(null, jiffClient); + /** + * Computes integer division of constant / [secret bits] + * @method + * @memberof bits + * @param {number} constant - the numerator number + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - denominator: an array of secret shares of bits, starting from least to most significant bits + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as the number of bits in constant, + * and the remainder array has the same length as bits or constant, whichever is smaller. + * Note: if bits represent 0, the returned result is the maximum + * number that fits in its bits (all 1), and the remainder + * is equal to constant + */ + jiffClient.protocols.bits.cdivr = arithmetic.cdivr.bind(null, jiffClient); + + /** + * Checks whether the given bitwise secret shared number and numeric constant are equal + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if parameters are equal, 0 otherwise. If result is known + * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.ceq = comparison.ceq.bind(null, jiffClient); + /** + * Checks whether the given bitwise secret shared number and numeric constant are not equal + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if parameters are not equal, 0 otherwise. If result is known + * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.cneq = comparison.cneq.bind(null, jiffClient); + /** + * Checks whether given secret shared bits are greater than the given constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are greater than constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.cgt = comparison.cgt.bind(null, jiffClient); + /** + * Checks whether given secret shared bits are greater or equal to the given constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are greater or equal to constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit or constant is zero), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.cgteq = comparison.cgteq.bind(null, jiffClient); + /** + * Checks whether given secret shared bits are less than the given constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are less than the constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.clt = comparison.clt.bind(null, jiffClient); + /** + * Checks whether given secret shared bits are less or equal to the given constant + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are less or equal to constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + jiffClient.protocols.bits.clteq = comparison.clteq.bind(null, jiffClient); + /** + * Checks whether the two given bitwise secret shared numbers are equal + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are equal, 0 otherwise + */ + jiffClient.protocols.bits.seq = comparison.seq.bind(null, jiffClient); + /** + * Checks whether the two given bitwise secret shared numbers are not equal + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are not equal, 0 otherwise + */ + jiffClient.protocols.bits.sneq = comparison.sneq.bind(null, jiffClient); + /** + * Checks whether the first given bitwise secret shared number is greater than the second bitwise secret shared number + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater than the second, 0 otherwise + */ + jiffClient.protocols.bits.sgt = comparison.sgt.bind(null, jiffClient); + /** + * Checks whether the first given bitwise secret shared number is greater than or equal to the second bitwise secret shared number + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater or equal to the second, 0 otherwise + */ + jiffClient.protocols.bits.sgteq = comparison.sgteq.bind(null, jiffClient); + /** + * Checks whether the first given bitwise secret shared number is less than the second bitwise secret shared number + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than the second, 0 otherwise + */ + jiffClient.protocols.bits.slt = comparison.slt.bind(null, jiffClient); + /** + * Checks whether the first given bitwise secret shared number is less or equal to the second bitwise secret shared number + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than or equal to the second, 0 otherwise + */ + jiffClient.protocols.bits.slteq = comparison.slteq.bind(null, jiffClient); + + /** + * Retrieves preprocessed rejection_sampling bits or performs the rejection sampling on the fly if crypto_provider is enabled + * @method + * @memberof bits + * @param {number} lower_bound - the lower bound, included (can be a bigNumber if using bigNumber extension) + * @param {number} upper_bound - the upper bound, excluded (can be a bigNumber if using bigNumber extension) + * @param {number} [threshold=parties.length] - the threshold of the resulting shares after sampling + * @param {Array} [parties=all_parties] - array of party ids that want to receive (or compute if needed) the sampling shares, by default, this includes all parties + * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly + * @returns {SecretShare[]} an array of secret shares, each representing a bit from the sampled value (from least to most significant) + */ + jiffClient.protocols.bits.rejection_sampling = otherProtocols.rejection_sampling.bind(null, jiffClient); + + /** + * Creates a secret share of the number represented by the given array of secret shared bits. + * Requires no communication, only local operations + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits. + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of the number represented by bits. + */ + jiffClient.protocols.bits.bit_composition = otherProtocols.bit_composition; + + /** + * Share a number as an array of secret bits + * This takes the same parameters as jiff-instance.share, but returns an array of secret bit shares per sending party. + * Each bit array starts with the least significant bit at index 0, and most significant bit at index length-1 + * @method + * @memberof bits + * @param {number} secret - the number to share (this party's input) + * @param {number} [bit_length=jiff_instance.Zp] - the number of generated bits, if the secret has less bits, it will be + * padded with zeros + * @param {number} [threshold=receivers_list.length] - threshold of each shared bit + * @param {Array} [receivers_list=all_parties] - receivers of every bits + * @param {Array} [senders_list=all_parties] - senders of evey bit + * @param {number} [Zp=jiff_instance.Zp] - the field of sharing for every bit + * @param {string|number} [share_id=auto_gen()] - synchronization id + * @returns {object} a map (of size equal to the number of parties) + * where the key is the party id (from 1 to n) + * and the value is an array of secret shared bits + */ + jiffClient.protocols.bits.share = sharing.share_bits.bind(null, jiffClient); + /** + * Opens the given array of secret shared bits. + * This works regardless of whether the represented value fit inside the corresponding field or not + * @method + * @memberof bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number[]} parties - parties to open (same as jiff_instance.open) + * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open + * @returns {promise} a promise to the number represented by bits + */ + jiffClient.protocols.bits.open = sharing.open_bits.bind(null, jiffClient); + /** + * Receives an opening of an array of secret bits without owning shares of the underlying value. + * Similar to jiff.receive_open() but for bits. + * This works regardless of whether the represented value fit inside the corresponding field or not + * @method + * @memberOf jiff-instance.protocols.bits + * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares + * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result + * @param {number} [count=ceil(log2(Zp))] - the number of bits being opened + * @param {number} [threshold=parties.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string|number|object} [op_id=auto_gen()] - unique and consistent synchronization id between all parties + * @returns {promise} a (JQuery) promise to the open value of the secret + */ + jiffClient.protocols.bits.receive_open = sharing.receive_open_bits.bind(null, jiffClient); }; },{"../protocols/bits/arithmetic.js":22,"../protocols/bits/comparison.js":23,"../protocols/bits/protocols.js":24,"../protocols/bits/sharing.js":25}],3:[function(require,module,exports){ -module.exports = function (jiffClient) { - /** - * Requests secret(s) from the server (crypto provider) of type matching the given label. - * @method from_crypto_provider - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} label - the type of secret(s) being requested from crypto_provider (e.g. triplet, quotient, numbers, etc) - * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the secret(s), by default, this includes all parties. - * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret(s). - * @param {number} [Zp=jiff_instance.Zp] - the mod, defaults to the Zp of the instance. - * @param {string} [op_id=auto_Gen()] - an id which is used to identify the secret requested, so that every party - * gets a share from the same secret for every matching instruction. An automatic id - * is generated by increasing a local counter per label, default ids suffice when all - * parties execute all instructions in the same order. - * @param {object} [params={}] - any additional parameters specific to the label, these are defined by the label handler at the server side. - * some of these parameters may be optional, while others may be required. - * @returns {promise} a promise to the secret(s) provided by the server/crypto provider, the promise returns an object with the given format: - * { values: , shares: } - */ - jiffClient.from_crypto_provider = function (label, receivers_list, threshold, Zp, op_id, params) { - // defaults - if (Zp == null) { - Zp = jiffClient.Zp; - } - if (receivers_list == null) { - receivers_list = []; - for (var i = 1; i <= jiffClient.party_count; i++) { - receivers_list.push(i); - } - } else { - jiffClient.helpers.sort_ids(receivers_list); - } - if (threshold == null) { - threshold = receivers_list.length; - } - if (op_id == null) { - op_id = jiffClient.counters.gen_op_id('crypto_provider:' + label, receivers_list); - } - if (params == null) { - params = {}; - } - - // Send a request to the server - var msg = {label: label, op_id: op_id, receivers: receivers_list, threshold: threshold, Zp: Zp, params: params}; - msg = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'crypto_provider', msg], 2); - msg = JSON.stringify(msg); - - // Setup deferred to handle receiving the result later. - jiffClient.deferreds[op_id] = new jiffClient.helpers.Deferred(); - var result = jiffClient.deferreds[op_id].promise; - - // send a request to the server. - jiffClient.socket.safe_emit('crypto_provider', msg); - return result; - }; +module.exports = function (jiffClient) { + /** + * Requests secret(s) from the server (crypto provider) of type matching the given label. + * @method from_crypto_provider + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} label - the type of secret(s) being requested from crypto_provider (e.g. triplet, quotient, numbers, etc) + * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the secret(s), by default, this includes all parties. + * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret(s). + * @param {number} [Zp=jiff_instance.Zp] - the mod, defaults to the Zp of the instance. + * @param {string} [op_id=auto_Gen()] - an id which is used to identify the secret requested, so that every party + * gets a share from the same secret for every matching instruction. An automatic id + * is generated by increasing a local counter per label, default ids suffice when all + * parties execute all instructions in the same order. + * @param {object} [params={}] - any additional parameters specific to the label, these are defined by the label handler at the server side. + * some of these parameters may be optional, while others may be required. + * @returns {promise} a promise to the secret(s) provided by the server/crypto provider, the promise returns an object with the given format: + * { values: , shares: } + */ + jiffClient.from_crypto_provider = function (label, receivers_list, threshold, Zp, op_id, params) { + // defaults + if (Zp == null) { + Zp = jiffClient.Zp; + } + if (receivers_list == null) { + receivers_list = []; + for (var i = 1; i <= jiffClient.party_count; i++) { + receivers_list.push(i); + } + } else { + jiffClient.helpers.sort_ids(receivers_list); + } + if (threshold == null) { + threshold = receivers_list.length; + } + if (op_id == null) { + op_id = jiffClient.counters.gen_op_id('crypto_provider:' + label, receivers_list); + } + if (params == null) { + params = {}; + } + + // Send a request to the server + var msg = {label: label, op_id: op_id, receivers: receivers_list, threshold: threshold, Zp: Zp, params: params}; + msg = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'crypto_provider', msg], 2); + msg = JSON.stringify(msg); + + // Setup deferred to handle receiving the result later. + jiffClient.deferreds[op_id] = new jiffClient.helpers.Deferred(); + var result = jiffClient.deferreds[op_id].promise; + + // send a request to the server. + jiffClient.socket.safe_emit('crypto_provider', msg); + return result; + }; }; },{}],4:[function(require,module,exports){ -module.exports = function (jiffClient) { - /** - * Sends a custom message to a subset of parties - * @memberof module:jiff-client~JIFFClient - * @method emit - * @instance - * @param {string} tag - the tag to attach to the message - * @param {Array} [receivers=all_parties] - contains the party ids to receive the message, defaults to all parties - * @param {string} message - the message to send - * @param {boolean} [encrypt=true] - if true, messages will be encrypted - */ - jiffClient.emit = function (tag, receivers, message, encrypt) { - if (typeof(message) !== 'string') { - throw new Error('Emit: message must be a string'); - } - - if (receivers == null) { - receivers = []; - for (var i = 1; i <= jiffClient.party_count; i++) { - receivers.push(i); - } - } - - // send to all other parties - for (var p = 0; p < receivers.length; p++) { - if (receivers[p] === jiffClient.id) { - continue; - } - - var message_to_send = {tag: tag, party_id: receivers[p], message: message, encrypted: encrypt}; - message_to_send = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'custom', message_to_send], 2); - - if (message_to_send['encrypted'] !== false) { - message_to_send['message'] = jiffClient.hooks.encryptSign(jiffClient, message_to_send['message'], jiffClient.keymap[message_to_send['party_id']], jiffClient.secret_key); - message_to_send['encrypted'] = true; - } - - jiffClient.socket.safe_emit('custom', JSON.stringify(message_to_send)); - } - - // receive our own message if specified - if (receivers.indexOf(jiffClient.id) > -1) { - jiffClient.handlers.receive_custom({tag: tag, party_id: jiffClient.id, message: message, encrypted: false}); - } - }; - - /** - * Registers the given function as a listener for messages with the given tag. - * Removes any previously set listener for this tag. - * @memberof module:jiff-client~JIFFClient - * @method listen - * @instance - * @param {string} tag - the tag to listen for. - * @param {function(party_id, string)} handler - the function that handles the received message: takes the sender id and the message as parameters. - */ - jiffClient.listen = function (tag, handler) { - jiffClient.listeners[tag] = handler; - - var stored_messages = jiffClient.custom_messages_mailbox[tag]; - if (stored_messages == null) { - return; - } - - for (var i = 0; i < stored_messages.length; i++) { - var sender_id = stored_messages[i].sender_id; - var message = stored_messages[i].message; - handler(sender_id, message); - } - - delete jiffClient.custom_messages_mailbox[tag]; - }; - - /** - * Removes the custom message listener attached to the given tag - * @memberof module:jiff-client~JIFFClient - * @method remove_listener - * @instance - * @param {string} tag - the tag of the listener to remove - */ - jiffClient.remove_listener = function (tag) { - delete jiffClient.listeners[tag]; - }; +module.exports = function (jiffClient) { + /** + * Sends a custom message to a subset of parties + * @memberof module:jiff-client~JIFFClient + * @method emit + * @instance + * @param {string} tag - the tag to attach to the message + * @param {Array} [receivers=all_parties] - contains the party ids to receive the message, defaults to all parties + * @param {string} message - the message to send + * @param {boolean} [encrypt=true] - if true, messages will be encrypted + */ + jiffClient.emit = function (tag, receivers, message, encrypt) { + if (typeof(message) !== 'string') { + throw new Error('Emit: message must be a string'); + } + + if (receivers == null) { + receivers = []; + for (var i = 1; i <= jiffClient.party_count; i++) { + receivers.push(i); + } + } + + // send to all other parties + for (var p = 0; p < receivers.length; p++) { + if (receivers[p] === jiffClient.id) { + continue; + } + + var message_to_send = {tag: tag, party_id: receivers[p], message: message, encrypted: encrypt}; + message_to_send = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'custom', message_to_send], 2); + + if (message_to_send['encrypted'] !== false) { + message_to_send['message'] = jiffClient.hooks.encryptSign(jiffClient, message_to_send['message'], jiffClient.keymap[message_to_send['party_id']], jiffClient.secret_key); + message_to_send['encrypted'] = true; + } + + jiffClient.socket.safe_emit('custom', JSON.stringify(message_to_send)); + } + + // receive our own message if specified + if (receivers.indexOf(jiffClient.id) > -1) { + jiffClient.handlers.receive_custom({tag: tag, party_id: jiffClient.id, message: message, encrypted: false}); + } + }; + + /** + * Registers the given function as a listener for messages with the given tag. + * Removes any previously set listener for this tag. + * @memberof module:jiff-client~JIFFClient + * @method listen + * @instance + * @param {string} tag - the tag to listen for. + * @param {function(party_id, string)} handler - the function that handles the received message: takes the sender id and the message as parameters. + */ + jiffClient.listen = function (tag, handler) { + jiffClient.listeners[tag] = handler; + + var stored_messages = jiffClient.custom_messages_mailbox[tag]; + if (stored_messages == null) { + return; + } + + for (var i = 0; i < stored_messages.length; i++) { + var sender_id = stored_messages[i].sender_id; + var message = stored_messages[i].message; + handler(sender_id, message); + } + + delete jiffClient.custom_messages_mailbox[tag]; + }; + + /** + * Removes the custom message listener attached to the given tag + * @memberof module:jiff-client~JIFFClient + * @method remove_listener + * @instance + * @param {string} tag - the tag of the listener to remove + */ + jiffClient.remove_listener = function (tag) { + delete jiffClient.listeners[tag]; + }; }; },{}],5:[function(require,module,exports){ -module.exports = function (jiffClient) { - /** - * Wait until the public keys of these parties are known. - * The public keys may be known before the parties connect (if provided in the options), - * or they could be sent by the server after the parties connect. - * Computation specified in the callback may assume that these parties are connected, - * if they are not, the server will handle storing and relaying the needed messages - * to them when they connect. - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {Array} parties - an array of party ids to wait for, must explicitly include 's1' if callback must wait for the server. - * @param {function(jiff-instance)} callback - the function to execute when these parties are known. - * @param {boolean} [wait_for_initialization=true] - specifies whether to wait for initialization to be complete - * before executing the callback (even if parties are available). - * Set this to false if you do not need the party count and this - * party's id, or if you already have them, and you are certain - * they will be accepted by the server on initialization. - */ - jiffClient.wait_for = function (parties, callback, wait_for_initialization) { - if (wait_for_initialization == null) { - wait_for_initialization = true; - } - - jiffClient.wait_callbacks.push({parties: parties, callback: callback, initialization: wait_for_initialization}); - jiffClient.execute_wait_callbacks(); // See if the callback can be executed immediately - }; - - /** - * Disconnects from the computation. - * Allows the client program to exit. - * @method disconnect - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {boolean} [safe=false] - if true, jiff will disconnect safely (i.e. after ensuring all - * outgoing pending messages were delivered). - * @param {boolean} [free=false] - if set to true, it means this party's disconnection is final, and all resources - * associated with this party must be freed. - * If all parties in a computation are freed, then all resources associated with the - * computation are freed, and any subsequent reconnection to the computation is as - * if a the connection is for a fresh new computation. - * @param {function()} [callback] - executed after the instance safely disconnects, if safe is set to false, this - * parameter is ignored. - */ - jiffClient.disconnect = function (safe, free, callback) { - if (safe) { - jiffClient.socket.safe_disconnect(free, callback); - } else { - if (free) { - jiffClient.free(); - } - jiffClient.socket.disconnect(); - } - }; - - /** - * Emits event to free up all the resources allocated for this party on the server. - * It is best not to call this function directly, as it can break things if resources still need to be used. - * Instead, use jiff.disconnect(safe, free, callback) to free after safely disconnecting. - * @see {@link module:jiff-client~JIFFClient#disconnect} - * @method free - * @memberof module:jiff-client~JIFFClient - * @instance - */ - jiffClient.free = function () { - var msg = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'free', {}], 2); - jiffClient.socket.safe_emit('free', JSON.stringify(msg)); - }; +module.exports = function (jiffClient) { + /** + * Wait until the public keys of these parties are known. + * The public keys may be known before the parties connect (if provided in the options), + * or they could be sent by the server after the parties connect. + * Computation specified in the callback may assume that these parties are connected, + * if they are not, the server will handle storing and relaying the needed messages + * to them when they connect. + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {Array} parties - an array of party ids to wait for, must explicitly include 's1' if callback must wait for the server. + * @param {function(jiff-instance)} callback - the function to execute when these parties are known. + * @param {boolean} [wait_for_initialization=true] - specifies whether to wait for initialization to be complete + * before executing the callback (even if parties are available). + * Set this to false if you do not need the party count and this + * party's id, or if you already have them, and you are certain + * they will be accepted by the server on initialization. + */ + jiffClient.wait_for = function (parties, callback, wait_for_initialization) { + if (wait_for_initialization == null) { + wait_for_initialization = true; + } + + jiffClient.wait_callbacks.push({parties: parties, callback: callback, initialization: wait_for_initialization}); + jiffClient.execute_wait_callbacks(); // See if the callback can be executed immediately + }; + + /** + * Disconnects from the computation. + * Allows the client program to exit. + * @method disconnect + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {boolean} [safe=false] - if true, jiff will disconnect safely (i.e. after ensuring all + * outgoing pending messages were delivered). + * @param {boolean} [free=false] - if set to true, it means this party's disconnection is final, and all resources + * associated with this party must be freed. + * If all parties in a computation are freed, then all resources associated with the + * computation are freed, and any subsequent reconnection to the computation is as + * if a the connection is for a fresh new computation. + * @param {function()} [callback] - executed after the instance safely disconnects, if safe is set to false, this + * parameter is ignored. + */ + jiffClient.disconnect = function (safe, free, callback) { + if (safe) { + jiffClient.socket.safe_disconnect(free, callback); + } else { + if (free) { + jiffClient.free(); + } + jiffClient.socket.disconnect(); + } + }; + + /** + * Emits event to free up all the resources allocated for this party on the server. + * It is best not to call this function directly, as it can break things if resources still need to be used. + * Instead, use jiff.disconnect(safe, free, callback) to free after safely disconnecting. + * @see {@link module:jiff-client~JIFFClient#disconnect} + * @method free + * @memberof module:jiff-client~JIFFClient + * @instance + */ + jiffClient.free = function () { + var msg = jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'free', {}], 2); + jiffClient.socket.safe_emit('free', JSON.stringify(msg)); + }; }; },{}],6:[function(require,module,exports){ -var numbers = require('../protocols/preprocessing/numbers.js'); -var bits = require('../protocols/preprocessing/bits.js'); -var triplets = require('../protocols/preprocessing/triplets.js'); -var quotients = require('../protocols/preprocessing/quotients.js'); -var sampling = require('../protocols/preprocessing/sampling.js'); - -/** - * Contains miscellaneous protocols (mostly used in preprocessing) - * @name protocols - * @alias protocols - * @namespace - */ -module.exports = function (jiffClient) { - /** - * Creates shares of an unknown random number. Every party comes up with its own random number and shares it. - * Then every party combines all the received shares to construct one share of the random unknown number. - * @method - * @memberof protocols - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. - * @param {Array} receivers_list - array of party ids to receive the result. - * @param {Array} compute_list - array of party ids to perform the protocol. - * @param {number} Zp - the mod. - * @param {object} params - an object containing extra parameters passed by the user. - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the result) and 'promise'. - */ - jiffClient.protocols.generate_random_number = numbers.generate_random_number.bind(null, jiffClient); - - /** - * Creates shares of 0, such that no party knows the other parties' shares. - * Every party secret shares 0, then every party sums all the shares they received, resulting - * in a new share of 0 for every party. - * @method - * @memberof protocols - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. - * @param {Array} receivers_list - array of party ids to receive the result. - * @param {Array} compute_list - array of party ids to perform the protocol. - * @param {number} Zp - the mod. - * @param {object} params - an object containing extra parameters passed by the user. - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the result) and 'promise'. - */ - jiffClient.protocols.generate_zero = numbers.generate_zero.bind(null, jiffClient); - - /** - * Generates a random bit under MPC by xoring all bits sent by participating parties using smult / beaver triples - * @method - * @memberof protocols - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. - * @param {Array} receivers_list - array of party ids to receive the result. - * @param {Array} compute_list - array of party ids to perform the protocol. - * @param {number} Zp - the mod. - * @param {object} params - an object containing extra parameters passed by the user. - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise'. - */ - jiffClient.protocols.generate_random_bit_smult = bits.generate_random_bit_smult.bind(null, jiffClient); - - /** - * Generates a random bit under MPC by xoring all bits sent by participating parties using smult_bgw - * @method - * @memberof protocols - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. - * @param {Array} receivers_list - array of party ids to receive the result. - * @param {Array} compute_list - array of party ids to perform the protocol. - * @param {number} Zp - the mod. - * @param {object} params - an object containing extra parameters passed by the user. - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise'. - */ - jiffClient.protocols.generate_random_bit_bgw = bits.generate_random_bit_bgw.bind(null, jiffClient); - - /** - * Generates a sequence of random bits under MPC. - * @method - * @memberof protocols - * @param {number} [threshold=receivers_list.length] - the threshold of the bit when stored by receivers after generation. * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. - * @param {Array} receivers_list - array of party ids to receive the result. - * @param {Array} compute_list - array of party ids to perform the protocol. - * @param {number} Zp - the mod. - * @param {object} params - an object containing extra parameters passed by the user. - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. - * - count: how many random bits to generate. - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @param {object} protocols - the protocols to use for preprocessing. - * @return {Object} contains 'share' (array of secret shares bits) and 'promise'. - */ - jiffClient.protocols.generate_random_bits = bits.generate_random_bits.bind(null, jiffClient); - - /** - * Generation of beaver triplet via MPC, uses the server for communication channels, but not for generation - * @method - * @memberof protocols - * @param {number} threshold - the threshold of the triplets when stored by receivers after generation - * @param {Array} receivers_list - array of party ids that want to receive the triplet shares - * @param {Array} compute_list - array of party ids that will perform this protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - an optional number compute_threshold parameter, which specifies threshold used - * during the protocol execution. By default, this is the length of the (compute_list+1)/2 - * @param {object} protocols - the sub protocols to use for preprocessing - * @return {object} all pre-processing protocols must return an object with these keys: - * { - * 'share': the share(s)/value(s) to store attached to op_id for later use by the computation (i.e. the result of preprocessing), - * 'promise': a promise for when this protocol is fully completed (could be null if the protocol was already completed) - * } - * In this case, 'share' is an array of this party's shares of the resulting triplet, a,b,c such that a*b=c - */ - jiffClient.protocols.generate_beaver_bgw = triplets.bind(null, jiffClient); - - /** - * Creates shares of r and x, such that r is a uniform random number between 0 and Zp, and x is floor(r/constant) - * where constant is provided by the extra params - * @method - * @memberof protocols - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * - constant: the constant to divide the random number by. - * - output_op_id: the set op id of the output quotient and noise - * @return {Object} contains 'share' (this party's share of the result) and 'promise' - */ - jiffClient.protocols.generate_random_and_quotient = quotients.bind(null, jiffClient); - - /** - * Wrapper for when doing rejection sampling during pre processing - * - * Do not use this function directly, especially during online computation time, use jiffClient.protocols.bits.rejection_sampling instead - * - * @method - * @memberof protocols - * @param {number} [threshold=receivers_list.length] - the threshold of the resulting shares after sampling - * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the sampling shares, by default, this includes all parties - * @param {Array} [compute_list=all_parties] - array of party ids that will perform this protocol, by default, this includes all parties - * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly - * @param {object} [params={}] - an object containing extra parameters passed by the user - * Expects: - * - an optional number compute_threshold parameter, which specifies threshold used - * during the protocol execution. By default, this is (|compute_list|+1)/2 - * - optional 'lower_bound' and 'upper_bound' numeric parameters, default to 0 and Zp respectively - * - op_id, the base op_id to tag operations inside this protocol with, defaults to auto generated - * - output_op_id, the tag id for the output result - * - retry_count, how many times rejection sampling have been retried! - * @param {object} [protocols=defaults] - the protocols to use for preprocessing, any protocol(s) not provided will be replaced with defaults - * @returns {Object} an object containing keys: 'share', and 'promise'. The promise is resolved when the rejection sampling is completed. - * The object is consumed by .preprocessing: - * - 'share' attribute contains the resulting array of secret shared bits representing the sampled value, and is stored in the preprocessing table internally - * - The promise is consumed and a new promise is returned by .preprocessing that is resolved after this returned promise (and all other promise generated by that .preprocessing call) are resolved - */ - jiffClient.protocols.rejection_sampling = sampling.bind(null, jiffClient); -}; -},{"../protocols/preprocessing/bits.js":31,"../protocols/preprocessing/numbers.js":32,"../protocols/preprocessing/quotients.js":33,"../protocols/preprocessing/sampling.js":34,"../protocols/preprocessing/triplets.js":35}],7:[function(require,module,exports){ -var shareProtocol = require('../protocols/shamir/share.js'); -var openProtocol = require('../protocols/shamir/open.js'); -var reshareProtocol = require('../protocols/shamir/reshare.js'); -var arraysSharing = require('../protocols/arrays/sharing.js'); - -module.exports = function (jiffClient) { - /** - * Share a secret input - * - * Can be overriden by extensions to customize behavior - * - * @method share - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {number} secret - the number to share (this party's input) - * @param {number} [threshold=receivers_list.length] - the minimum number of parties needed to reconstruct the secret, defaults to all the receivers - * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties - * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties - * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string|number} [share_id=auto_gen()] - the tag used to tag the messages sent by this share operation, this tag is used - * so that parties distinguish messages belonging to this share operation from other - * share operations between the same parties (when the order of execution is not - * deterministic). An automatic id is generated by increasing a local counter, default - * ids suffice when all parties execute all sharing operations with the same senders - * and receivers in the same order - * @returns {object} a map (of size equal to the number of sending parties) - * where the key is the party id (between 1 and n), or 's1' if 's1' is specified in the senders_list, - * and the value is the share object that wraps the value received from that party (the internal value maybe - * deferred). - * - * @example - * // share an input value with all parties, and receive all other parties' inputs - * var shares = jiffClient.share(input); - * // my party id is '1', so the first share is mine (technically my share of my input value) - * var my_share = shares[1]; - * // my share of party 2's input - * var p2_share = shares[2]; - */ - jiffClient.share = function (secret, threshold, receivers_list, senders_list, Zp, share_id) { - // type check to confirm the secret to be shared is a number - // for fixed-point extension it should allow non-ints - if (secret != null && (typeof(secret) !== 'number' || Math.floor(secret) !== secret || secret < 0)) { - throw new Error('secret must be a non-negative whole number'); - } - if (secret != null && (secret >= (Zp == null ? jiffClient.Zp : Zp))) { - throw new Error('secret must fit inside Zp'); - } - return jiffClient.internal_share(secret, threshold, receivers_list, senders_list, Zp, share_id); - }; - - /** - * Same as share, but used by internal JIFF primitives/protocols, do not override this! - * @see {@link module:jiff-client~JIFFClient#share} - * @method internal_share - * @instance - * @memberof module:jiff-client~JIFFClient - */ - jiffClient.internal_share = shareProtocol.jiff_share.bind(null, jiffClient); - - /** - * re-share an existing share (value) under a new threshold or to a new set of parties or both. - * Do not use this to refresh a share (use {@link module:jiff-client~JIFFClient#SecretShare#refresh} instead) - * @method reshare - * @instance - * @memberof module:jiff-client~JIFFClient - * @param {module:jiff-client~JIFFClient#SecretShare} [share=null] - the share you would like to reshare (null if you are a receiver but not a sender) - * @param {number} [threshold=receivers_list.length] - the new threshold, defaults to the length of receivers_list param - * @param {Array} [receivers_list=all_parties] - array of party ids to receive from, by default, this includes all parties - * @param {Array} [senders_list=all_parties] - array of party ids that posses the share and will reshare it with the receivers, by default, this includes all parties - * @param {number} [Zp=jiff.Zp] - the Zp of the existing share - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). - * This id must be unique, and must be passed by all parties to the same instruction. - * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id - * is generated by increasing a local counter, default ids suffice when all parties execute the - * instructions in the same order - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result under the new threshold, or null if this party is not a receiver - */ - jiffClient.reshare = reshareProtocol.bind(null, jiffClient); - - /** - * Open a secret share to reconstruct secret. - * @method open - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {module:jiff-client~JIFFClient#SecretShare} share - this party's share of the secret to reconstruct. - * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties. - * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages. - * @returns {?promise} a (JQuery) promise to the open value of the secret, null if the party is not specified in the parties array as a receiver. - * @example - * var shares = jiff_instance.share(input); - * //multiply the inputs of party 1 and 2 together - * var result = shares[1].mult(shares[2]); - * // reveal the result of the multiplication to all parties - * return jiff_instance.open(result); - */ - jiffClient.open = openProtocol.jiff_open.bind(null, jiffClient); - - /** - * Same as open, but used by internal JIFF primitives/protocols, do not override this! - * @see {@link module:jiff-client~JIFFClient#open} - * @method internal_open - * @instance - * @memberof module:jiff-client~JIFFClient - */ - jiffClient.internal_open = jiffClient.open; - - /** - * Receive shares from the specified parties and reconstruct their secret. - * Use this function in a party that will receive some answer/value but does not have a share of it. - * @method receive_open - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares, this must be provided! - * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result - * @param {number} [threshold=senders.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders - * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string|number} [op_id=auto_Gen()] - same as jiff-instance.open - * @returns {!promise} a (JQuery) promise to the open value of the secret. - */ - jiffClient.receive_open = function (senders, receivers, threshold, Zp, op_id) { - if (senders == null) { - throw new Error('Must provide "senders" parameter in receive_open'); - } - - jiffClient.helpers.sort_ids(senders); - if (receivers == null) { - receivers = []; - for (var i = 1; i <= jiffClient.party_count; i++) { - receivers.push(i); - } - } else { - jiffClient.helpers.sort_ids(receivers); - } - if (Zp == null) { - Zp = jiffClient.Zp; - } - if (threshold == null) { - threshold = senders.length; - } - - var imitationSecretShare = new jiffClient.SecretShare({}, senders, threshold, Zp); - return jiffClient.open(imitationSecretShare, receivers, op_id); - }; - - /** - * Share an array of values. Each sender may have an array of different length. This is handled by the lengths parameter. - * This function will reveal the lengths of the shared array. - * - * If parties would like to keep the lengths of their arrays secret, they should agree on some public "max" length apriori (either under MPC - * or as part of the logistics of the computation), all their arrays should be padded to that length by using appropriate default/identity - * values - * @method share_array - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {Array} array - the array to be shared. - * @param {null|number|object} [lengths] - the lengths of the arrays to be shared, has the following options:
- * 1. null: lengths are unknown, each sender will publicly reveal the lengths of its own array.
- * 2. number: all arrays are of this length
- * 3. object: { : length }: must specify the length of the array for each sender.
- * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. - * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. - * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. - * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used). - * @param {string|number} [share_id=auto_gen()] - the base tag used to tag the messages sent by this share operation, every element of the array - * will get a unique id based on the concatenation of base_share_id and the index of the element. - * This tag is used so that parties distinguish messages belonging to this share operation from - * other share operations between the same parties (when the order of execution is not - * deterministic). An automatic id is generated by increasing a local counter, default - * ids suffice when all parties execute all sharing operations with the same senders - * and receivers in the same order. - * @returns {?promise} if the calling party is a receiver then a promise to the shared arrays is returned, the promise will provide an object - * formatted as follows: { : [ <1st_share>, <2nd_share>, ..., <(lengths[party_id])th_share> ] } - * where the party_ids are those of the senders. - * if the calling party is not a receiver, then null is returned. - */ - jiffClient.share_array = arraysSharing.jiff_share_array.bind(null, jiffClient); - - /** - * Opens an array of secret shares. - * @method open_array - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} shares - an array containing this party's shares of the secrets to reconstruct - * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties - * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open - * @returns {?promise} a (JQuery) promise to ALL the open values of the secret, the promise will yield - * an array of values matching the corresponding given secret share by index. If the calling party - * is not specified in parties, then null is returned - */ - jiffClient.open_array = arraysSharing.jiff_open_array.bind(null, jiffClient); -}; -},{"../protocols/arrays/sharing.js":21,"../protocols/shamir/open.js":36,"../protocols/shamir/reshare.js":37,"../protocols/shamir/share.js":38}],8:[function(require,module,exports){ -module.exports = function (jiffClient) { - var maxBarrierId = 10000000; - var currentBarrierId = 0; - var openBarriers = 0; - - /** - * Starts a new barrier, all promises and secret shares created between this call and the corresponding start_barrier - * call will be part of this barrier. start_barrier may be called before previous barriers are resolved, in which - * case promises / secret shares created will be part of the new barrier as well as any previous barriers. - * @memberof module:jiff-client~JIFFClient - * @method start_barrier - * @instance - * @returns {number} a barrier id that identifies this barrier. - */ - jiffClient.start_barrier = function () { - openBarriers++; - currentBarrierId = (currentBarrierId + 1 % maxBarrierId); - jiffClient.barriers[currentBarrierId] = []; - return currentBarrierId; - }; - - /** - * Adds given promise to all active barriers. - * @memberof module:jiff-client~JIFFClient - * @method add_to_barriers - * @instance - * @param {promise} promise - the promise to add. - */ - jiffClient.add_to_barriers = function (promise) { - if (openBarriers > 0) { - for (var id in jiffClient.barriers) { - if (jiffClient.barriers.hasOwnProperty(id)) { - jiffClient.barriers[id].push(promise); - } - } - } - }; - - /** - * Executes the callback only after all promises / secret shares in the barrier were resolved. - * @memberof module:jiff-client~JIFFClient - * @method end_barrier - * @instance - * @param {number} [barrier_id=jiff.barriers.length - 1] - identifies the barrier, should be returned by start_barrier. - * by default, barrier_id will refer to the last barrier. - * @returns {promise} a promise that resolves after the secret shares are resolved. - */ - jiffClient.end_barrier = function (barrier_id) { - if (openBarriers === 0) { - return; - } - - openBarriers--; - if (barrier_id == null) { - barrier_id = currentBarrierId; - } +var numbers = require('../protocols/preprocessing/numbers.js'); +var bits = require('../protocols/preprocessing/bits.js'); +var triplets = require('../protocols/preprocessing/triplets.js'); +var quotients = require('../protocols/preprocessing/quotients.js'); +var sampling = require('../protocols/preprocessing/sampling.js'); + +/** + * Contains miscellaneous protocols (mostly used in preprocessing) + * @name protocols + * @alias protocols + * @namespace + */ +module.exports = function (jiffClient) { + /** + * Creates shares of an unknown random number. Every party comes up with its own random number and shares it. + * Then every party combines all the received shares to construct one share of the random unknown number. + * @method + * @memberof protocols + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. + * @param {Array} receivers_list - array of party ids to receive the result. + * @param {Array} compute_list - array of party ids to perform the protocol. + * @param {number} Zp - the mod. + * @param {object} params - an object containing extra parameters passed by the user. + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the result) and 'promise'. + */ + jiffClient.protocols.generate_random_number = numbers.generate_random_number.bind(null, jiffClient); + + /** + * Creates shares of 0, such that no party knows the other parties' shares. + * Every party secret shares 0, then every party sums all the shares they received, resulting + * in a new share of 0 for every party. + * @method + * @memberof protocols + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. + * @param {Array} receivers_list - array of party ids to receive the result. + * @param {Array} compute_list - array of party ids to perform the protocol. + * @param {number} Zp - the mod. + * @param {object} params - an object containing extra parameters passed by the user. + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the result) and 'promise'. + */ + jiffClient.protocols.generate_zero = numbers.generate_zero.bind(null, jiffClient); + + /** + * Generates a random bit under MPC by xoring all bits sent by participating parties using smult / beaver triples + * @method + * @memberof protocols + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. + * @param {Array} receivers_list - array of party ids to receive the result. + * @param {Array} compute_list - array of party ids to perform the protocol. + * @param {number} Zp - the mod. + * @param {object} params - an object containing extra parameters passed by the user. + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise'. + */ + jiffClient.protocols.generate_random_bit_smult = bits.generate_random_bit_smult.bind(null, jiffClient); + + /** + * Generates a random bit under MPC by xoring all bits sent by participating parties using smult_bgw + * @method + * @memberof protocols + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. + * @param {Array} receivers_list - array of party ids to receive the result. + * @param {Array} compute_list - array of party ids to perform the protocol. + * @param {number} Zp - the mod. + * @param {object} params - an object containing extra parameters passed by the user. + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise'. + */ + jiffClient.protocols.generate_random_bit_bgw = bits.generate_random_bit_bgw.bind(null, jiffClient); + + /** + * Generates a sequence of random bits under MPC. + * @method + * @memberof protocols + * @param {number} [threshold=receivers_list.length] - the threshold of the bit when stored by receivers after generation. * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed. + * @param {Array} receivers_list - array of party ids to receive the result. + * @param {Array} compute_list - array of party ids to perform the protocol. + * @param {number} Zp - the mod. + * @param {object} params - an object containing extra parameters passed by the user. + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated. + * - count: how many random bits to generate. + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @param {object} protocols - the protocols to use for preprocessing. + * @return {Object} contains 'share' (array of secret shares bits) and 'promise'. + */ + jiffClient.protocols.generate_random_bits = bits.generate_random_bits.bind(null, jiffClient); + + /** + * Generation of beaver triplet via MPC, uses the server for communication channels, but not for generation + * @method + * @memberof protocols + * @param {number} threshold - the threshold of the triplets when stored by receivers after generation + * @param {Array} receivers_list - array of party ids that want to receive the triplet shares + * @param {Array} compute_list - array of party ids that will perform this protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - an optional number compute_threshold parameter, which specifies threshold used + * during the protocol execution. By default, this is the length of the (compute_list+1)/2 + * @param {object} protocols - the sub protocols to use for preprocessing + * @return {object} all pre-processing protocols must return an object with these keys: + * { + * 'share': the share(s)/value(s) to store attached to op_id for later use by the computation (i.e. the result of preprocessing), + * 'promise': a promise for when this protocol is fully completed (could be null if the protocol was already completed) + * } + * In this case, 'share' is an array of this party's shares of the resulting triplet, a,b,c such that a*b=c + */ + jiffClient.protocols.generate_beaver_bgw = triplets.bind(null, jiffClient); + + /** + * Creates shares of r and x, such that r is a uniform random number between 0 and Zp, and x is floor(r/constant) + * where constant is provided by the extra params + * @method + * @memberof protocols + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * - constant: the constant to divide the random number by. + * - output_op_id: the set op id of the output quotient and noise + * @return {Object} contains 'share' (this party's share of the result) and 'promise' + */ + jiffClient.protocols.generate_random_and_quotient = quotients.bind(null, jiffClient); + + /** + * Wrapper for when doing rejection sampling during pre processing + * + * Do not use this function directly, especially during online computation time, use jiffClient.protocols.bits.rejection_sampling instead + * + * @method + * @memberof protocols + * @param {number} [threshold=receivers_list.length] - the threshold of the resulting shares after sampling + * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the sampling shares, by default, this includes all parties + * @param {Array} [compute_list=all_parties] - array of party ids that will perform this protocol, by default, this includes all parties + * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly + * @param {object} [params={}] - an object containing extra parameters passed by the user + * Expects: + * - an optional number compute_threshold parameter, which specifies threshold used + * during the protocol execution. By default, this is (|compute_list|+1)/2 + * - optional 'lower_bound' and 'upper_bound' numeric parameters, default to 0 and Zp respectively + * - op_id, the base op_id to tag operations inside this protocol with, defaults to auto generated + * - output_op_id, the tag id for the output result + * - retry_count, how many times rejection sampling have been retried! + * @param {object} [protocols=defaults] - the protocols to use for preprocessing, any protocol(s) not provided will be replaced with defaults + * @returns {Object} an object containing keys: 'share', and 'promise'. The promise is resolved when the rejection sampling is completed. + * The object is consumed by .preprocessing: + * - 'share' attribute contains the resulting array of secret shared bits representing the sampled value, and is stored in the preprocessing table internally + * - The promise is consumed and a new promise is returned by .preprocessing that is resolved after this returned promise (and all other promise generated by that .preprocessing call) are resolved + */ + jiffClient.protocols.rejection_sampling = sampling.bind(null, jiffClient); +}; +},{"../protocols/preprocessing/bits.js":35,"../protocols/preprocessing/numbers.js":36,"../protocols/preprocessing/quotients.js":37,"../protocols/preprocessing/sampling.js":38,"../protocols/preprocessing/triplets.js":39}],7:[function(require,module,exports){ +var shareProtocol = require('../protocols/shamir/share.js'); +var openProtocol = require('../protocols/shamir/open.js'); +var reshareProtocol = require('../protocols/shamir/reshare.js'); +var arraysSharing = require('../protocols/arrays/sharing.js'); +var gmwShareProtocol=require('../protocols/gmw_bit/gmw_share.js'); +var gmwOpenProtocol = require('../protocols/gmw_bit/gmw_open.js'); + +module.exports = function (jiffClient) { + /** + * Share a secret input + * + * Can be overriden by extensions to customize behavior + * + * @method share + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {number} secret - the number to share (this party's input) + * @param {number} [threshold=receivers_list.length] - the minimum number of parties needed to reconstruct the secret, defaults to all the receivers + * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties + * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string|number} [share_id=auto_gen()] - the tag used to tag the messages sent by this share operation, this tag is used + * so that parties distinguish messages belonging to this share operation from other + * share operations between the same parties (when the order of execution is not + * deterministic). An automatic id is generated by increasing a local counter, default + * ids suffice when all parties execute all sharing operations with the same senders + * and receivers in the same order + * @returns {object} a map (of size equal to the number of sending parties) + * where the key is the party id (between 1 and n), or 's1' if 's1' is specified in the senders_list, + * and the value is the share object that wraps the value received from that party (the internal value maybe + * deferred). + * + * @example + * // share an input value with all parties, and receive all other parties' inputs + * var shares = jiffClient.share(input); + * // my party id is '1', so the first share is mine (technically my share of my input value) + * var my_share = shares[1]; + * // my share of party 2's input + * var p2_share = shares[2]; + */ + jiffClient.share = function (secret, threshold, receivers_list, senders_list, Zp, share_id) { + // type check to confirm the secret to be shared is a number + // for fixed-point extension it should allow non-ints + if (secret != null && (typeof(secret) !== 'number' || Math.floor(secret) !== secret || secret < 0)) { + throw new Error('secret must be a non-negative whole number'); + } + if (secret != null && (secret >= (Zp == null ? jiffClient.Zp : Zp))) { + throw new Error('secret must fit inside Zp'); + } + return jiffClient.internal_share(secret, threshold, receivers_list, senders_list, Zp, share_id); + }; + + /** + * Same as share, but used by internal JIFF primitives/protocols, do not override this! + * @see {@link module:jiff-client~JIFFClient#share} + * @method internal_share + * @instance + * @memberof module:jiff-client~JIFFClient + */ + jiffClient.internal_share = shareProtocol.jiff_share.bind(null, jiffClient); + + + /** + * Share a secret bit input + * + * Can be overriden by extensions to customize behavior + * + * @method gmw_share + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {number} secret - the number to share (this party's input) + * @param {number} [threshold=receivers_list.length] - the minimum number of parties needed to reconstruct the secret, defaults to all the receivers + * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties + * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string|number} [share_id=auto_gen()] - the tag used to tag the messages sent by this share operation, this tag is used + * so that parties distinguish messages belonging to this share operation from other + * share operations between the same parties (when the order of execution is not + * deterministic). An automatic id is generated by increasing a local counter, default + * ids suffice when all parties execute all sharing operations with the same senders + * and receivers in the same order + * @returns {object} a map (of size equal to the number of sending parties) + * where the key is the party id (between 1 and n), or 's1' if 's1' is specified in the senders_list, + * and the value is the share object that wraps the value received from that party (the internal value maybe + * deferred). + * + * @example + * // share an input value with all parties, and receive all other parties' inputs + * var shares = jiffClient.gmw_share(input); + * // my party id is '1', so the first share is mine (technically my share of my input value) + * var my_share = shares[1]; + * // my share of party 2's input + * var p2_share = shares[2]; + */ + + jiffClient.gmw_share = function (secret, threshold, receivers_list, senders_list, Zp, share_id) { + // type check to confirm the secret to be shared is bit input + if (secret != null && (typeof(secret) !== 'number' || Math.floor(secret) !== secret || secret < 0||secret>1)) { + throw new Error('secret must be bit 0 or 1'); + } + if (secret != null && (secret >= (Zp == null ? jiffClient.Zp : Zp))) { + throw new Error('secret must fit inside Zp'); + } + return jiffClient.gmw_internal_share(secret, threshold, receivers_list, senders_list, Zp, share_id); + }; + + /** + * Same as share, but used by internal JIFF primitives/protocols, do not override this! + * @see {@link module:jiff-client~JIFFClient#share} + * @method gmw_internal_share + * @instance + * @memberof module:jiff-client~JIFFClient + */ + jiffClient.gmw_internal_share = gmwShareProtocol.gmw_share.bind(null, jiffClient); + + /** + * re-share an existing share (value) under a new threshold or to a new set of parties or both. + * Do not use this to refresh a share (use {@link module:jiff-client~JIFFClient#SecretShare#refresh} instead) + * @method reshare + * @instance + * @memberof module:jiff-client~JIFFClient + * @param {module:jiff-client~JIFFClient#SecretShare} [share=null] - the share you would like to reshare (null if you are a receiver but not a sender) + * @param {number} [threshold=receivers_list.length] - the new threshold, defaults to the length of receivers_list param + * @param {Array} [receivers_list=all_parties] - array of party ids to receive from, by default, this includes all parties + * @param {Array} [senders_list=all_parties] - array of party ids that posses the share and will reshare it with the receivers, by default, this includes all parties + * @param {number} [Zp=jiff.Zp] - the Zp of the existing share + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). + * This id must be unique, and must be passed by all parties to the same instruction. + * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id + * is generated by increasing a local counter, default ids suffice when all parties execute the + * instructions in the same order + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result under the new threshold, or null if this party is not a receiver + */ + jiffClient.reshare = reshareProtocol.bind(null, jiffClient); + + /** + * Open a secret share to reconstruct secret. + * @method open + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {module:jiff-client~JIFFClient#SecretShare} share - this party's share of the secret to reconstruct. + * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties. + * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages. + * @returns {?promise} a (JQuery) promise to the open value of the secret, null if the party is not specified in the parties array as a receiver. + * @example + * var shares = jiff_instance.share(input); + * //multiply the inputs of party 1 and 2 together + * var result = shares[1].mult(shares[2]); + * // reveal the result of the multiplication to all parties + * return jiff_instance.open(result); + */ + jiffClient.open = openProtocol.jiff_open.bind(null, jiffClient); + + /** + * Open a secret share to reconstruct bit secret. + * only used to open shares generated by gmw_share function or associated funcs (i.e. gmw_and, gmw_xor) + * @method gmw_open + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {module:jiff-client~JIFFClient#SecretShare} share - this party's share of the secret to reconstruct. + * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties. + * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages. + * @returns {?promise} a (JQuery) promise to the open value of the secret, null if the party is not specified in the parties array as a receiver. + * @example + * var shares = jiff_instance.gmw_share(input); + * //xor the inputs of party 1 and 2 together + * var result = shares[1].gmw_xor(shares[2]); + * // reveal the result of the multiplication to all parties + * return jiff_instance.gmw_open(result); + */ + + jiffClient.gmw_open = gmwOpenProtocol.gmw_open.bind(null, jiffClient); + /** + * Same as open, but used by internal JIFF primitives/protocols, do not override this! + * @see {@link module:jiff-client~JIFFClient#open} + * @method internal_open + * @instance + * @memberof module:jiff-client~JIFFClient + */ + jiffClient.internal_open = jiffClient.open; + + /** + * Receive shares from the specified parties and reconstruct their secret. + * Use this function in a party that will receive some answer/value but does not have a share of it. + * @method receive_open + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares, this must be provided! + * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result + * @param {number} [threshold=senders.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string|number} [op_id=auto_Gen()] - same as jiff-instance.open + * @returns {!promise} a (JQuery) promise to the open value of the secret. + */ + jiffClient.receive_open = function (senders, receivers, threshold, Zp, op_id) { + if (senders == null) { + throw new Error('Must provide "senders" parameter in receive_open'); + } + + jiffClient.helpers.sort_ids(senders); + if (receivers == null) { + receivers = []; + for (var i = 1; i <= jiffClient.party_count; i++) { + receivers.push(i); + } + } else { + jiffClient.helpers.sort_ids(receivers); + } + if (Zp == null) { + Zp = jiffClient.Zp; + } + if (threshold == null) { + threshold = senders.length; + } + + var imitationSecretShare = new jiffClient.SecretShare({}, senders, threshold, Zp); + return jiffClient.open(imitationSecretShare, receivers, op_id); + }; + + /** + * Share an array of values. Each sender may have an array of different length. This is handled by the lengths parameter. + * This function will reveal the lengths of the shared array. + * + * If parties would like to keep the lengths of their arrays secret, they should agree on some public "max" length apriori (either under MPC + * or as part of the logistics of the computation), all their arrays should be padded to that length by using appropriate default/identity + * values + * @method share_array + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {Array} array - the array to be shared. + * @param {null|number|object} [lengths] - the lengths of the arrays to be shared, has the following options:
+ * 1. null: lengths are unknown, each sender will publicly reveal the lengths of its own array.
+ * 2. number: all arrays are of this length
+ * 3. object: { : length }: must specify the length of the array for each sender.
+ * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. + * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. + * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used). + * @param {string|number} [share_id=auto_gen()] - the base tag used to tag the messages sent by this share operation, every element of the array + * will get a unique id based on the concatenation of base_share_id and the index of the element. + * This tag is used so that parties distinguish messages belonging to this share operation from + * other share operations between the same parties (when the order of execution is not + * deterministic). An automatic id is generated by increasing a local counter, default + * ids suffice when all parties execute all sharing operations with the same senders + * and receivers in the same order. + * @returns {?promise} if the calling party is a receiver then a promise to the shared arrays is returned, the promise will provide an object + * formatted as follows: { : [ <1st_share>, <2nd_share>, ..., <(lengths[party_id])th_share> ] } + * where the party_ids are those of the senders. + * if the calling party is not a receiver, then null is returned. + */ + jiffClient.share_array = arraysSharing.jiff_share_array.bind(null, jiffClient); + + /** + * Opens an array of secret shares. + * @method open_array + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} shares - an array containing this party's shares of the secrets to reconstruct + * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties + * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open + * @returns {?promise} a (JQuery) promise to ALL the open values of the secret, the promise will yield + * an array of values matching the corresponding given secret share by index. If the calling party + * is not specified in parties, then null is returned + */ + jiffClient.open_array = arraysSharing.jiff_open_array.bind(null, jiffClient); +}; - var promise = Promise.all(jiffClient.barriers[barrier_id]); - delete jiffClient.barriers[barrier_id]; - return promise; - }; +},{"../protocols/arrays/sharing.js":21,"../protocols/gmw_bit/gmw_open.js":30,"../protocols/gmw_bit/gmw_share.js":31,"../protocols/shamir/open.js":40,"../protocols/shamir/reshare.js":41,"../protocols/shamir/share.js":42}],8:[function(require,module,exports){ +module.exports = function (jiffClient) { + var maxBarrierId = 10000000; + var currentBarrierId = 0; + var openBarriers = 0; + + /** + * Starts a new barrier, all promises and secret shares created between this call and the corresponding start_barrier + * call will be part of this barrier. start_barrier may be called before previous barriers are resolved, in which + * case promises / secret shares created will be part of the new barrier as well as any previous barriers. + * @memberof module:jiff-client~JIFFClient + * @method start_barrier + * @instance + * @returns {number} a barrier id that identifies this barrier. + */ + jiffClient.start_barrier = function () { + openBarriers++; + currentBarrierId = (currentBarrierId + 1 % maxBarrierId); + jiffClient.barriers[currentBarrierId] = []; + return currentBarrierId; + }; + + /** + * Adds given promise to all active barriers. + * @memberof module:jiff-client~JIFFClient + * @method add_to_barriers + * @instance + * @param {promise} promise - the promise to add. + */ + jiffClient.add_to_barriers = function (promise) { + if (openBarriers > 0) { + for (var id in jiffClient.barriers) { + if (jiffClient.barriers.hasOwnProperty(id)) { + jiffClient.barriers[id].push(promise); + } + } + } + }; + + /** + * Executes the callback only after all promises / secret shares in the barrier were resolved. + * @memberof module:jiff-client~JIFFClient + * @method end_barrier + * @instance + * @param {number} [barrier_id=jiff.barriers.length - 1] - identifies the barrier, should be returned by start_barrier. + * by default, barrier_id will refer to the last barrier. + * @returns {promise} a promise that resolves after the secret shares are resolved. + */ + jiffClient.end_barrier = function (barrier_id) { + if (openBarriers === 0) { + return; + } + + openBarriers--; + if (barrier_id == null) { + barrier_id = currentBarrierId; + } + + var promise = Promise.all(jiffClient.barriers[barrier_id]); + delete jiffClient.barriers[barrier_id]; + return promise; + }; }; },{}],9:[function(require,module,exports){ -// Manages op_id counters and generation -module.exports = function (jiffClient) { - - /** - * Resets all the counters for op_ids - * @method counters.reset - * @memberof module:jiff-client~JIFFClient - * @instance - */ - jiffClient.counters.reset = function () { - jiffClient.counters.op_count = {}; - jiffClient.counters.op_count_preprocessing = {}; - - if (jiffClient.counters.pending_opens == null) { - jiffClient.counters.pending_opens = 0; - } - - // stores a seed for generating unique op_ids. - jiffClient.op_id_seed = ''; - }; - - // initialize the counters for the first time - jiffClient.counters.reset(); - - /** - * Shorthand for generating unique operation ids. - * All primitives called after this seed will use their usual default ids prefixed by the seed. - * Helpful when we have nested callbacks/functions (e.g. share_arrays) that may be executed in arbitrary order, - * using this function as a the first call inside such callbacks with an appropriate deterministic unique base_op_id - * ensures that regardless of the order of execution, operations in the same callback are matched correctly across - * all parties. - * Check out demos/graph-pip/mpc.js for an example on using this. - * @method seed_ids - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string|number} base_op_id - the base seed to use as a prefix for all future op_ids. - */ - jiffClient.seed_ids = function (base_op_id) { - if (base_op_id == null || base_op_id === '') { - jiffClient.op_id_seed = ''; - } else { - jiffClient.op_id_seed = base_op_id.toString() + ':'; - } - }; - - /** - * Generate a unique operation id for a new operation object. - * The returned op_id will be unique with respect to other operations, and identifies the same - * operation across all parties, as long as all parties are executing instructions in the same order. - * @method gen_op_id - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op - the type/name of operation performed. - * @param {Array} holders - an array containing the ids of all the parties carrying out the operation. - * @return {string} the op_id for the operation. - */ - jiffClient.counters.gen_op_id = function (op, holders) { - var label = jiffClient.op_id_seed + op + ':' + holders.join(','); - if (jiffClient.counters.op_count[label] == null) { - jiffClient.counters.op_count[label] = 0; - } - return label + ':' + (jiffClient.counters.op_count[label]++); - }; - - /** - * Generate a unique operation id for a new operation object given two distinct executing parties lists. - * For example, when sharing, this is given two potentially different lists of senders and receivers. - * The returned op_id will be unique with respect to other operations, and identifies the same - * operation across all parties, as long as all parties are executing instructions in the same order. - * @method gen_op_id2 - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op - the type/name of operation performed. - * @param {Array} receivers - an array containing the ids of all the parties carrying out the receiving portion of the operation. - * @param {Array} senders - an array containing the ids of all the parties carrying out the sending portion of the operation. - * @return {string} the op_id for the operation. - */ - jiffClient.counters.gen_op_id2 = function (op, receivers, senders) { - var label = jiffClient.op_id_seed + op + ':' + senders.join(',') + ':' + receivers.join(','); - if (jiffClient.counters.op_count[label] == null) { - jiffClient.counters.op_count[label] = 0; - } - return label + ':' + (jiffClient.counters.op_count[label]++); - }; - - /** - * Generate a unique operation id for a new operation object (for preprocessing) - * The returned op_id will be unique with respect to other operations, and identifies the same - * operation across all parties, as long as all parties are executing instructions in the same order. - * @method gen_op_id_preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op - the type/name of operation performed. - * @param {Array} holders - an array containing the ids of all the parties carrying out the operation. - * @return {string} the op_id for the operation. - */ - jiffClient.counters.gen_op_id_preprocessing = function (op, holders) { - var label = jiffClient.op_id_seed + op + ':' + holders.join(','); - if (jiffClient.counters.op_count_preprocessing[label] == null) { - jiffClient.counters.op_count_preprocessing[label] = 0; - } - return label + ':' + (jiffClient.counters.op_count_preprocessing[label]++); - }; - - /** - * Generate a unique operation id for a new operation object given two distinct executing parties lists (for preprocessing). - * For example, when sharing, this is given two potentially different lists of senders and receivers. - * The returned op_id will be unique with respect to other operations, and identifies the same - * operation across all parties, as long as all parties are executing instructions in the same order. - * @method gen_op_id2_preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op - the type/name of operation performed. - * @param {Array} receivers - an array containing the ids of all the parties carrying out the receiving portion of the operation. - * @param {Array} senders - an array containing the ids of all the parties carrying out the sending portion of the operation. - * @return {string} the op_id for the operation. - */ - jiffClient.counters.gen_op_id2_preprocessing = function (op, receivers, senders) { - var label = jiffClient.op_id_seed + op + ':' + senders.join(',') + ':' + receivers.join(','); - if (jiffClient.counters.op_count_preprocessing[label] == null) { - jiffClient.counters.op_count_preprocessing[label] = 0; - } - return label + ':' + (jiffClient.counters.op_count_preprocessing[label]++); - }; +// Manages op_id counters and generation +module.exports = function (jiffClient) { + + /** + * Resets all the counters for op_ids + * @method counters.reset + * @memberof module:jiff-client~JIFFClient + * @instance + */ + jiffClient.counters.reset = function () { + jiffClient.counters.op_count = {}; + jiffClient.counters.op_count_preprocessing = {}; + + if (jiffClient.counters.pending_opens == null) { + jiffClient.counters.pending_opens = 0; + } + + // stores a seed for generating unique op_ids. + jiffClient.op_id_seed = ''; + }; + + // initialize the counters for the first time + jiffClient.counters.reset(); + + /** + * Shorthand for generating unique operation ids. + * All primitives called after this seed will use their usual default ids prefixed by the seed. + * Helpful when we have nested callbacks/functions (e.g. share_arrays) that may be executed in arbitrary order, + * using this function as a the first call inside such callbacks with an appropriate deterministic unique base_op_id + * ensures that regardless of the order of execution, operations in the same callback are matched correctly across + * all parties. + * Check out demos/graph-pip/mpc.js for an example on using this. + * @method seed_ids + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string|number} base_op_id - the base seed to use as a prefix for all future op_ids. + */ + jiffClient.seed_ids = function (base_op_id) { + if (base_op_id == null || base_op_id === '') { + jiffClient.op_id_seed = ''; + } else { + jiffClient.op_id_seed = base_op_id.toString() + ':'; + } + }; + + /** + * Generate a unique operation id for a new operation object. + * The returned op_id will be unique with respect to other operations, and identifies the same + * operation across all parties, as long as all parties are executing instructions in the same order. + * @method gen_op_id + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op - the type/name of operation performed. + * @param {Array} holders - an array containing the ids of all the parties carrying out the operation. + * @return {string} the op_id for the operation. + */ + jiffClient.counters.gen_op_id = function (op, holders) { + var label = jiffClient.op_id_seed + op + ':' + holders.join(','); + if (jiffClient.counters.op_count[label] == null) { + jiffClient.counters.op_count[label] = 0; + } + return label + ':' + (jiffClient.counters.op_count[label]++); + }; + + /** + * Generate a unique operation id for a new operation object given two distinct executing parties lists. + * For example, when sharing, this is given two potentially different lists of senders and receivers. + * The returned op_id will be unique with respect to other operations, and identifies the same + * operation across all parties, as long as all parties are executing instructions in the same order. + * @method gen_op_id2 + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op - the type/name of operation performed. + * @param {Array} receivers - an array containing the ids of all the parties carrying out the receiving portion of the operation. + * @param {Array} senders - an array containing the ids of all the parties carrying out the sending portion of the operation. + * @return {string} the op_id for the operation. + */ + jiffClient.counters.gen_op_id2 = function (op, receivers, senders) { + var label = jiffClient.op_id_seed + op + ':' + senders.join(',') + ':' + receivers.join(','); + if (jiffClient.counters.op_count[label] == null) { + jiffClient.counters.op_count[label] = 0; + } + return label + ':' + (jiffClient.counters.op_count[label]++); + }; + + /** + * Generate a unique operation id for a new operation object (for preprocessing) + * The returned op_id will be unique with respect to other operations, and identifies the same + * operation across all parties, as long as all parties are executing instructions in the same order. + * @method gen_op_id_preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op - the type/name of operation performed. + * @param {Array} holders - an array containing the ids of all the parties carrying out the operation. + * @return {string} the op_id for the operation. + */ + jiffClient.counters.gen_op_id_preprocessing = function (op, holders) { + var label = jiffClient.op_id_seed + op + ':' + holders.join(','); + if (jiffClient.counters.op_count_preprocessing[label] == null) { + jiffClient.counters.op_count_preprocessing[label] = 0; + } + return label + ':' + (jiffClient.counters.op_count_preprocessing[label]++); + }; + + /** + * Generate a unique operation id for a new operation object given two distinct executing parties lists (for preprocessing). + * For example, when sharing, this is given two potentially different lists of senders and receivers. + * The returned op_id will be unique with respect to other operations, and identifies the same + * operation across all parties, as long as all parties are executing instructions in the same order. + * @method gen_op_id2_preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op - the type/name of operation performed. + * @param {Array} receivers - an array containing the ids of all the parties carrying out the receiving portion of the operation. + * @param {Array} senders - an array containing the ids of all the parties carrying out the sending portion of the operation. + * @return {string} the op_id for the operation. + */ + jiffClient.counters.gen_op_id2_preprocessing = function (op, receivers, senders) { + var label = jiffClient.op_id_seed + op + ':' + senders.join(',') + ':' + receivers.join(','); + if (jiffClient.counters.op_count_preprocessing[label] == null) { + jiffClient.counters.op_count_preprocessing[label] = 0; + } + return label + ':' + (jiffClient.counters.op_count_preprocessing[label]++); + }; }; },{}],10:[function(require,module,exports){ -// Server extensions management system -module.exports = function (JIFFClient) { - /** - * Checks if the given extension is applied. - * @method has_extension - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} name - the extension name (found in the extension filename as jiff-client-[name].js). - * @return {boolean} true if the extension was applied, false otherwise. - */ - JIFFClient.prototype.has_extension = function (name) { - return this.extensions.indexOf(name) > -1; - }; - - /** - * Checks if a given extension can be safely applied to the instance - * @method can_apply_extension - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} name - the extension name (found in the filename at jiff-client[name].js) - * @return {boolean} true if the extension can be safely applied, otherwise returns an error message. - */ - JIFFClient.prototype.can_apply_extension = function (name) { - return true; - }; - - /** - * Applies the given extension. - * If the extension is safe (as per can_apply_extension), it will be applied successfully. - * If the extension is not safe to be applied, an exception will be thrown with an appropriate error message. - * @see {@link module:jiff-client~JIFFClient#can_apply_extension} - * @method apply_extension - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {object} ext - the namespace of the extension acquired when the extension is imported, should contain a make_jiff function. - * @param {object} [options={}] - optional options to be passed to the extension. - */ - JIFFClient.prototype.apply_extension = function (ext, options) { - if (options == null) { - options = {}; - } - - var name = ext.name; - var status = this.can_apply_extension(name); - - if (status === true) { - ext.make_jiff(this, options); - - this.extensions.push(name); - this.extension_applied(name, options); - } else { - throw status; - } - }; - - /** - * Called when an extension is applied successfully. Override to change behavior of your extension based on future extensions. - * @method extension_applied - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} name - the name of the applied extension. - * @param {object} [options={}] - the options passed by the user to the newly applied extension. - */ - JIFFClient.prototype.extension_applied = function (name, options) {}; +// Server extensions management system +module.exports = function (JIFFClient) { + /** + * Checks if the given extension is applied. + * @method has_extension + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} name - the extension name (found in the extension filename as jiff-client-[name].js). + * @return {boolean} true if the extension was applied, false otherwise. + */ + JIFFClient.prototype.has_extension = function (name) { + return this.extensions.indexOf(name) > -1; + }; + + /** + * Checks if a given extension can be safely applied to the instance + * @method can_apply_extension + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} name - the extension name (found in the filename at jiff-client[name].js) + * @return {boolean} true if the extension can be safely applied, otherwise returns an error message. + */ + JIFFClient.prototype.can_apply_extension = function (name) { + return true; + }; + + /** + * Applies the given extension. + * If the extension is safe (as per can_apply_extension), it will be applied successfully. + * If the extension is not safe to be applied, an exception will be thrown with an appropriate error message. + * @see {@link module:jiff-client~JIFFClient#can_apply_extension} + * @method apply_extension + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {object} ext - the namespace of the extension acquired when the extension is imported, should contain a make_jiff function. + * @param {object} [options={}] - optional options to be passed to the extension. + */ + JIFFClient.prototype.apply_extension = function (ext, options) { + if (options == null) { + options = {}; + } + + var name = ext.name; + var status = this.can_apply_extension(name); + + if (status === true) { + ext.make_jiff(this, options); + + this.extensions.push(name); + this.extension_applied(name, options); + } else { + throw status; + } + }; + + /** + * Called when an extension is applied successfully. Override to change behavior of your extension based on future extensions. + * @method extension_applied + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} name - the name of the applied extension. + * @param {object} [options={}] - the options passed by the user to the newly applied extension. + */ + JIFFClient.prototype.extension_applied = function (name, options) {}; }; },{}],11:[function(require,module,exports){ -/** - * The hooks for this instance. - * Checkout the hooks documentation - * @see {@link module:jiff-client~JIFFClient#hooks} - * @name hooks - * @alias hooks - * @namespace - */ - -var crypto = require('../util/crypto.js'); -var shamir_share = require('../protocols/shamir/share.js'); -var shamir_open = require('../protocols/shamir/open.js'); - -function Hooks(jiffClient) { - this.jiffClient = jiffClient; - - // avoid sharing aliases to the same array - for (hook in Hooks.prototype) { - if (Hooks.prototype.hasOwnProperty(hook) && typeof(Hooks.prototype[hook].length) === 'number' && Hooks.prototype[hook].slice) { - this[hook] = Hooks.prototype[hook].slice(); - } - } - - // fill in hooks from options - var optionHooks = jiffClient.options.hooks || {}; - for (var hook in optionHooks) { - if (hook === 'afterOperation') { - this[hook] = optionHooks[hook].concat(this[hook]); - } else if (optionHooks.hasOwnProperty(hook)) { - this[hook] = optionHooks[hook]; - } - } -} - -/** - * Hook for computing shares of a secret - * @method computeShares - * @memberof hooks - * @param jiffClient {module:jiff-client~JIFFClient} - the jiff client instance - * @param secret {number} - the secret to share - * @param parties_list {number[]} - array of party ids to share with - * @param threshold {number} - threshold of sharing - * @param Zp {number} - the field prime - */ -Hooks.prototype.computeShares = shamir_share.jiff_compute_shares; -Hooks.prototype.reconstructShare = shamir_open.jiff_lagrange; - -// Crypto hooks -Hooks.prototype.encryptSign = function (jiffClient, message) { - if (jiffClient.options.sodium !== false) { - return crypto.encrypt_and_sign.apply(null, arguments); - } else { - return message; - } -}; - -Hooks.prototype.decryptSign = function (jiffClient, cipher) { - if (jiffClient.options.sodium !== false) { - return crypto.decrypt_and_sign.apply(null, arguments); - } else { - return cipher; - } -}; - -Hooks.prototype.generateKeyPair = function (jiffClient) { - if (jiffClient.options.sodium !== false) { - var key = jiffClient.sodium_.crypto_box_keypair(); // this party's public and secret key - return { public_key: key.publicKey, secret_key: key.privateKey } - } else { - return { public_key: '', secret_key: ''}; - } -}; - -Hooks.prototype.parseKey = function (jiffClient, keyString) { - if (jiffClient.options.sodium !== false) { - return new Uint8Array(JSON.parse(keyString)); - } else { - return ''; - } -}; - -Hooks.prototype.dumpKey = function (jiffClient, key) { - if (jiffClient.options.sodium !== false) { - return '[' + key.toString() + ']'; - } else { - return ''; - } -}; - -// Array Hooks -Hooks.prototype.beforeShare = []; -Hooks.prototype.afterComputeShare = []; -Hooks.prototype.receiveShare = []; - -Hooks.prototype.beforeOpen = []; -Hooks.prototype.receiveOpen = []; -Hooks.prototype.afterReconstructShare = []; - -Hooks.prototype.createSecretShare = []; - -Hooks.prototype.beforeOperation = []; -Hooks.prototype.afterOperation = [ - // parse content of share/open messages to be integers (instead of strings due to encryption/decryption) - function (jiff, label, msg) { - if (label === 'share' || label === 'open') { - msg['share'] = parseInt(msg['share'], 10); - } - return msg; - } -]; - -/** - * Execute all hooks attached to the given name in order. - * Hooks are executed sequentially such that the first hook's return value is passed into the second and so on. - * @method execute_array_hooks - * @memberof hooks - * @param {string} hook_name - the name of the hook - * @param {Array} params - parameters to pass to the hooks - * @param {number} acc_index - the index in params in which the result of the hooks must be saved, if no hooks - * exist for the name, then params[acc_index] is returned. - * @return {object} returns the result of the last hook. - */ -Hooks.prototype.execute_array_hooks = function (hook_name, params, acc_index) { - var arr = this.jiffClient.hooks[hook_name]; - arr = (arr == null ? [] : arr); - - for (var i = 0; i < arr.length; i++) { - params[acc_index] = arr[i].apply(this.jiffClient, params); - } - return params[acc_index]; -}; - +/** + * The hooks for this instance. + * Checkout the hooks documentation + * @see {@link module:jiff-client~JIFFClient#hooks} + * @name hooks + * @alias hooks + * @namespace + */ + +var crypto = require('../util/crypto.js'); +var shamir_share = require('../protocols/shamir/share.js'); +var shamir_open = require('../protocols/shamir/open.js'); + +function Hooks(jiffClient) { + this.jiffClient = jiffClient; + + // avoid sharing aliases to the same array + for (hook in Hooks.prototype) { + if (Hooks.prototype.hasOwnProperty(hook) && typeof(Hooks.prototype[hook].length) === 'number' && Hooks.prototype[hook].slice) { + this[hook] = Hooks.prototype[hook].slice(); + } + } + + // fill in hooks from options + var optionHooks = jiffClient.options.hooks || {}; + for (var hook in optionHooks) { + if (hook === 'afterOperation') { + this[hook] = optionHooks[hook].concat(this[hook]); + } else if (optionHooks.hasOwnProperty(hook)) { + this[hook] = optionHooks[hook]; + } + } +} + +/** + * Hook for computing shares of a secret + * @method computeShares + * @memberof hooks + * @param jiffClient {module:jiff-client~JIFFClient} - the jiff client instance + * @param secret {number} - the secret to share + * @param parties_list {number[]} - array of party ids to share with + * @param threshold {number} - threshold of sharing + * @param Zp {number} - the field prime + */ +Hooks.prototype.computeShares = shamir_share.jiff_compute_shares; +Hooks.prototype.reconstructShare = shamir_open.jiff_lagrange; + +// Crypto hooks +Hooks.prototype.encryptSign = function (jiffClient, message) { + if (jiffClient.sodium_ !== false) { + return crypto.encrypt_and_sign.apply(null, arguments); + } else { + return message; + } +}; + +Hooks.prototype.decryptSign = function (jiffClient, cipher) { + if (jiffClient.sodium_ !== false) { + return crypto.decrypt_and_sign.apply(null, arguments); + } else { + return cipher; + } +}; + +Hooks.prototype.generateKeyPair = function (jiffClient) { + if (jiffClient.sodium_ !== false) { + var key = jiffClient.sodium_.crypto_box_keypair(); // this party's public and secret key + return { public_key: key.publicKey, secret_key: key.privateKey } + } else { + return { public_key: '', secret_key: ''}; + } +}; + +Hooks.prototype.parseKey = function (jiffClient, keyString) { + if (jiffClient.sodium_ !== false) { + return new Uint8Array(JSON.parse(keyString)); + } else { + return ''; + } +}; + +Hooks.prototype.dumpKey = function (jiffClient, key) { + if (jiffClient.sodium_ !== false) { + return '[' + key.toString() + ']'; + } else { + return ''; + } +}; + +// Array Hooks +Hooks.prototype.beforeShare = []; +Hooks.prototype.afterComputeShare = []; +Hooks.prototype.receiveShare = []; + +Hooks.prototype.beforeOpen = []; +Hooks.prototype.receiveOpen = []; +Hooks.prototype.afterReconstructShare = []; + +Hooks.prototype.createSecretShare = []; + +Hooks.prototype.beforeOperation = []; +Hooks.prototype.afterOperation = [ + // parse content of share/open messages to be integers (instead of strings due to encryption/decryption) + function (jiff, label, msg) { + if (label === 'share' || label === 'open') { + msg['share'] = parseInt(msg['share'], 10); + } + return msg; + } +]; + +/** + * Execute all hooks attached to the given name in order. + * Hooks are executed sequentially such that the first hook's return value is passed into the second and so on. + * @method execute_array_hooks + * @memberof hooks + * @param {string} hook_name - the name of the hook + * @param {Array} params - parameters to pass to the hooks + * @param {number} acc_index - the index in params in which the result of the hooks must be saved, if no hooks + * exist for the name, then params[acc_index] is returned. + * @return {object} returns the result of the last hook. + */ +Hooks.prototype.execute_array_hooks = function (hook_name, params, acc_index) { + var arr = this.jiffClient.hooks[hook_name]; + arr = (arr == null ? [] : arr); + + for (var i = 0; i < arr.length; i++) { + params[acc_index] = arr[i].apply(this.jiffClient, params); + } + return params[acc_index]; +}; + module.exports = Hooks; -},{"../protocols/shamir/open.js":36,"../protocols/shamir/share.js":38,"../util/crypto.js":45}],12:[function(require,module,exports){ -var initializationHandlers = require('./handlers/initialization.js'); -var shareHandlers = require('./handlers/sharing.js'); -var customHandlers = require('./handlers/custom.js'); -var cryptoProviderHandlers = require('./handlers/crypto_provider.js'); - -/** - * Contains handlers for communication events - * @name handlers - * @alias handlers - * @namespace - */ - -// Add handlers implementations -module.exports = function (jiffClient) { - // fill in handlers - initializationHandlers(jiffClient); - shareHandlers(jiffClient); - customHandlers(jiffClient); - cryptoProviderHandlers(jiffClient); +},{"../protocols/shamir/open.js":40,"../protocols/shamir/share.js":42,"../util/crypto.js":49}],12:[function(require,module,exports){ +var initializationHandlers = require('./handlers/initialization.js'); +var shareHandlers = require('./handlers/sharing.js'); +var customHandlers = require('./handlers/custom.js'); +var cryptoProviderHandlers = require('./handlers/crypto_provider.js'); + +/** + * Contains handlers for communication events + * @name handlers + * @alias handlers + * @namespace + */ + +// Add handlers implementations +module.exports = function (jiffClient) { + // fill in handlers + initializationHandlers(jiffClient); + shareHandlers(jiffClient); + customHandlers(jiffClient); + cryptoProviderHandlers(jiffClient); }; },{"./handlers/crypto_provider.js":13,"./handlers/custom.js":14,"./handlers/initialization.js":15,"./handlers/sharing.js":16}],13:[function(require,module,exports){ -// setup handler for receiving messages from the crypto provider -module.exports = function (jiffClient) { - /** - * Parse crypto provider message and resolve associated promise. - * @method - * @memberof handlers - * @param {object} json_msg - the parsed json message as received by the crypto_provider event, contains 'values' and 'shares' attributes. - */ - jiffClient.handlers.receive_crypto_provider = function (json_msg) { - // Hook - json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'crypto_provider', json_msg], 2); - - var op_id = json_msg['op_id']; - if (jiffClient.deferreds[op_id] == null) { - return; // duplicate message: ignore - } - - // parse msg - var receivers_list = json_msg['receivers']; - var threshold = json_msg['threshold']; - var Zp = json_msg['Zp']; - - // construct secret share objects - var result = {}; - if (json_msg['values'] != null) { - result.values = json_msg['values']; - } - if (json_msg['shares'] != null) { - result.shares = []; - for (var i = 0; i < json_msg['shares'].length; i++) { - result.shares.push(new jiffClient.SecretShare(json_msg['shares'][i], receivers_list, threshold, Zp)); - } - } - - // resolve deferred - jiffClient.deferreds[op_id].resolve(result); - delete jiffClient.deferreds[op_id]; - }; +// setup handler for receiving messages from the crypto provider +module.exports = function (jiffClient) { + /** + * Parse crypto provider message and resolve associated promise. + * @method + * @memberof handlers + * @param {object} json_msg - the parsed json message as received by the crypto_provider event, contains 'values' and 'shares' attributes. + */ + jiffClient.handlers.receive_crypto_provider = function (json_msg) { + // Hook + json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'crypto_provider', json_msg], 2); + + var op_id = json_msg['op_id']; + if (jiffClient.deferreds[op_id] == null) { + return; // duplicate message: ignore + } + + // parse msg + var receivers_list = json_msg['receivers']; + var threshold = json_msg['threshold']; + var Zp = json_msg['Zp']; + + // construct secret share objects + var result = {}; + if (json_msg['values'] != null) { + result.values = json_msg['values']; + } + if (json_msg['shares'] != null) { + result.shares = []; + for (var i = 0; i < json_msg['shares'].length; i++) { + result.shares.push(new jiffClient.SecretShare(json_msg['shares'][i], receivers_list, threshold, Zp)); + } + } + + // resolve deferred + jiffClient.deferreds[op_id].resolve(result); + delete jiffClient.deferreds[op_id]; + }; }; },{}],14:[function(require,module,exports){ -module.exports = function (jiffClient) { - /** - * Called when this party receives a custom tag message from any party (including itself). - * If a custom listener was setup to listen to the tag, the message is passed to the listener. - * Otherwise, the message is stored until such a listener is provided. - * @method - * @memberof handlers - * @param {object} json_msg - the parsed json message as received by the custom event. - */ - jiffClient.handlers.receive_custom = function (json_msg) { - if (json_msg['party_id'] !== jiffClient.id) { - if (json_msg['encrypted'] === true) { - json_msg['message'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['message'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); - } - - json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'custom', json_msg], 2); - } - - var sender_id = json_msg['party_id']; - var tag = json_msg['tag']; - var message = json_msg['message']; - - if (jiffClient.listeners[tag] != null) { - jiffClient.listeners[tag](sender_id, message); - } else { - // Store message until listener is provided - var stored_messages = jiffClient.custom_messages_mailbox[tag]; - if (stored_messages == null) { - stored_messages = []; - jiffClient.custom_messages_mailbox[tag] = stored_messages; - } - - stored_messages.push({sender_id: sender_id, message: message}); - } - } +module.exports = function (jiffClient) { + /** + * Called when this party receives a custom tag message from any party (including itself). + * If a custom listener was setup to listen to the tag, the message is passed to the listener. + * Otherwise, the message is stored until such a listener is provided. + * @method + * @memberof handlers + * @param {object} json_msg - the parsed json message as received by the custom event. + */ + jiffClient.handlers.receive_custom = function (json_msg) { + if (json_msg['party_id'] !== jiffClient.id) { + if (json_msg['encrypted'] === true) { + json_msg['message'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['message'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); + } + + json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'custom', json_msg], 2); + } + + var sender_id = json_msg['party_id']; + var tag = json_msg['tag']; + var message = json_msg['message']; + + + if (jiffClient.listeners[tag] != null) { + jiffClient.listeners[tag](sender_id, message); + } else { + // Store message until listener is provided + var stored_messages = jiffClient.custom_messages_mailbox[tag]; + if (stored_messages == null) { + stored_messages = []; + jiffClient.custom_messages_mailbox[tag] = stored_messages; + } + + stored_messages.push({sender_id: sender_id, message: message}); + } + } }; },{}],15:[function(require,module,exports){ -// add handlers for initialization -module.exports = function (jiffClient) { - jiffClient.options.initialization = Object.assign({}, jiffClient.options.initialization); - - /** - * Called when an error occurs - * @method - * @memberof handlers - * @param {string} label - the name of message or operation causing the error - * @param {error|string} error - the error - */ - jiffClient.handlers.error = function (label, error) { - if (jiffClient.options.onError) { - jiffClient.options.onError(label, error); - } - - console.log(jiffClient.id, ':', 'Error from server:', label, '---', error); // TODO: remove debugging - if (label === 'initialization') { - jiffClient.socket.disconnect(); - - if (jiffClient.initialization_counter < jiffClient.options.maxInitializationRetries) { - console.log(jiffClient.id, ':', 'reconnecting..'); // TODO: remove debugging - setTimeout(jiffClient.connect, jiffClient.options.socketOptions.reconnectionDelay); - } - } - }; - - /** - * Builds the initialization message for this instance - * @method - * @memberof handlers - * @return {Object} - */ - jiffClient.handlers.build_initialization_message = function () { - var msg = { - computation_id: jiffClient.computation_id, - party_id: jiffClient.id, - party_count: jiffClient.party_count, - public_key: jiffClient.public_key != null ? jiffClient.hooks.dumpKey(jiffClient, jiffClient.public_key) : undefined - }; - msg = Object.assign(msg, jiffClient.options.initialization); - - // Initialization Hook - return jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'initialization', msg], 2); - }; - - /** - * Begins initialization of this instance by sending the initialization message to the server. - * Should only be called after connection is established. - * Do not call this manually unless you know what you are doing, use .connect() instead! - * @method - * @memberof handlers - */ - jiffClient.handlers.connected = function () { - console.log('Connected!', jiffClient.id); // TODO: remove debugging - jiffClient.initialization_counter++; - - if (jiffClient.secret_key == null && jiffClient.public_key == null) { - var key = jiffClient.hooks.generateKeyPair(jiffClient); - jiffClient.secret_key = key.secret_key; - jiffClient.public_key = key.public_key; - } - - // Initialization message - var msg = jiffClient.handlers.build_initialization_message(); - - // Emit initialization message to server - jiffClient.socket.emit('initialization', JSON.stringify(msg)); - }; - - /** - * Called after the server approves initialization of this instance. - * Sets the instance id, the count of parties in the computation, and the public keys - * of initialized parties. - * @method - * @memberof handlers - */ - jiffClient.handlers.initialized = function (msg) { - jiffClient.__initialized = true; - jiffClient.initialization_counter = 0; - - msg = JSON.parse(msg); - msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'initialization', msg], 2); - - jiffClient.id = msg.party_id; - jiffClient.party_count = msg.party_count; - - // Now: (1) this party is connect (2) server (and other parties) know this public key - // Resend all pending messages - jiffClient.socket.resend_mailbox(); - - // store the received public keys and resolve wait callbacks - jiffClient.handlers.store_public_keys(msg.public_keys); - }; - - /** - * Parse and store the given public keys - * @method - * @memberof handlers - * @param {object} keymap - maps party id to serialized public key. - */ - jiffClient.handlers.store_public_keys = function (keymap) { - var i; - for (i in keymap) { - if (keymap.hasOwnProperty(i) && jiffClient.keymap[i] == null) { - jiffClient.keymap[i] = jiffClient.hooks.parseKey(jiffClient, keymap[i]); - } - } - - // Resolve any pending messages that were received before the sender's public key was known - jiffClient.resolve_messages_waiting_for_keys(); - - // Resolve any pending waits that have satisfied conditions - jiffClient.execute_wait_callbacks(); - - // Check if all keys have been received - if (jiffClient.keymap['s1'] == null) { - return; - } - for (i = 1; i <= jiffClient.party_count; i++) { - if (jiffClient.keymap[i] == null) { - return; - } - } - - // all parties are connected; execute callback - if (jiffClient.__ready !== true && jiffClient.__initialized) { - jiffClient.__ready = true; - if (jiffClient.options.onConnect != null) { - jiffClient.options.onConnect(jiffClient); - } - } - }; +// add handlers for initialization +module.exports = function (jiffClient) { + jiffClient.options.initialization = Object.assign({}, jiffClient.options.initialization); + + /** + * Called when an error occurs + * @method + * @memberof handlers + * @param {string} label - the name of message or operation causing the error + * @param {error|string} error - the error + */ + jiffClient.handlers.error = function (label, error) { + if (jiffClient.options.onError) { + jiffClient.options.onError(label, error); + } + + console.log(jiffClient.id, ':', 'Error from server:', label, '---', error); // TODO: remove debugging + if (label === 'initialization') { + jiffClient.socket.disconnect(); + + if (jiffClient.initialization_counter < jiffClient.options.maxInitializationRetries) { + console.log(jiffClient.id, ':', 'reconnecting..'); // TODO: remove debugging + setTimeout(jiffClient.connect, jiffClient.options.socketOptions.reconnectionDelay); + } + } + }; + + /** + * Builds the initialization message for this instance + * @method + * @memberof handlers + * @return {Object} + */ + jiffClient.handlers.build_initialization_message = function () { + var msg = { + computation_id: jiffClient.computation_id, + party_id: jiffClient.id, + party_count: jiffClient.party_count, + public_key: jiffClient.public_key != null ? jiffClient.hooks.dumpKey(jiffClient, jiffClient.public_key) : undefined + }; + msg = Object.assign(msg, jiffClient.options.initialization); + + // Initialization Hook + return jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'initialization', msg], 2); + }; + + /** + * Begins initialization of this instance by sending the initialization message to the server. + * Should only be called after connection is established. + * Do not call this manually unless you know what you are doing, use .connect() instead! + * @method + * @memberof handlers + */ + jiffClient.handlers.connected = function () { + console.log('Connected!', jiffClient.id); // TODO: remove debugging + jiffClient.initialization_counter++; + + if (jiffClient.secret_key == null && jiffClient.public_key == null) { + var key = jiffClient.hooks.generateKeyPair(jiffClient); + jiffClient.secret_key = key.secret_key; + jiffClient.public_key = key.public_key; + } + + // Initialization message + var msg = jiffClient.handlers.build_initialization_message(); + + // Emit initialization message to server + jiffClient.socket.emit('initialization', JSON.stringify(msg)); + }; + + /** + * Called after the server approves initialization of this instance. + * Sets the instance id, the count of parties in the computation, and the public keys + * of initialized parties. + * @method + * @memberof handlers + */ + jiffClient.handlers.initialized = function (msg) { + jiffClient.__initialized = true; + jiffClient.initialization_counter = 0; + + msg = JSON.parse(msg); + msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'initialization', msg], 2); + + jiffClient.id = msg.party_id; + jiffClient.party_count = msg.party_count; + + // Now: (1) this party is connect (2) server (and other parties) know this public key + // Resend all pending messages + jiffClient.socket.resend_mailbox(); + + // store the received public keys and resolve wait callbacks + jiffClient.handlers.store_public_keys(msg.public_keys); + }; + + /** + * Parse and store the given public keys + * @method + * @memberof handlers + * @param {object} keymap - maps party id to serialized public key. + */ + jiffClient.handlers.store_public_keys = function (keymap) { + var i; + for (i in keymap) { + if (keymap.hasOwnProperty(i) && jiffClient.keymap[i] == null) { + jiffClient.keymap[i] = jiffClient.hooks.parseKey(jiffClient, keymap[i]); + } + } + + // Resolve any pending messages that were received before the sender's public key was known + jiffClient.resolve_messages_waiting_for_keys(); + + // Resolve any pending waits that have satisfied conditions + jiffClient.execute_wait_callbacks(); + + // Check if all keys have been received + if (jiffClient.keymap['s1'] == null) { + return; + } + for (i = 1; i <= jiffClient.party_count; i++) { + if (jiffClient.keymap[i] == null) { + return; + } + } + + // all parties are connected; execute callback + if (jiffClient.__ready !== true && jiffClient.__initialized) { + jiffClient.__ready = true; + if (jiffClient.options.onConnect != null) { + jiffClient.options.onConnect(jiffClient); + } + } + }; }; },{}],16:[function(require,module,exports){ -// adds sharing related handlers -module.exports = function (jiffClient) { - /** - * Store the received share and resolves the corresponding - * deferred if needed. - * @method - * @memberof handlers - * @param {object} json_msg - the parsed json message as received. - */ - jiffClient.handlers.receive_share = function (json_msg) { - // Decrypt share - json_msg['share'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['share'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); - json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'share', json_msg], 2); - - var sender_id = json_msg['party_id']; - var op_id = json_msg['op_id']; - var share = json_msg['share']; - - // Call hook - share = jiffClient.hooks.execute_array_hooks('receiveShare', [jiffClient, sender_id, share], 2); - - // check if a deferred is set up (maybe the share was received early) - if (jiffClient.deferreds[op_id] == null) { - jiffClient.deferreds[op_id] = {}; - } - if (jiffClient.deferreds[op_id][sender_id] == null) { - // Share is received before deferred was setup, store it. - jiffClient.deferreds[op_id][sender_id] = new jiffClient.helpers.Deferred(); - } - - // Deferred is already setup, resolve it. - jiffClient.deferreds[op_id][sender_id].resolve(share); - }; - - /** - * Resolves the deferred corresponding to operation_id and sender_id. - * @method - * @memberof handlers - * @param {object} json_msg - the json message as received with the open event. - */ - jiffClient.handlers.receive_open = function (json_msg) { - // Decrypt share - if (json_msg['party_id'] !== jiffClient.id) { - json_msg['share'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['share'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); - json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'open', json_msg], 2); - } - - var sender_id = json_msg['party_id']; - var op_id = json_msg['op_id']; - var share = json_msg['share']; - var Zp = json_msg['Zp']; - - // call hook - share = jiffClient.hooks.execute_array_hooks('receiveOpen', [jiffClient, sender_id, share, Zp], 2); - - // Ensure deferred is setup - if (jiffClient.deferreds[op_id] == null) { - jiffClient.deferreds[op_id] = {}; - } - if (jiffClient.deferreds[op_id].shares == null) { - jiffClient.deferreds[op_id].shares = []; - } - - // Accumulate received shares - jiffClient.deferreds[op_id].shares.push({value: share, sender_id: sender_id, Zp: Zp}); - - // Resolve when ready - if (jiffClient.deferreds[op_id].shares.length === jiffClient.deferreds[op_id].threshold) { - jiffClient.deferreds[op_id].deferred.resolve(); - } - - // Clean up if done - if (jiffClient.deferreds[op_id] != null && jiffClient.deferreds[op_id].deferred === 'CLEAN' && jiffClient.deferreds[op_id].shares.length === jiffClient.deferreds[op_id].total) { - delete jiffClient.deferreds[op_id]; - } - } +// adds sharing related handlers +module.exports = function (jiffClient) { + /** + * Store the received share and resolves the corresponding + * deferred if needed. + * @method + * @memberof handlers + * @param {object} json_msg - the parsed json message as received. + */ + + jiffClient.handlers.receive_share = function (json_msg) { + // Decrypt share + json_msg['share'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['share'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); + json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'share', json_msg], 2); + + var sender_id = json_msg['party_id']; + var op_id = json_msg['op_id']; + var share = json_msg['share']; + + // Call hook + share = jiffClient.hooks.execute_array_hooks('receiveShare', [jiffClient, sender_id, share], 2); + + // check if a deferred is set up (maybe the share was received early) + if (jiffClient.deferreds[op_id] == null) { + jiffClient.deferreds[op_id] = {}; + } + if (jiffClient.deferreds[op_id][sender_id] == null) { + // Share is received before deferred was setup, store it. + jiffClient.deferreds[op_id][sender_id] = new jiffClient.helpers.Deferred(); + } + + // Deferred is already setup, resolve it. + jiffClient.deferreds[op_id][sender_id].resolve(share); + }; + + /** + * Store the received ot msg and resolves the corresponding for gmw_and function internal use. + * deferred if needed. + * @method + * @memberof handlers + * @param {object} json_msg - the parsed json message as received. + */ + jiffClient.handlers.ot_receive = function (json_msg) { + // Decrypt share + json_msg['message'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['message'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); + json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'message', json_msg], 2); + var sender_id = json_msg['party_id']; + + var msg=json_msg['message']; + msg=JSON.parse(msg); + var opts=msg['opts']; + var opId=msg['op_id']+'-'+msg['tag']; + + // check if a deferred is set up (maybe the share was received early) + if (jiffClient.deferreds[opId] == null) { + jiffClient.deferreds[opId] = {}; + } + if (jiffClient.deferreds[opId][sender_id] == null) { + // Share is received before deferred was setup, store it. + jiffClient.deferreds[opId][sender_id] = new jiffClient.helpers.Deferred(); + } + + // Deferred is already setup, resolve it. + jiffClient.deferreds[opId][sender_id].resolve(opts); + }; + + /** + * Resolves the deferred corresponding to operation_id and sender_id. + * @method + * @memberof handlers + * @param {object} json_msg - the json message as received with the open event. + */ + + + jiffClient.handlers.receive_open = function (json_msg) { + // Decrypt share + if (json_msg['party_id'] !== jiffClient.id) { + json_msg['share'] = jiffClient.hooks.decryptSign(jiffClient, json_msg['share'], jiffClient.secret_key, jiffClient.keymap[json_msg['party_id']]); + json_msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'open', json_msg], 2); + } + + var sender_id = json_msg['party_id']; + var op_id = json_msg['op_id']; + var share = json_msg['share']; + var Zp = json_msg['Zp']; + + // call hook + share = jiffClient.hooks.execute_array_hooks('receiveOpen', [jiffClient, sender_id, share, Zp], 2); + + // Ensure deferred is setup + if (jiffClient.deferreds[op_id] == null) { + jiffClient.deferreds[op_id] = {}; + } + if (jiffClient.deferreds[op_id].shares == null) { + jiffClient.deferreds[op_id].shares = []; + } + + // Accumulate received shares + jiffClient.deferreds[op_id].shares.push({value: share, sender_id: sender_id, Zp: Zp}); + + // Resolve when ready + if (jiffClient.deferreds[op_id].shares.length === jiffClient.deferreds[op_id].threshold) { + jiffClient.deferreds[op_id].deferred.resolve(); + } + + // Clean up if done + if (jiffClient.deferreds[op_id] != null && jiffClient.deferreds[op_id].deferred === 'CLEAN' && jiffClient.deferreds[op_id].shares.length === jiffClient.deferreds[op_id].total) { + delete jiffClient.deferreds[op_id]; + } + } }; },{}],17:[function(require,module,exports){ -var linkedList = require('../../common/linkedlist.js'); - -module.exports = function (jiffClient) { - var isRunning = false; - var userCallbacks = []; - var preprocessingTasks = [linkedList()]; - - /** - * Checks if the given operation uses preprocessed values - * @method has_preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op - name of the operation to check - * @return {boolean} true if the op uses preprocessing, false otherwise - */ - jiffClient.has_preprocessing = function (op) { - for (var i = 0; i < jiffClient.extensions.length; i++) { - if (jiffClient.preprocessing_function_map[jiffClient.extensions[i]][op] != null) { - return true; - } - } - - return false; - }; - - /** - * Get a preprocessed share/value by associated op_id. If value does not exist - * Fallback to some user specified way for creating it - * @method get_preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op_id - the op_id associated with the preprocessed value/share - * @return {object} the preprocessed share(s) - */ - jiffClient.get_preprocessing = function (op_id) { - var values = jiffClient.preprocessing_table[op_id]; - if (values != null) { - return values; - } - if (jiffClient.crypto_provider === true) { - return null; - } - throw new Error('No preprocessed value(s) that correspond to the op_id "' + op_id + '"'); - }; - - /** - * Store a pair of op_id and associated pre-processed value/share - * The value/share can be accessed later during the computation through jiffClient.get_preprocessing(op_id) - * @method store_preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} op_id - the op_id associated with the preprocessed value/share - * @param {SecretShare} share - the share/value to store - */ - jiffClient.store_preprocessing = function (op_id, share) { - if (share != null) { - jiffClient.preprocessing_table[op_id] = share; - } - }; - - /** - * Generate values used for JIFF operations in advance of the computation. - * - * Calling this function does not begin preprocessing, it just creates a preprocessing task. After you created - * your desired tasks, you can ask JIFF to execute them via {@link module:jiff-client~JIFFClient#executePreprocessing}. - * - * @method preprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param {string} dependent_op - name of the operation that will later use the pre_processed values - * @param {Number} [count=1] - number of times the protocol should be performed, number of values that will be generated - * @param {Object} [protocols=defaults] - a mapping from base preprocessing elements ('beaver', 'bits', 'sampling') to functions that can pre-process them - * the function must implement the same interface as the JIFF provided protocols (e.g. jiffClient.protocols.generate_beaver_bgw), - * missing mappings indicate that JIFF must use the default protocols - * @param {Number} [threshold=receivers_list.length] - the threshold of the preprocessed shares - * @param {Array} [receivers_list=all_parties] - the parties that will receive the preprocsssed shares - * @param {Array} [compute_list=all_parties] - the parties that will compute the preprocsssed shares - * @param {Number} [Zp=jiffClient.Zp] - the Zp of the preprocessed shares - * @param {Array} [id_list=auto_gen()] - array of ids to be used sequentially to identify the pre_processed values - * @param {Object} [params={}] - any additional protocol-specific parameters - * @return {promise} a promise that is resolved when preprocessing is completed, null if this is called by a party that is neither a compute nor receiver party - * @see {@link module:jiff-client~JIFFClient#executePreprocessing} - */ - jiffClient.preprocessing = function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, id_list, params) { - // defaults! - if (receivers_list == null) { - receivers_list = []; - for (var p = 1; p <= jiffClient.party_count; p++) { - receivers_list.push(p); - } - } else { - jiffClient.helpers.sort_ids(receivers_list); - } - if (compute_list == null) { - compute_list = []; - for (var c = 1; c <= jiffClient.party_count; c++) { - compute_list.push(c); - } - } else { - jiffClient.helpers.sort_ids(compute_list); - } - - // not a receiver nor a sender - if (receivers_list.indexOf(jiffClient.id) === -1 && compute_list.indexOf(jiffClient.id) === -1) { - return null; - } - - // more defaults - if (Zp == null) { - Zp = jiffClient.Zp; - } - if (threshold == null) { - threshold = receivers_list.length; - } - if (protocols == null) { - protocols = jiffClient.default_preprocessing_protocols; - } - - // actual preprocessing - if (count == null || count <= 0) { - count = 1; - } - if (params == null) { - params = {}; - } - if (params['namespace'] == null) { - params['namespace'] = jiffClient.extensions[jiffClient.extensions.length - 1]; - } - - // Create preprocessing tasks - var task = { - dependent_op : dependent_op, - count : count, - threshold : threshold, - receivers_list : receivers_list, - compute_list : compute_list, - Zp : Zp, - id_list : id_list, - id : null, - params : params, - protocols : protocols, - deferred: new jiffClient.helpers.Deferred() - }; - - preprocessingTasks[preprocessingTasks.length - 1].add(task); - - return task.deferred.promise; - }; - - /** - * Ask JIFF to start executing preprocessing for tasks previously added by {@link module:jiff-client~JIFFClient#preprocessing}. - * - * Calls the provided callback when the preprocessing tasks are all done. - * - * @method executePreprocessing - * @memberof module:jiff-client~JIFFClient - * @instance - * @param callback {!Function} - the callback to execute when preprocessing is finished. - * {@link module:jiff-client~JIFFClient#preprocessing} - */ - jiffClient.executePreprocessing = function (callback) { - userCallbacks.push(callback); - preprocessingTasks.push(linkedList()); - - if (!isRunning) { - __executePreprocessing(); - } - }; - - // called only when preprocessing can run RIGHT NOW - var __executePreprocessing = function () { - isRunning = true; - - jiffClient.currentPreprocessingTasks = preprocessingTasks.shift(); - var currentCallback = userCallbacks.shift(); - - jiffClient.preprocessingCallback = function () { - if (currentCallback != null) { - currentCallback.apply(null, currentCallback); - } - - if (userCallbacks.length > 0) { - __executePreprocessing(); - } else { - isRunning = false; - } - }; - - jiffClient.preprocessingDaemon(); - }; -}; +var linkedList = require('../../common/linkedlist.js'); + +module.exports = function (jiffClient) { + var isRunning = false; + var userCallbacks = []; + var preprocessingTasks = [linkedList()]; + + /** + * Checks if the given operation uses preprocessed values + * @method has_preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op - name of the operation to check + * @return {boolean} true if the op uses preprocessing, false otherwise + */ + jiffClient.has_preprocessing = function (op) { + for (var i = 0; i < jiffClient.extensions.length; i++) { + if (jiffClient.preprocessing_function_map[jiffClient.extensions[i]][op] != null) { + return true; + } + } + + return false; + }; + + /** + * Get a preprocessed share/value by associated op_id. If value does not exist + * Fallback to some user specified way for creating it + * @method get_preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op_id - the op_id associated with the preprocessed value/share + * @return {object} the preprocessed share(s) + */ + jiffClient.get_preprocessing = function (op_id) { + var values = jiffClient.preprocessing_table[op_id]; + if (values != null) { + return values; + } + if (jiffClient.crypto_provider === true) { + return null; + } + throw new Error('No preprocessed value(s) that correspond to the op_id "' + op_id + '"'); + }; + + /** + * Store a pair of op_id and associated pre-processed value/share + * The value/share can be accessed later during the computation through jiffClient.get_preprocessing(op_id) + * @method store_preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} op_id - the op_id associated with the preprocessed value/share + * @param {SecretShare} share - the share/value to store + */ + jiffClient.store_preprocessing = function (op_id, share) { + if (share != null) { + jiffClient.preprocessing_table[op_id] = share; + } + }; + + /** + * Generate values used for JIFF operations in advance of the computation. + * + * Calling this function does not begin preprocessing, it just creates a preprocessing task. After you created + * your desired tasks, you can ask JIFF to execute them via {@link module:jiff-client~JIFFClient#executePreprocessing}. + * + * @method preprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param {string} dependent_op - name of the operation that will later use the pre_processed values + * @param {Number} [count=1] - number of times the protocol should be performed, number of values that will be generated + * @param {Object} [protocols=defaults] - a mapping from base preprocessing elements ('beaver', 'bits', 'sampling') to functions that can pre-process them + * the function must implement the same interface as the JIFF provided protocols (e.g. jiffClient.protocols.generate_beaver_bgw), + * missing mappings indicate that JIFF must use the default protocols + * @param {Number} [threshold=receivers_list.length] - the threshold of the preprocessed shares + * @param {Array} [receivers_list=all_parties] - the parties that will receive the preprocsssed shares + * @param {Array} [compute_list=all_parties] - the parties that will compute the preprocsssed shares + * @param {Number} [Zp=jiffClient.Zp] - the Zp of the preprocessed shares + * @param {Array} [id_list=auto_gen()] - array of ids to be used sequentially to identify the pre_processed values + * @param {Object} [params={}] - any additional protocol-specific parameters + * @return {promise} a promise that is resolved when preprocessing is completed, null if this is called by a party that is neither a compute nor receiver party + * @see {@link module:jiff-client~JIFFClient#executePreprocessing} + */ + jiffClient.preprocessing = function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, id_list, params) { + // defaults! + if (receivers_list == null) { + receivers_list = []; + for (var p = 1; p <= jiffClient.party_count; p++) { + receivers_list.push(p); + } + } else { + jiffClient.helpers.sort_ids(receivers_list); + } + if (compute_list == null) { + compute_list = []; + for (var c = 1; c <= jiffClient.party_count; c++) { + compute_list.push(c); + } + } else { + jiffClient.helpers.sort_ids(compute_list); + } + + // not a receiver nor a sender + if (receivers_list.indexOf(jiffClient.id) === -1 && compute_list.indexOf(jiffClient.id) === -1) { + return null; + } + + // more defaults + if (Zp == null) { + Zp = jiffClient.Zp; + } + if (threshold == null) { + threshold = receivers_list.length; + } + if (protocols == null) { + protocols = jiffClient.default_preprocessing_protocols; + } + + // actual preprocessing + if (count == null || count <= 0) { + count = 1; + } + if (params == null) { + params = {}; + } + if (params['namespace'] == null) { + params['namespace'] = jiffClient.extensions[jiffClient.extensions.length - 1]; + } + + // Create preprocessing tasks + var task = { + dependent_op : dependent_op, + count : count, + threshold : threshold, + receivers_list : receivers_list, + compute_list : compute_list, + Zp : Zp, + id_list : id_list, + id : null, + params : params, + protocols : protocols, + deferred: new jiffClient.helpers.Deferred() + }; + + preprocessingTasks[preprocessingTasks.length - 1].add(task); + + return task.deferred.promise; + }; + + /** + * Ask JIFF to start executing preprocessing for tasks previously added by {@link module:jiff-client~JIFFClient#preprocessing}. + * + * Calls the provided callback when the preprocessing tasks are all done. + * + * @method executePreprocessing + * @memberof module:jiff-client~JIFFClient + * @instance + * @param callback {!Function} - the callback to execute when preprocessing is finished. + * {@link module:jiff-client~JIFFClient#preprocessing} + */ + jiffClient.executePreprocessing = function (callback) { + userCallbacks.push(callback); + preprocessingTasks.push(linkedList()); + + if (!isRunning) { + __executePreprocessing(); + } + }; + + // called only when preprocessing can run RIGHT NOW + var __executePreprocessing = function () { + isRunning = true; + + jiffClient.currentPreprocessingTasks = preprocessingTasks.shift(); + var currentCallback = userCallbacks.shift(); + + jiffClient.preprocessingCallback = function () { + if (currentCallback != null) { + currentCallback.apply(null, currentCallback); + } + + if (userCallbacks.length > 0) { + __executePreprocessing(); + } else { + isRunning = false; + } + }; + + jiffClient.preprocessingDaemon(); + }; +}; -},{"../../common/linkedlist.js":49}],18:[function(require,module,exports){ -module.exports = function (jiffClient) { - var linkedList = require('../../common/linkedlist.js'); - var currentBatchLoad = 0; - var suspendedTasks = 0; - - var getFirstTask = function (task) { - if (task.count > 1) { - var remainingTasks = Object.assign({}, task); - - var deferred1 = new jiffClient.helpers.Deferred(); - var deferred2 = new jiffClient.helpers.Deferred(); - Promise.all([deferred1.promise, deferred2.promise]).then(task.deferred.resolve); - task.deferred = deferred1; - remainingTasks.deferred = deferred2; - - remainingTasks.count--; - task.count = 1; - if (task.id_list != null) { - task.id = remainingTasks.id_list.shift(); - task.id_list = null; - } - jiffClient.currentPreprocessingTasks.pushHead(remainingTasks); - } - if (task.id_list != null) { - task.id = task.id_list[0]; - task.id_list = null; - } - return task; - }; - - var checkIfDone = function () { - if (currentBatchLoad === 0 && suspendedTasks === 0) { - var callback = jiffClient.preprocessingCallback; - jiffClient.preprocessingCallback = null; - callback(jiffClient); - } - }; - - var buildID = function (task) { - // Two kinds of operations: one that relies on different sets of senders and receivers, and one that has a set of holders - if (task.dependent_op === 'open' || task.dependent_op === 'bits.open') { // TODO: make this part of the description in table - var open_parties = task.params['open_parties'] != null ? task.params['open_parties'] : task.receivers_list; - task.id = jiffClient.counters.gen_op_id2_preprocessing(task.dependent_op, open_parties, task.receivers_list); - } else { - task.id = jiffClient.counters.gen_op_id_preprocessing(task.dependent_op, task.receivers_list); - } - }; - - var taskIsExecutable = function (task) { - // if the protocol name is in the map, it can be directly executed - var namespace = find_closest_namespace(task.dependent_op, task.params['namespace']); - return (namespace == null); - }; - - var find_closest_namespace = function (op, starting_namespace) { - var namespace_index = jiffClient.extensions.indexOf(starting_namespace); - while (namespace_index >= 0) { - var namespace = jiffClient.extensions[namespace_index]; - if (jiffClient.preprocessing_function_map[namespace] != null && jiffClient.preprocessing_function_map[namespace][op] != null) { - return namespace; - } - namespace_index--; - } - - return null; - }; - - // execute a task and handle it upon completion - var executeTask = function (task) { - currentBatchLoad++; - - var _params = Object.assign({}, task.params); - _params.output_op_id = task.id; - - var protocol = task.protocols[task.dependent_op] || jiffClient.default_preprocessing_protocols[task.dependent_op]; - var result = protocol(task.threshold, task.receivers_list, task.compute_list, task.Zp, _params, task.protocols); - - if (result.promise == null || result.promise.then == null) { - taskFinished(task, result); - } else { - result.promise.then(taskFinished.bind(null, task, result)); - } - }; - var taskFinished = function (task, result) { - currentBatchLoad--; - - if (task.receivers_list.indexOf(jiffClient.id) > -1) { - jiffClient.store_preprocessing(task.id, result.share); - } - task.deferred.resolve(); - jiffClient.preprocessingDaemon(); - }; - - // expand task by one level and replace the node in the task list - var expandTask = function (task) { - // copy of params - var _params = Object.assign({}, task.params); - - // Recursively follow jiffClient.preprocessing_function_map - // to figure out the sub-components/nested primitives of the given operation - // and pre-process those with the right op_ids. - - // ID should never be null - var namespace = find_closest_namespace(task.dependent_op, _params['namespace']); - var preprocessing_dependencies = jiffClient.preprocessing_function_map[namespace][task.dependent_op]; - - if (typeof(preprocessing_dependencies) === 'function') { - preprocessing_dependencies = preprocessing_dependencies(task.dependent_op, task.count, task.protocols, task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, _params, task, jiffClient); - } - - var newTasks = linkedList(); - var deferredChain = []; - // build linked list of new dependencies, afterwords merge them with current tasks list - for (var k = 0; k < preprocessing_dependencies.length; k++) { - var dependency = preprocessing_dependencies[k]; - var next_op = dependency['op']; - - // copy both the originally given extra_params and the extra params of the dependency and merge them - // together, dependency params overwrite duplicate keys. - // If params are ever needed in non-leaf operations, this must be changed to accommodate - var extra_params = Object.assign({}, _params, dependency['params']); - extra_params['namespace'] = dependency['namespace'] != null ? dependency['namespace'] : 'base'; - if (dependency.handler != null) { - extra_params = dependency.handler(task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, extra_params, task, jiffClient); - } - if (extra_params.ignore === true) { - continue; - } - - // compose ids similar to how the actual operation is implemented - var next_id_list = []; - var next_count = dependency['count']; - - if (next_count == null) { - next_count = 1; - next_id_list[0] = dependency['absolute_op_id'] || (task.id + dependency['op_id']); - } else { - next_count = next_count(task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, extra_params); - for (var j = 0; j < next_count; j++) { - next_id_list.push(dependency['absolute_op_id'] || (task.id + dependency['op_id'] + j)); - } - } - - var nextTask = { - dependent_op : next_op, - count : next_count, - threshold : dependency['threshold'] || task.threshold, - receivers_list : dependency['receivers_list'] || task.receivers_list, - compute_list : dependency['compute_list'] || task.compute_list, - Zp : dependency['Zp'] || task.Zp, - id_list : next_id_list, - id : null, - params : extra_params, - protocols : task.protocols, - deferred: new jiffClient.helpers.Deferred() - }; - - deferredChain.push(nextTask.deferred.promise); - if (dependency.requires != null) { - nextTask.wait = true; - var required_ops = []; - for (var r = 0; r < dependency.requires.length; r++) { - if (dependency.requires[r] >= k) { - throw new Error('Preprocessing dependency "' + next_op + '" in preprocessingMap for "' + task.dependent_op - + '" at namespace "' + namespace + '" cannot require subsequent dependency ' + dependency.requires[r]); - } - required_ops.push(deferredChain[dependency.requires[r]]); - } - - Promise.all(required_ops).then(function (nextTask) { - delete nextTask['wait']; - jiffClient.preprocessingDaemon(); - }.bind(null, nextTask)); - - // add waiting task to the tail of the queue - // jiffClient.currentPreprocessingTasks.add(nextTask); - newTasks.add(nextTask); - } else { - // non-waiting tasks are added to the head of the queue - newTasks.add(nextTask); - } - } - - Promise.all(deferredChain).then(task.deferred.resolve); - jiffClient.currentPreprocessingTasks = newTasks.extend(jiffClient.currentPreprocessingTasks); - }; - - /** - * Preprocessing Daemon that executes all currently scheduled preprocessing tasks (entries in jiffClient.currentPreprocessingTasks array) in order. - * @method preprocessingDaemon - * @memberof module:jiff-client~JIFFClient - * @instance - */ - jiffClient.preprocessingDaemon = function () { - while (currentBatchLoad < jiffClient.preprocessingBatchSize) { - var task = jiffClient.currentPreprocessingTasks.popHead(); - - if (task == null) { - checkIfDone(); - return; - } - - if (task.object.wait) { - jiffClient.currentPreprocessingTasks.pushHead(task.object); - break; - } - - task = getFirstTask(task.object); - if (task.id == null) { - buildID(task); - } - - // check if task is executable or no - if (taskIsExecutable(task)) { - executeTask(task); // co-recursively calls preprocessingDaemon() - } else { - //expand single task - expandTask(task); - } - } - }; -}; - -},{"../../common/linkedlist.js":49}],19:[function(require,module,exports){ -// internal functions for use in preprocessing function map -module.exports = { - bits_count: function (threshold, receivers_list, compute_list, Zp, op_id, params) { - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - return bitLength; - }, - constant_bits_count: function () { - return module.exports.bits_count.apply(null, arguments) - 1; - }, - dynamic_bits_cmult: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { - // constant bit length - var constantBits = Zp.toString(2).length; - if (params.constantBits != null) { - constantBits = params.constantBits; - } - // secret bit length - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - // for every bit from constant, pre-process for one bits.sadd of the right size - var ops = []; - for (var i = 0; i < constantBits; i++) { - var accLength = i === 0 ? 1 : (bitLength + i); - ops.push({ op: 'bits.sadd', op_id: ':bits.sadd:' + i, params: {bitLengthLeft: accLength, bitLengthRight: bitLength + i}}); - } - return ops; - }, - dynamic_bits_smult: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - - var left = params.bitLengthLeft; - var right = params.bitLengthRight; - left = left != null ? left : bitLength; - right = right != null ? right : bitLength; - var max = Math.max(left, right); - var min = Math.max(left, right); - - var ops = []; - for (var i = 0; i < min; i++) { - for (var j = 0; j < max + i; j++) { - ops.push({ op: 'if_else', op_id: ':if_else:' + i + ':' + j }); - } - var accLength = i === 0 ? min : (max + i); - ops.push({ op: 'bits.sadd', op_id: ':bits.sadd:'+i, params: {bitLengthLeft: accLength, bitLengthRight: max + i}}); - } - return ops; - }, - choice_bits_count: function (choice, offset) { - if (offset == null) { - offset = 0; - } - return function (threshold, receivers_list, compute_list, Zp, op_id, params) { - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - - var left = params.bitLengthLeft; - var right = params.bitLengthRight; - left = left != null ? left : bitLength; - right = right != null ? right : bitLength; - - return choice(left, right) + offset; - }; - }, - decomposition_ifelse_count: function (threshold, receivers_list, compute_list, Zp, op_id, params) { - return Zp.toString(2).length; - }, - dynamic_bits_sdiv: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - - var left = params.bitLengthLeft; - var right = params.bitLengthRight; - left = left != null ? left : bitLength; - right = right != null ? right : bitLength; - var min = Math.min(left, right); - - var ops = []; - for (var i = 0; i < left; i++) { - var accLength = Math.min(i+1, min+1); - ops.push({ op: 'bits.ssub', op_id: ':bits.ssub:'+i, params: {bitLengthLeft: accLength, bitLengthRight: right}}); - for (var j = 0; j < accLength; j++) { - ops.push({ op: 'if_else', op_id: ':if_else:' + i + ':' + j }); - } - } - return ops; - }, - dynamic_bits_cdiv: function (dir) { - return function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { - var constantBits = Zp.toString(2).length; - if (params.constantBits != null) { - constantBits = params.constantBits; - } - var bitLength = params.bitLength; - if (bitLength == null) { - bitLength = Zp.toString(2).length; - } - var min = Math.min(bitLength, constantBits); - - var ops = []; - var loopCounter = (dir === 'left') ? bitLength : constantBits; - for (var i = 0; i < loopCounter; i++) { - var accLength = Math.min(i + 1, min + 1); - if (dir === 'left') { - ops.push({ - op: 'bits.csubl', - op_id: ':bits.csubl:' + i, - params: {bitLength: accLength, constantBits: constantBits} - }); - } else { - ops.push({ - op: 'bits.ssub', - op_id: ':bits.ssub:' + i, - params: {bitLengthLeft: accLength, bitLengthRight: bitLength} - }); - } - - for (var j = 0; j < accLength; j++) { - ops.push({op: 'if_else', op_id: ':if_else:' + i + ':' + j}); - } - } - return ops; - } - }, - // rejection sampling - dynamic_rejection_sampling: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { - var previousPreprocessing = jiff.preprocessing_table[task.id]; - params.reject_count = params.reject_count == null ? -1 : params.reject_count; - - if (previousPreprocessing == null || previousPreprocessing === 'RETRY' || (previousPreprocessing[0] != null && previousPreprocessing[0].value === 'RETRY')) { - if (!params.defaultBounds && (params.lower_bound == null || params.upper_bound == null)) { - jiff.store_preprocessing(task.id, {ondemand: true}); - return []; - } - - var compute_threshold = params.compute_threshold; - if (compute_threshold == null) { // honest majority BGW - compute_threshold = Math.floor((compute_list.length + 1) / 2); - } - - var extra_params = {compute_threshold: compute_threshold}; - var reject_count = ++params.reject_count; - - Zp = Zp != null ? Zp : jiff.Zp; - params.lower_bound = params.lower_bound || 0; - params.upper_bound = params.upper_bound != null ? params.upper_bound : Zp; - - var range; - if (params.upper_bound.isBigNumber === true) { - range = params.upper_bound.minus(params.lower_bound); - } else { - range = params.upper_bound - params.lower_bound; - } - - // handle special cases - if (range.toString() === '0') { - throw new Error('rejection sampling preprocessing called with range 0, no numbers to sample!'); - } - if (range.toString() === '1') { - return [{op: 'sampling', op_id: '', params: extra_params}]; - } - - var bitLength = jiff.helpers.ceil(jiff.helpers.bLog(range, 2)); - bitLength = parseInt(bitLength.toString(), 10); - params.bitLength = bitLength; - - // fill in dependencies according to the lower and upper bounds - var dependent_ops = []; - var requires = []; - if (jiff.helpers.bLog(range, 2).toString().indexOf('.') > -1) { - dependent_ops = [ - {op: 'bits.clt', op_id: ':bits.clt:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list}, - {op: 'open', op_id: ':open:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list} - ]; - requires = [0, 1]; - } - - if (params.lower_bound.toString() !== '0' && bitLength > 1) { - dependent_ops.push({op: 'bits.cadd', op_id: ':bits.cadd:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list}); - requires.push(dependent_ops.length - 1); - } - - dependent_ops.push( - {op: 'sampling', op_id: '', requires: requires, params: extra_params}, - {op: 'rejection_sampling', op_id: '', requires: [dependent_ops.length]} - ); - - return dependent_ops; - } - - if (previousPreprocessing[0] != null && previousPreprocessing[0].value === 'PLACEHOLDER') { - delete jiff.preprocessing_table[task.id]; - } - - return []; - }, - // random quotients for cdiv - dynamic_random_and_quotient: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { - var constantNotProvided = (params.constant == null); - receivers_list = constantNotProvided ? compute_list : receivers_list; - Zp = Zp ? Zp : jiff.Zp; - - var newParams = {compute_threshold: params.compute_threshold}; - if (params.compute_threshold == null) { // honest majority BGW - newParams.compute_threshold = Math.floor((compute_list.length + 1) / 2); - } - threshold = newParams.compute_threshold; - - var dependent_ops = [ - {op: 'bits.cgteq', op_id: ':bits_cgteq', receivers_list: receivers_list, threshold: threshold, params: newParams}, - {op: 'if_else', op_id: ':ifelse1', receivers_list: receivers_list, threshold: threshold, params: newParams}, - {op: 'if_else', op_id: ':ifelse2', receivers_list: receivers_list, threshold: threshold, params: newParams}, - {op: 'rejection_sampling', op_id: ':rejection1', receivers_list: receivers_list, threshold: threshold, params: {lower_bound: 0, upper_bound: Zp, compute_threshold: threshold}} - ]; - - if (constantNotProvided) { - jiff.store_preprocessing(task_id, {ondemand: true}); - return dependent_ops; - } - - // we want to sample uniformly in [0, largest multiple of constant <= Zp) and [0, constant) - var largestQuotient = jiff.share_helpers['floor'](jiff.share_helpers['/'](Zp, params.constant)); - - dependent_ops.push( - {op: 'rejection_sampling', op_id: ':rejection2', threshold: threshold, params: {lower_bound: 0, upper_bound: largestQuotient, compute_threshold: threshold}}, - {op: 'rejection_sampling', op_id: ':rejection3', threshold: threshold, params: {lower_bound: 0, upper_bound: params.constant, compute_threshold: threshold}}, - {op: 'generate_random_and_quotient', op_id: '', requires: [0, 1, 2, 3, 4, 5], params: newParams} - ); - - return dependent_ops; - }, - // fast exponentiation - dynamic_fast_exponentiation: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { - Zp = Zp ? Zp : jiff.Zp; - var constantNotProvided = params.constant == null; - var constant = params.constant; - var constantBits = params.constantBits == null ? Zp.toString(2).length : params.constantBits; - - // special case - if (!constantNotProvided && constant.toString() === '0') { - return []; - } - - var ops = []; - if (constantNotProvided) { - for (var i = 0; i < constantBits-1; i++) { - ops.push({op: 'smult', op_id: ':smult0:' + i}); - ops.push({op: 'smult', op_id: ':smult1:' + i}); - } - ops.push({op: 'smult', op_id: ':smult0:' + i}); - return ops; - } - - // handle big number - if (jiff.helpers.BigNumber) { - constant = jiff.helpers.BigNumber(constant); - } +},{"../../common/linkedlist.js":53}],18:[function(require,module,exports){ +module.exports = function (jiffClient) { + var linkedList = require('../../common/linkedlist.js'); + var currentBatchLoad = 0; + var suspendedTasks = 0; + + var getFirstTask = function (task) { + if (task.count > 1) { + var remainingTasks = Object.assign({}, task); + + var deferred1 = new jiffClient.helpers.Deferred(); + var deferred2 = new jiffClient.helpers.Deferred(); + Promise.all([deferred1.promise, deferred2.promise]).then(task.deferred.resolve); + task.deferred = deferred1; + remainingTasks.deferred = deferred2; + + remainingTasks.count--; + task.count = 1; + if (task.id_list != null) { + task.id = remainingTasks.id_list.shift(); + task.id_list = null; + } + jiffClient.currentPreprocessingTasks.pushHead(remainingTasks); + } + if (task.id_list != null) { + task.id = task.id_list[0]; + task.id_list = null; + } + return task; + }; + + var checkIfDone = function () { + if (currentBatchLoad === 0 && suspendedTasks === 0) { + var callback = jiffClient.preprocessingCallback; + jiffClient.preprocessingCallback = null; + callback(jiffClient); + } + }; + + var buildID = function (task) { + // Two kinds of operations: one that relies on different sets of senders and receivers, and one that has a set of holders + if (task.dependent_op === 'open' || task.dependent_op === 'bits.open') { // TODO: make this part of the description in table + var open_parties = task.params['open_parties'] != null ? task.params['open_parties'] : task.receivers_list; + task.id = jiffClient.counters.gen_op_id2_preprocessing(task.dependent_op, open_parties, task.receivers_list); + } else { + task.id = jiffClient.counters.gen_op_id_preprocessing(task.dependent_op, task.receivers_list); + } + }; + + var taskIsExecutable = function (task) { + // if the protocol name is in the map, it can be directly executed + var namespace = find_closest_namespace(task.dependent_op, task.params['namespace']); + return (namespace == null); + }; + + var find_closest_namespace = function (op, starting_namespace) { + var namespace_index = jiffClient.extensions.indexOf(starting_namespace); + while (namespace_index >= 0) { + var namespace = jiffClient.extensions[namespace_index]; + if (jiffClient.preprocessing_function_map[namespace] != null && jiffClient.preprocessing_function_map[namespace][op] != null) { + return namespace; + } + namespace_index--; + } + + return null; + }; + + // execute a task and handle it upon completion + var executeTask = function (task) { + currentBatchLoad++; + + var _params = Object.assign({}, task.params); + _params.output_op_id = task.id; + + var protocol = task.protocols[task.dependent_op] || jiffClient.default_preprocessing_protocols[task.dependent_op]; + var result = protocol(task.threshold, task.receivers_list, task.compute_list, task.Zp, _params, task.protocols); + + if (result.promise == null || result.promise.then == null) { + taskFinished(task, result); + } else { + result.promise.then(taskFinished.bind(null, task, result)); + } + }; + var taskFinished = function (task, result) { + currentBatchLoad--; + + if (task.receivers_list.indexOf(jiffClient.id) > -1) { + jiffClient.store_preprocessing(task.id, result.share); + } + task.deferred.resolve(); + jiffClient.preprocessingDaemon(); + }; + + // expand task by one level and replace the node in the task list + var expandTask = function (task) { + // copy of params + var _params = Object.assign({}, task.params); + + // Recursively follow jiffClient.preprocessing_function_map + // to figure out the sub-components/nested primitives of the given operation + // and pre-process those with the right op_ids. + + // ID should never be null + var namespace = find_closest_namespace(task.dependent_op, _params['namespace']); + var preprocessing_dependencies = jiffClient.preprocessing_function_map[namespace][task.dependent_op]; + + if (typeof(preprocessing_dependencies) === 'function') { + preprocessing_dependencies = preprocessing_dependencies(task.dependent_op, task.count, task.protocols, task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, _params, task, jiffClient); + } + + var newTasks = linkedList(); + var deferredChain = []; + // build linked list of new dependencies, afterwords merge them with current tasks list + for (var k = 0; k < preprocessing_dependencies.length; k++) { + var dependency = preprocessing_dependencies[k]; + var next_op = dependency['op']; + + // copy both the originally given extra_params and the extra params of the dependency and merge them + // together, dependency params overwrite duplicate keys. + // If params are ever needed in non-leaf operations, this must be changed to accommodate + var extra_params = Object.assign({}, _params, dependency['params']); + extra_params['namespace'] = dependency['namespace'] != null ? dependency['namespace'] : 'base'; + if (dependency.handler != null) { + extra_params = dependency.handler(task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, extra_params, task, jiffClient); + } + if (extra_params.ignore === true) { + continue; + } + + // compose ids similar to how the actual operation is implemented + var next_id_list = []; + var next_count = dependency['count']; + + if (next_count == null) { + next_count = 1; + next_id_list[0] = dependency['absolute_op_id'] || (task.id + dependency['op_id']); + } else { + next_count = next_count(task.threshold, task.receivers_list, task.compute_list, task.Zp, task.id, extra_params); + for (var j = 0; j < next_count; j++) { + next_id_list.push(dependency['absolute_op_id'] || (task.id + dependency['op_id'] + j)); + } + } + + var nextTask = { + dependent_op : next_op, + count : next_count, + threshold : dependency['threshold'] || task.threshold, + receivers_list : dependency['receivers_list'] || task.receivers_list, + compute_list : dependency['compute_list'] || task.compute_list, + Zp : dependency['Zp'] || task.Zp, + id_list : next_id_list, + id : null, + params : extra_params, + protocols : task.protocols, + deferred: new jiffClient.helpers.Deferred() + }; + + deferredChain.push(nextTask.deferred.promise); + if (dependency.requires != null) { + nextTask.wait = true; + var required_ops = []; + for (var r = 0; r < dependency.requires.length; r++) { + if (dependency.requires[r] >= k) { + throw new Error('Preprocessing dependency "' + next_op + '" in preprocessingMap for "' + task.dependent_op + + '" at namespace "' + namespace + '" cannot require subsequent dependency ' + dependency.requires[r]); + } + required_ops.push(deferredChain[dependency.requires[r]]); + } + + Promise.all(required_ops).then(function (nextTask) { + delete nextTask['wait']; + jiffClient.preprocessingDaemon(); + }.bind(null, nextTask)); + + // add waiting task to the tail of the queue + // jiffClient.currentPreprocessingTasks.add(nextTask); + newTasks.add(nextTask); + } else { + // non-waiting tasks are added to the head of the queue + newTasks.add(nextTask); + } + } + + Promise.all(deferredChain).then(task.deferred.resolve); + jiffClient.currentPreprocessingTasks = newTasks.extend(jiffClient.currentPreprocessingTasks); + }; + + /** + * Preprocessing Daemon that executes all currently scheduled preprocessing tasks (entries in jiffClient.currentPreprocessingTasks array) in order. + * @method preprocessingDaemon + * @memberof module:jiff-client~JIFFClient + * @instance + */ + jiffClient.preprocessingDaemon = function () { + while (currentBatchLoad < jiffClient.preprocessingBatchSize) { + var task = jiffClient.currentPreprocessingTasks.popHead(); + + if (task == null) { + checkIfDone(); + return; + } + + if (task.object.wait) { + jiffClient.currentPreprocessingTasks.pushHead(task.object); + break; + } + + task = getFirstTask(task.object); + if (task.id == null) { + buildID(task); + } + + // check if task is executable or no + if (taskIsExecutable(task)) { + executeTask(task); // co-recursively calls preprocessingDaemon() + } else { + //expand single task + expandTask(task); + } + } + }; +}; - // preprocess for exactly the needed amount of multiplications - for (i = 0; jiff.share_helpers['<'](1, constant); i++) { - ops.push({op: 'smult', op_id: ':smult0:' + i}); - if (!jiff.share_helpers['even'](constant)) { - ops.push({op: 'smult', op_id: ':smult1:' + i}); - } - constant = jiff.share_helpers['floor'](jiff.share_helpers['/'](constant, 2)); - } - ops.push({op: 'smult', op_id: ':smult0:' + i}); - return ops; - }, - // for various equality tests, preprocess of cpow(Zp - 1) (Fermat's little theorem) - handler_cpow_Zp_minus_1: function (threshold, receivers_list, compute_list, Zp, op_id, params, task, jiff) { - Zp = Zp ? Zp : jiff.Zp; - params.constant = jiff.share_helpers['-'](Zp, 1); - return params; - } +},{"../../common/linkedlist.js":53}],19:[function(require,module,exports){ +// internal functions for use in preprocessing function map +module.exports = { + bits_count: function (threshold, receivers_list, compute_list, Zp, op_id, params) { + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + return bitLength; + }, + constant_bits_count: function () { + return module.exports.bits_count.apply(null, arguments) - 1; + }, + dynamic_bits_cmult: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { + // constant bit length + var constantBits = Zp.toString(2).length; + if (params.constantBits != null) { + constantBits = params.constantBits; + } + // secret bit length + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + // for every bit from constant, pre-process for one bits.sadd of the right size + var ops = []; + for (var i = 0; i < constantBits; i++) { + var accLength = i === 0 ? 1 : (bitLength + i); + ops.push({ op: 'bits.sadd', op_id: ':bits.sadd:' + i, params: {bitLengthLeft: accLength, bitLengthRight: bitLength + i}}); + } + return ops; + }, + dynamic_bits_smult: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + + var left = params.bitLengthLeft; + var right = params.bitLengthRight; + left = left != null ? left : bitLength; + right = right != null ? right : bitLength; + var max = Math.max(left, right); + var min = Math.max(left, right); + + var ops = []; + for (var i = 0; i < min; i++) { + for (var j = 0; j < max + i; j++) { + ops.push({ op: 'if_else', op_id: ':if_else:' + i + ':' + j }); + } + var accLength = i === 0 ? min : (max + i); + ops.push({ op: 'bits.sadd', op_id: ':bits.sadd:'+i, params: {bitLengthLeft: accLength, bitLengthRight: max + i}}); + } + return ops; + }, + choice_bits_count: function (choice, offset) { + if (offset == null) { + offset = 0; + } + return function (threshold, receivers_list, compute_list, Zp, op_id, params) { + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + + var left = params.bitLengthLeft; + var right = params.bitLengthRight; + left = left != null ? left : bitLength; + right = right != null ? right : bitLength; + + return choice(left, right) + offset; + }; + }, + decomposition_ifelse_count: function (threshold, receivers_list, compute_list, Zp, op_id, params) { + return Zp.toString(2).length; + }, + dynamic_bits_sdiv: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + + var left = params.bitLengthLeft; + var right = params.bitLengthRight; + left = left != null ? left : bitLength; + right = right != null ? right : bitLength; + var min = Math.min(left, right); + + var ops = []; + for (var i = 0; i < left; i++) { + var accLength = Math.min(i+1, min+1); + ops.push({ op: 'bits.ssub', op_id: ':bits.ssub:'+i, params: {bitLengthLeft: accLength, bitLengthRight: right}}); + for (var j = 0; j < accLength; j++) { + ops.push({ op: 'if_else', op_id: ':if_else:' + i + ':' + j }); + } + } + return ops; + }, + dynamic_bits_cdiv: function (dir) { + return function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params) { + var constantBits = Zp.toString(2).length; + if (params.constantBits != null) { + constantBits = params.constantBits; + } + var bitLength = params.bitLength; + if (bitLength == null) { + bitLength = Zp.toString(2).length; + } + var min = Math.min(bitLength, constantBits); + + var ops = []; + var loopCounter = (dir === 'left') ? bitLength : constantBits; + for (var i = 0; i < loopCounter; i++) { + var accLength = Math.min(i + 1, min + 1); + if (dir === 'left') { + ops.push({ + op: 'bits.csubl', + op_id: ':bits.csubl:' + i, + params: {bitLength: accLength, constantBits: constantBits} + }); + } else { + ops.push({ + op: 'bits.ssub', + op_id: ':bits.ssub:' + i, + params: {bitLengthLeft: accLength, bitLengthRight: bitLength} + }); + } + + for (var j = 0; j < accLength; j++) { + ops.push({op: 'if_else', op_id: ':if_else:' + i + ':' + j}); + } + } + return ops; + } + }, + // rejection sampling + dynamic_rejection_sampling: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { + var previousPreprocessing = jiff.preprocessing_table[task.id]; + params.reject_count = params.reject_count == null ? -1 : params.reject_count; + + if (previousPreprocessing == null || previousPreprocessing === 'RETRY' || (previousPreprocessing[0] != null && previousPreprocessing[0].value === 'RETRY')) { + if (!params.defaultBounds && (params.lower_bound == null || params.upper_bound == null)) { + jiff.store_preprocessing(task.id, {ondemand: true}); + return []; + } + + var compute_threshold = params.compute_threshold; + if (compute_threshold == null) { // honest majority BGW + compute_threshold = Math.floor((compute_list.length + 1) / 2); + } + + var extra_params = {compute_threshold: compute_threshold}; + var reject_count = ++params.reject_count; + + Zp = Zp != null ? Zp : jiff.Zp; + params.lower_bound = params.lower_bound || 0; + params.upper_bound = params.upper_bound != null ? params.upper_bound : Zp; + + var range; + if (params.upper_bound.isBigNumber === true) { + range = params.upper_bound.minus(params.lower_bound); + } else { + range = params.upper_bound - params.lower_bound; + } + + // handle special cases + if (range.toString() === '0') { + throw new Error('rejection sampling preprocessing called with range 0, no numbers to sample!'); + } + if (range.toString() === '1') { + return [{op: 'sampling', op_id: '', params: extra_params}]; + } + + var bitLength = jiff.helpers.ceil(jiff.helpers.bLog(range, 2)); + bitLength = parseInt(bitLength.toString(), 10); + params.bitLength = bitLength; + + // fill in dependencies according to the lower and upper bounds + var dependent_ops = []; + var requires = []; + if (jiff.helpers.bLog(range, 2).toString().indexOf('.') > -1) { + dependent_ops = [ + {op: 'bits.clt', op_id: ':bits.clt:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list}, + {op: 'open', op_id: ':open:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list} + ]; + requires = [0, 1]; + } + + if (params.lower_bound.toString() !== '0' && bitLength > 1) { + dependent_ops.push({op: 'bits.cadd', op_id: ':bits.cadd:' + reject_count, params: extra_params, threshold: compute_threshold, receivers_list: compute_list}); + requires.push(dependent_ops.length - 1); + } + + dependent_ops.push( + {op: 'sampling', op_id: '', requires: requires, params: extra_params}, + {op: 'rejection_sampling', op_id: '', requires: [dependent_ops.length]} + ); + + return dependent_ops; + } + + if (previousPreprocessing[0] != null && previousPreprocessing[0].value === 'PLACEHOLDER') { + delete jiff.preprocessing_table[task.id]; + } + + return []; + }, + // random quotients for cdiv + dynamic_random_and_quotient: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { + var constantNotProvided = (params.constant == null); + receivers_list = constantNotProvided ? compute_list : receivers_list; + Zp = Zp ? Zp : jiff.Zp; + + var newParams = {compute_threshold: params.compute_threshold}; + if (params.compute_threshold == null) { // honest majority BGW + newParams.compute_threshold = Math.floor((compute_list.length + 1) / 2); + } + threshold = newParams.compute_threshold; + + var dependent_ops = [ + {op: 'bits.cgteq', op_id: ':bits_cgteq', receivers_list: receivers_list, threshold: threshold, params: newParams}, + {op: 'if_else', op_id: ':ifelse1', receivers_list: receivers_list, threshold: threshold, params: newParams}, + {op: 'if_else', op_id: ':ifelse2', receivers_list: receivers_list, threshold: threshold, params: newParams}, + {op: 'rejection_sampling', op_id: ':rejection1', receivers_list: receivers_list, threshold: threshold, params: {lower_bound: 0, upper_bound: Zp, compute_threshold: threshold}} + ]; + + if (constantNotProvided) { + jiff.store_preprocessing(task_id, {ondemand: true}); + return dependent_ops; + } + + // we want to sample uniformly in [0, largest multiple of constant <= Zp) and [0, constant) + var largestQuotient = jiff.share_helpers['floor'](jiff.share_helpers['/'](Zp, params.constant)); + + dependent_ops.push( + {op: 'rejection_sampling', op_id: ':rejection2', threshold: threshold, params: {lower_bound: 0, upper_bound: largestQuotient, compute_threshold: threshold}}, + {op: 'rejection_sampling', op_id: ':rejection3', threshold: threshold, params: {lower_bound: 0, upper_bound: params.constant, compute_threshold: threshold}}, + {op: 'generate_random_and_quotient', op_id: '', requires: [0, 1, 2, 3, 4, 5], params: newParams} + ); + + return dependent_ops; + }, + // fast exponentiation + dynamic_fast_exponentiation: function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, task_id, params, task, jiff) { + Zp = Zp ? Zp : jiff.Zp; + var constantNotProvided = params.constant == null; + var constant = params.constant; + var constantBits = params.constantBits == null ? Zp.toString(2).length : params.constantBits; + + // special case + if (!constantNotProvided && constant.toString() === '0') { + return []; + } + + var ops = []; + if (constantNotProvided) { + for (var i = 0; i < constantBits-1; i++) { + ops.push({op: 'smult', op_id: ':smult0:' + i}); + ops.push({op: 'smult', op_id: ':smult1:' + i}); + } + ops.push({op: 'smult', op_id: ':smult0:' + i}); + return ops; + } + + // handle big number + if (jiff.helpers.BigNumber) { + constant = jiff.helpers.BigNumber(constant); + } + + // preprocess for exactly the needed amount of multiplications + for (i = 0; jiff.share_helpers['<'](1, constant); i++) { + ops.push({op: 'smult', op_id: ':smult0:' + i}); + if (!jiff.share_helpers['even'](constant)) { + ops.push({op: 'smult', op_id: ':smult1:' + i}); + } + constant = jiff.share_helpers['floor'](jiff.share_helpers['/'](constant, 2)); + } + ops.push({op: 'smult', op_id: ':smult0:' + i}); + return ops; + }, + // for various equality tests, preprocess of cpow(Zp - 1) (Fermat's little theorem) + handler_cpow_Zp_minus_1: function (threshold, receivers_list, compute_list, Zp, op_id, params, task, jiff) { + Zp = Zp ? Zp : jiff.Zp; + params.constant = jiff.share_helpers['-'](Zp, 1); + return params; + } }; },{}],20:[function(require,module,exports){ -module.exports = function (jiffClient) { - var handlers = require('./handlers.js'); - - jiffClient.default_preprocessing_protocols = { - generate_beaver: jiffClient.protocols.generate_beaver_bgw, - generate_random_number: jiffClient.protocols.generate_random_number, - sampling: jiffClient.protocols.rejection_sampling, - generate_random_bits: jiffClient.protocols.generate_random_bits, - generate_random_bit: jiffClient.protocols.generate_random_bit_bgw, - generate_zero: jiffClient.protocols.generate_zero, - generate_random_and_quotient: jiffClient.protocols.generate_random_and_quotient - }; - - jiffClient.preprocessing_function_map = { - base: { - // arithmetic sharing protocols - 'smult': [ - {op: 'open', op_id: ':open1'}, - {op: 'generate_beaver', op_id: ':triplet'}, - {op: 'open', op_id: ':open2'} - ], - 'sxor_bit': [ - {op: 'smult', op_id: ':smult1'} - ], - 'slt': [ - {op: 'lt_halfprime', op_id: ':halfprime:1'}, - {op: 'lt_halfprime', op_id: ':halfprime:2'}, - {op: 'lt_halfprime', op_id: ':halfprime:3'}, - {op: 'smult', op_id: ':smult1'}, - {op: 'smult', op_id: ':smult2'} - ], - 'cgt': [ - {op: 'lt_halfprime', op_id: ':halfprime:1'}, - {op: 'lt_halfprime', op_id: ':halfprime:2'}, - {op: 'smult', op_id: ':smult1'} - ], - 'clt': [ - {op: 'lt_halfprime', op_id: ':halfprime:1'}, - {op: 'lt_halfprime', op_id: ':halfprime:2'}, - {op: 'smult', op_id: ':smult1'} - ], - 'lt_halfprime': [ - {op: 'rejection_sampling', op_id: ':sampling', params: {defaultBounds: true}}, - {op: 'smult', op_id: ':smult1'}, - {op: 'bits.cgt', op_id: ':bits.cgt'}, - {op: 'sxor_bit', op_id: ':sxor_bit'}, - {op: 'open', op_id: ':open'} - ], - 'cneq': [ - {op: 'cpow', op_id: ':cpow', handler: handlers.handler_cpow_Zp_minus_1} - ], - 'cpow': handlers.dynamic_fast_exponentiation, - 'cdiv': [ - {op: 'cgt', op_id: ':wrap_cgt'}, - {op: 'cgteq', op_id: ':cor1'}, - {op: 'cgteq', op_id: ':cor2'}, - {op: 'smult', op_id: ':smult'}, - {op: 'clt', op_id: ':zero_check'}, - {op: 'smult', op_id: ':zero_it'}, - {op: 'open', op_id: ':open'}, - {op: 'quotient', op_id: ':quotient'} - ], - 'sdiv': [ - {op: 'bit_decomposition', op_id: ':decomposition1'}, - {op: 'bit_decomposition', op_id: ':decomposition2'}, - {op: 'bits.sdiv', op_id: ':bits.sdiv'} - ], - 'if_else': [ - {op: 'smult', op_id: ':smult'} - ], - // bits protocols - 'bit_decomposition': [ - {op: 'rejection_sampling', op_id: ':sampling', params: {defaultBounds: true}}, - {op: 'bits.csubr', op_id: ':bits.csubr:1'}, - {op: 'bits.csubr', op_id: ':bits.csubr:2'}, - {op: 'if_else', op_id: ':if_else:', count: handlers.decomposition_ifelse_count}, - {op: 'open', op_id: ':open'} - ], - // comparisons - 'bits.cgteq': [ - {op: 'smult', op_id: ':smult:', count: handlers.constant_bits_count} - ], - 'bits.cneq': [ - {op: 'sor_bit', op_id: ':sor_bit:', count: handlers.constant_bits_count} - ], - 'bits.sneq': [ - {op: 'sxor_bit', op_id: ':sxor_bit:initial'}, - {op: 'sxor_bit', op_id: ':sxor_bit:', count: handlers.choice_bits_count(Math.min, -1)}, - {op: 'sor_bit', op_id: ':sor_bit:', count: handlers.choice_bits_count(Math.max, -1)} - ], - 'bits.sgteq': [ - {op: 'smult', op_id: ':smult:initial'}, - {op: 'smult', op_id: ':smult1:', count: handlers.choice_bits_count(Math.max, -1)}, - {op: 'sxor_bit', op_id: ':sxor_bit1:', count: handlers.choice_bits_count(Math.min, -1)}, - {op: 'smult', op_id: ':smult2:', count: handlers.choice_bits_count(Math.min, -1)} - ], - 'bits.sgt': [ - {op: 'bits.sgteq', op_id: ':bits.sgteq'}, - {op: 'bits.sneq', op_id: ':bits.sneq'}, - {op: 'smult', op_id: ':smult'} - ], - // constant arithmetic - 'bits.cadd': [ - {op: 'smult', op_id: ':smult:', count: handlers.constant_bits_count}, - {op: 'sxor_bit', op_id: ':sxor_bit:', count: handlers.constant_bits_count} - ], - 'bits.cmult': handlers.dynamic_bits_cmult, - 'bits.cdivl': handlers.dynamic_bits_cdiv('left'), - 'bits.cdivr': handlers.dynamic_bits_cdiv('right'), - // secret arithmetic - 'bits.sadd': [ - {op: 'sxor_bit', op_id: ':sxor_bit:initial'}, - {op: 'smult', op_id: ':smult:initial'}, - {op: 'smult', op_id: ':smult1:', count: handlers.choice_bits_count(Math.max, -1)}, - {op: 'sxor_bit', op_id: ':sxor_bit1:', count: handlers.choice_bits_count(Math.max, -1)}, - {op: 'smult', op_id: ':smult2:', count: handlers.choice_bits_count(Math.min, -1)}, - {op: 'sxor_bit', op_id: ':sxor_bit2:', count: handlers.choice_bits_count(Math.min, -1)} - ], - 'bits.smult': handlers.dynamic_bits_smult, - 'bits.sdiv': handlers.dynamic_bits_sdiv, - 'bits.open': [ - {op: 'open', op_id: ':', count: handlers.bits_count} - ], - // refresh/open - 'refresh': [ - {op: 'generate_zero', op_id: ''} - ], - 'open': [ - {op: 'refresh', op_id: ':refresh'} - ], - // generating a random number and its quotient / constant - 'quotient': handlers.dynamic_random_and_quotient, - // rejection sampling - 'rejection_sampling': handlers.dynamic_rejection_sampling - } - }; - - // arithmetic protocols - jiffClient.preprocessing_function_map['base']['sor_bit'] = jiffClient.preprocessing_function_map['base']['sxor_bit']; - jiffClient.preprocessing_function_map['base']['smod'] = jiffClient.preprocessing_function_map['base']['sdiv']; - jiffClient.preprocessing_function_map['base']['slteq'] = jiffClient.preprocessing_function_map['base']['slt']; - jiffClient.preprocessing_function_map['base']['sgteq'] = jiffClient.preprocessing_function_map['base']['slt']; - jiffClient.preprocessing_function_map['base']['sgt'] = jiffClient.preprocessing_function_map['base']['slt']; - jiffClient.preprocessing_function_map['base']['clteq'] = jiffClient.preprocessing_function_map['base']['cgt']; - jiffClient.preprocessing_function_map['base']['cgteq'] = jiffClient.preprocessing_function_map['base']['clt']; - jiffClient.preprocessing_function_map['base']['seq'] = jiffClient.preprocessing_function_map['base']['cneq']; - jiffClient.preprocessing_function_map['base']['sneq'] = jiffClient.preprocessing_function_map['base']['cneq']; - jiffClient.preprocessing_function_map['base']['ceq'] = jiffClient.preprocessing_function_map['base']['cneq']; - - // bits protocols - jiffClient.preprocessing_function_map['base']['bits.clt'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; - jiffClient.preprocessing_function_map['base']['bits.clteq'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; - jiffClient.preprocessing_function_map['base']['bits.cgt'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; - jiffClient.preprocessing_function_map['base']['bits.ceq'] = jiffClient.preprocessing_function_map['base']['bits.cneq']; - jiffClient.preprocessing_function_map['base']['bits.slt'] = jiffClient.preprocessing_function_map['base']['bits.sgteq']; - jiffClient.preprocessing_function_map['base']['bits.slteq'] = jiffClient.preprocessing_function_map['base']['bits.sgt']; - jiffClient.preprocessing_function_map['base']['bits.seq'] = jiffClient.preprocessing_function_map['base']['bits.sneq']; - jiffClient.preprocessing_function_map['base']['bits.csubl'] = jiffClient.preprocessing_function_map['base']['bits.cadd']; - jiffClient.preprocessing_function_map['base']['bits.csubr'] = jiffClient.preprocessing_function_map['base']['bits.cadd']; - jiffClient.preprocessing_function_map['base']['bits.ssub'] = jiffClient.preprocessing_function_map['base']['bits.sadd']; -}; +module.exports = function (jiffClient) { + var handlers = require('./handlers.js'); + + jiffClient.default_preprocessing_protocols = { + generate_beaver: jiffClient.protocols.generate_beaver_bgw, + generate_random_number: jiffClient.protocols.generate_random_number, + sampling: jiffClient.protocols.rejection_sampling, + generate_random_bits: jiffClient.protocols.generate_random_bits, + generate_random_bit: jiffClient.protocols.generate_random_bit_bgw, + generate_zero: jiffClient.protocols.generate_zero, + generate_random_and_quotient: jiffClient.protocols.generate_random_and_quotient + }; + + jiffClient.preprocessing_function_map = { + base: { + // arithmetic sharing protocols + 'smult': [ + {op: 'open', op_id: ':open1'}, + {op: 'generate_beaver', op_id: ':triplet'}, + {op: 'open', op_id: ':open2'} + ], + 'sxor_bit': [ + {op: 'smult', op_id: ':smult1'} + ], + 'slt': [ + {op: 'lt_halfprime', op_id: ':halfprime:1'}, + {op: 'lt_halfprime', op_id: ':halfprime:2'}, + {op: 'lt_halfprime', op_id: ':halfprime:3'}, + {op: 'smult', op_id: ':smult1'}, + {op: 'smult', op_id: ':smult2'} + ], + 'cgt': [ + {op: 'lt_halfprime', op_id: ':halfprime:1'}, + {op: 'lt_halfprime', op_id: ':halfprime:2'}, + {op: 'smult', op_id: ':smult1'} + ], + 'clt': [ + {op: 'lt_halfprime', op_id: ':halfprime:1'}, + {op: 'lt_halfprime', op_id: ':halfprime:2'}, + {op: 'smult', op_id: ':smult1'} + ], + 'lt_halfprime': [ + {op: 'rejection_sampling', op_id: ':sampling', params: {defaultBounds: true}}, + {op: 'smult', op_id: ':smult1'}, + {op: 'bits.cgt', op_id: ':bits.cgt'}, + {op: 'sxor_bit', op_id: ':sxor_bit'}, + {op: 'open', op_id: ':open'} + ], + 'cneq': [ + {op: 'cpow', op_id: ':cpow', handler: handlers.handler_cpow_Zp_minus_1} + ], + 'cpow': handlers.dynamic_fast_exponentiation, + 'cdiv': [ + {op: 'cgt', op_id: ':wrap_cgt'}, + {op: 'cgteq', op_id: ':cor1'}, + {op: 'cgteq', op_id: ':cor2'}, + {op: 'smult', op_id: ':smult'}, + {op: 'clt', op_id: ':zero_check'}, + {op: 'smult', op_id: ':zero_it'}, + {op: 'open', op_id: ':open'}, + {op: 'quotient', op_id: ':quotient'} + ], + 'sdiv': [ + {op: 'bit_decomposition', op_id: ':decomposition1'}, + {op: 'bit_decomposition', op_id: ':decomposition2'}, + {op: 'bits.sdiv', op_id: ':bits.sdiv'} + ], + 'if_else': [ + {op: 'smult', op_id: ':smult'} + ], + // bits protocols + 'bit_decomposition': [ + {op: 'rejection_sampling', op_id: ':sampling', params: {defaultBounds: true}}, + {op: 'bits.csubr', op_id: ':bits.csubr:1'}, + {op: 'bits.csubr', op_id: ':bits.csubr:2'}, + {op: 'if_else', op_id: ':if_else:', count: handlers.decomposition_ifelse_count}, + {op: 'open', op_id: ':open'} + ], + // comparisons + 'bits.cgteq': [ + {op: 'smult', op_id: ':smult:', count: handlers.constant_bits_count} + ], + 'bits.cneq': [ + {op: 'sor_bit', op_id: ':sor_bit:', count: handlers.constant_bits_count} + ], + 'bits.sneq': [ + {op: 'sxor_bit', op_id: ':sxor_bit:initial'}, + {op: 'sxor_bit', op_id: ':sxor_bit:', count: handlers.choice_bits_count(Math.min, -1)}, + {op: 'sor_bit', op_id: ':sor_bit:', count: handlers.choice_bits_count(Math.max, -1)} + ], + 'bits.sgteq': [ + {op: 'smult', op_id: ':smult:initial'}, + {op: 'smult', op_id: ':smult1:', count: handlers.choice_bits_count(Math.max, -1)}, + {op: 'sxor_bit', op_id: ':sxor_bit1:', count: handlers.choice_bits_count(Math.min, -1)}, + {op: 'smult', op_id: ':smult2:', count: handlers.choice_bits_count(Math.min, -1)} + ], + 'bits.sgt': [ + {op: 'bits.sgteq', op_id: ':bits.sgteq'}, + {op: 'bits.sneq', op_id: ':bits.sneq'}, + {op: 'smult', op_id: ':smult'} + ], + // constant arithmetic + 'bits.cadd': [ + {op: 'smult', op_id: ':smult:', count: handlers.constant_bits_count}, + {op: 'sxor_bit', op_id: ':sxor_bit:', count: handlers.constant_bits_count} + ], + 'bits.cmult': handlers.dynamic_bits_cmult, + 'bits.cdivl': handlers.dynamic_bits_cdiv('left'), + 'bits.cdivr': handlers.dynamic_bits_cdiv('right'), + // secret arithmetic + 'bits.sadd': [ + {op: 'sxor_bit', op_id: ':sxor_bit:initial'}, + {op: 'smult', op_id: ':smult:initial'}, + {op: 'smult', op_id: ':smult1:', count: handlers.choice_bits_count(Math.max, -1)}, + {op: 'sxor_bit', op_id: ':sxor_bit1:', count: handlers.choice_bits_count(Math.max, -1)}, + {op: 'smult', op_id: ':smult2:', count: handlers.choice_bits_count(Math.min, -1)}, + {op: 'sxor_bit', op_id: ':sxor_bit2:', count: handlers.choice_bits_count(Math.min, -1)} + ], + 'bits.smult': handlers.dynamic_bits_smult, + 'bits.sdiv': handlers.dynamic_bits_sdiv, + 'bits.open': [ + {op: 'open', op_id: ':', count: handlers.bits_count} + ], + // refresh/open + 'refresh': [ + {op: 'generate_zero', op_id: ''} + ], + 'open': [ + {op: 'refresh', op_id: ':refresh'} + ], + // generating a random number and its quotient / constant + 'quotient': handlers.dynamic_random_and_quotient, + // rejection sampling + 'rejection_sampling': handlers.dynamic_rejection_sampling + } + }; + + // arithmetic protocols + jiffClient.preprocessing_function_map['base']['sor_bit'] = jiffClient.preprocessing_function_map['base']['sxor_bit']; + jiffClient.preprocessing_function_map['base']['smod'] = jiffClient.preprocessing_function_map['base']['sdiv']; + jiffClient.preprocessing_function_map['base']['slteq'] = jiffClient.preprocessing_function_map['base']['slt']; + jiffClient.preprocessing_function_map['base']['sgteq'] = jiffClient.preprocessing_function_map['base']['slt']; + jiffClient.preprocessing_function_map['base']['sgt'] = jiffClient.preprocessing_function_map['base']['slt']; + jiffClient.preprocessing_function_map['base']['clteq'] = jiffClient.preprocessing_function_map['base']['cgt']; + jiffClient.preprocessing_function_map['base']['cgteq'] = jiffClient.preprocessing_function_map['base']['clt']; + jiffClient.preprocessing_function_map['base']['seq'] = jiffClient.preprocessing_function_map['base']['cneq']; + jiffClient.preprocessing_function_map['base']['sneq'] = jiffClient.preprocessing_function_map['base']['cneq']; + jiffClient.preprocessing_function_map['base']['ceq'] = jiffClient.preprocessing_function_map['base']['cneq']; + + // bits protocols + jiffClient.preprocessing_function_map['base']['bits.clt'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; + jiffClient.preprocessing_function_map['base']['bits.clteq'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; + jiffClient.preprocessing_function_map['base']['bits.cgt'] = jiffClient.preprocessing_function_map['base']['bits.cgteq']; + jiffClient.preprocessing_function_map['base']['bits.ceq'] = jiffClient.preprocessing_function_map['base']['bits.cneq']; + jiffClient.preprocessing_function_map['base']['bits.slt'] = jiffClient.preprocessing_function_map['base']['bits.sgteq']; + jiffClient.preprocessing_function_map['base']['bits.slteq'] = jiffClient.preprocessing_function_map['base']['bits.sgt']; + jiffClient.preprocessing_function_map['base']['bits.seq'] = jiffClient.preprocessing_function_map['base']['bits.sneq']; + jiffClient.preprocessing_function_map['base']['bits.csubl'] = jiffClient.preprocessing_function_map['base']['bits.cadd']; + jiffClient.preprocessing_function_map['base']['bits.csubr'] = jiffClient.preprocessing_function_map['base']['bits.cadd']; + jiffClient.preprocessing_function_map['base']['bits.ssub'] = jiffClient.preprocessing_function_map['base']['bits.sadd']; +}; },{"./handlers.js":19}],21:[function(require,module,exports){ -module.exports = { - /** - * Share an array of values. Each sender may have an array of different length. This is handled by the lengths parameter. - * This function will reveal the lengths of the shared array - * - * If parties would like to keep the lengths of their arrays secret, they should agree on some "max" length apriori (either under MPC - * or as part of the logistics of the computation), all their arrays should be padded to that length by using appropriate default/identity - * values - * @function jiff_share_array - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. - * @param {Array} array - the array to be shared. - * @param {null|number|object} lengths - the lengths of the arrays to be shared, has the following options: - * 1. null: lengths are unknown, each sender will publicly reveal the lengths of its own array. - * 2. number: all arrays are of this length - * 3. object: { : length }: must specify the length of the array for each sender. - * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. - * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. - * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. - * @param {number} [Zp=jiff.Zp] - the mod. - * @param {string|number} [share_id=auto_gen()] - the base tag used to tag the messages sent by this share operation, every element of the array - * will get a unique id based on the concatenation of base_share_id and the index of the element. - * This tag is used so that parties distinguish messages belonging to this share operation from - * other share operations between the same parties (when the order of execution is not - * deterministic). An automatic id is generated by increasing a local counter, default - * ids suffice when all parties execute all sharing operations with the same senders - * and receivers in the same order. - * @return {promise} if the calling party is a receiver then a promise to the shared arrays is returned, the promise will provide an object - * formatted as follows: { : [ <1st_share>, <2nd_share>, ..., <(lengths[party_id])th_share> ] } - * where the party_ids are those of the senders. - * if the calling party is not a receiver, then null is returned. - */ - jiff_share_array: function (jiff, array, lengths, threshold, receivers_list, senders_list, Zp, share_id) { - var i; - - // Check format of lengths - if (lengths != null && typeof(lengths) !== 'number' && typeof(lengths) !== 'object') { - throw new Error('share_array: unrecognized lengths'); - } - - // Default values - if (receivers_list == null) { - receivers_list = []; - for (i = 1; i <= jiff.party_count; i++) { - receivers_list.push(i); - } - } else { - jiff.helpers.sort_ids(receivers_list); - } - if (senders_list == null) { - senders_list = []; - for (i = 1; i <= jiff.party_count; i++) { - senders_list.push(i); - } - } else { - jiff.helpers.sort_ids(senders_list); - } - - var isReceiving = receivers_list.indexOf(jiff.id) > -1; - if (senders_list.indexOf(jiff.id) === -1 && !isReceiving) { - return null; - } // This party is neither a sender nor a receiver, do nothing! - - // compute operation id - if (share_id == null) { - share_id = jiff.counters.gen_op_id2('share_array', receivers_list, senders_list); - } - - // wrap around result of share_array - var share_array_deferred = new jiff.helpers.Deferred(); - var share_array_promise = share_array_deferred.promise; - - // figure out lengths by having each party emit their length publicly - if (lengths == null) { - lengths = {}; - var total = 0; - if (senders_list.indexOf(jiff.id) > -1) { - lengths[jiff.id] = array.length; - - // send the length of this party's array to all receivers - jiff.emit(share_id + 'length', receivers_list, array.length.toString(10)); - } - - jiff.listen(share_id + 'length', function (sender, message) { - lengths[sender] = parseInt(message, 10); - total++; - if (total === senders_list.length) { - jiff.remove_listener(share_id + 'length'); - share_array_deferred.resolve(lengths); - } - }); - } else if (typeof(lengths) === 'number') { - // All arrays are of the same length - var l = lengths; - lengths = {}; - for (i = 0; i < senders_list.length; i++) { - lengths[senders_list[i]] = l; - } - - share_array_deferred.resolve(lengths); - } else { - // Lengths of the different arrays are all provided - for (i = 0; i < senders_list.length; i++) { - if (lengths[senders_list[i]] == null) { - throw new Error('share_array: missing length'); - } - } - - share_array_deferred.resolve(lengths); - } - - // lengths are now set, start sharing - share_array_promise = share_array_promise.then(function (lengths) { - // compute the number of sharing rounds - var max = 0; - for (i = 0; i < senders_list.length; i++) { - var l = lengths[senders_list[i]]; - max = l > max ? l : max; - } - - // Store results here - var results = {}; - if (isReceiving) { - for (i = 0; i < senders_list.length; i++) { - results[senders_list[i]] = []; - } - } - - // share every round - for (var r = 0; r < max; r++) { - var round_senders = []; - for (i = 0; i < senders_list.length; i++) { - if (lengths[senders_list[i]] > r) { - round_senders.push(senders_list[i]); - } - } - - var value = (senders_list.indexOf(jiff.id) > -1) && (r < array.length) ? array[r] : null; - var round_results = jiff.share(value, threshold, receivers_list, round_senders, Zp, share_id + 'round:' + r); - - for (var sender_id in round_results) { - if (round_results.hasOwnProperty(sender_id)) { - results[sender_id].push(round_results[sender_id]); - } - } - } - - return results; - }); - - return isReceiving ? share_array_promise : null; - }, - - /** - * Opens a bunch of secret shares. - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. - * @param {module:jiff-client~JIFFClient#SecretShare[]} shares - an array containing this party's shares of the secrets to reconstruct. - * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties. - * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open - * @returns {?promise} a (JQuery) promise to ALL the open values of the secret, the promise will yield - * an array of values matching the corresponding given secret share by index, if the calling - * party is not a receiver, null is returned - */ - jiff_open_array: function (jiff, shares, parties, op_id) { - // Default values - if (parties == null) { - parties = []; - for (i = 1; i <= jiff.party_count; i++) { - parties.push(i); - } - } else { - jiff.helpers.sort_ids(parties); - } - - // Compute operation ids (one for each party that will receive a result - if (op_id == null) { - op_id = jiff.counters.gen_op_id2('open_array', parties, shares[0].holders); - } - - var promises = []; - for (var i = 0; i < shares.length; i++) { - var promise = jiff.open(shares[i], parties, op_id + ':' + i); - if (promise != null) { - promises.push(promise); - } - } - - if (promises.length === 0) { - return null; - } - - return Promise.all(promises); - } +module.exports = { + /** + * Share an array of values. Each sender may have an array of different length. This is handled by the lengths parameter. + * This function will reveal the lengths of the shared array + * + * If parties would like to keep the lengths of their arrays secret, they should agree on some "max" length apriori (either under MPC + * or as part of the logistics of the computation), all their arrays should be padded to that length by using appropriate default/identity + * values + * @function jiff_share_array + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. + * @param {Array} array - the array to be shared. + * @param {null|number|object} lengths - the lengths of the arrays to be shared, has the following options: + * 1. null: lengths are unknown, each sender will publicly reveal the lengths of its own array. + * 2. number: all arrays are of this length + * 3. object: { : length }: must specify the length of the array for each sender. + * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. + * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. + * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. + * @param {number} [Zp=jiff.Zp] - the mod. + * @param {string|number} [share_id=auto_gen()] - the base tag used to tag the messages sent by this share operation, every element of the array + * will get a unique id based on the concatenation of base_share_id and the index of the element. + * This tag is used so that parties distinguish messages belonging to this share operation from + * other share operations between the same parties (when the order of execution is not + * deterministic). An automatic id is generated by increasing a local counter, default + * ids suffice when all parties execute all sharing operations with the same senders + * and receivers in the same order. + * @return {promise} if the calling party is a receiver then a promise to the shared arrays is returned, the promise will provide an object + * formatted as follows: { : [ <1st_share>, <2nd_share>, ..., <(lengths[party_id])th_share> ] } + * where the party_ids are those of the senders. + * if the calling party is not a receiver, then null is returned. + */ + jiff_share_array: function (jiff, array, lengths, threshold, receivers_list, senders_list, Zp, share_id) { + var i; + + // Check format of lengths + if (lengths != null && typeof(lengths) !== 'number' && typeof(lengths) !== 'object') { + throw new Error('share_array: unrecognized lengths'); + } + + // Default values + if (receivers_list == null) { + receivers_list = []; + for (i = 1; i <= jiff.party_count; i++) { + receivers_list.push(i); + } + } else { + jiff.helpers.sort_ids(receivers_list); + } + if (senders_list == null) { + senders_list = []; + for (i = 1; i <= jiff.party_count; i++) { + senders_list.push(i); + } + } else { + jiff.helpers.sort_ids(senders_list); + } + + var isReceiving = receivers_list.indexOf(jiff.id) > -1; + if (senders_list.indexOf(jiff.id) === -1 && !isReceiving) { + return null; + } // This party is neither a sender nor a receiver, do nothing! + + // compute operation id + if (share_id == null) { + share_id = jiff.counters.gen_op_id2('share_array', receivers_list, senders_list); + } + + // wrap around result of share_array + var share_array_deferred = new jiff.helpers.Deferred(); + var share_array_promise = share_array_deferred.promise; + + // figure out lengths by having each party emit their length publicly + if (lengths == null) { + lengths = {}; + var total = 0; + if (senders_list.indexOf(jiff.id) > -1) { + lengths[jiff.id] = array.length; + + // send the length of this party's array to all receivers + jiff.emit(share_id + 'length', receivers_list, array.length.toString(10)); + } + + jiff.listen(share_id + 'length', function (sender, message) { + lengths[sender] = parseInt(message, 10); + total++; + if (total === senders_list.length) { + jiff.remove_listener(share_id + 'length'); + share_array_deferred.resolve(lengths); + } + }); + } else if (typeof(lengths) === 'number') { + // All arrays are of the same length + var l = lengths; + lengths = {}; + for (i = 0; i < senders_list.length; i++) { + lengths[senders_list[i]] = l; + } + + share_array_deferred.resolve(lengths); + } else { + // Lengths of the different arrays are all provided + for (i = 0; i < senders_list.length; i++) { + if (lengths[senders_list[i]] == null) { + throw new Error('share_array: missing length'); + } + } + + share_array_deferred.resolve(lengths); + } + + // lengths are now set, start sharing + share_array_promise = share_array_promise.then(function (lengths) { + // compute the number of sharing rounds + var max = 0; + for (i = 0; i < senders_list.length; i++) { + var l = lengths[senders_list[i]]; + max = l > max ? l : max; + } + + // Store results here + var results = {}; + if (isReceiving) { + for (i = 0; i < senders_list.length; i++) { + results[senders_list[i]] = []; + } + } + + // share every round + for (var r = 0; r < max; r++) { + var round_senders = []; + for (i = 0; i < senders_list.length; i++) { + if (lengths[senders_list[i]] > r) { + round_senders.push(senders_list[i]); + } + } + + var value = (senders_list.indexOf(jiff.id) > -1) && (r < array.length) ? array[r] : null; + var round_results = jiff.share(value, threshold, receivers_list, round_senders, Zp, share_id + 'round:' + r); + + for (var sender_id in round_results) { + if (round_results.hasOwnProperty(sender_id)) { + results[sender_id].push(round_results[sender_id]); + } + } + } + + return results; + }); + + return isReceiving ? share_array_promise : null; + }, + + /** + * Opens a bunch of secret shares. + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. + * @param {module:jiff-client~JIFFClient#SecretShare[]} shares - an array containing this party's shares of the secrets to reconstruct. + * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties. + * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open + * @returns {?promise} a (JQuery) promise to ALL the open values of the secret, the promise will yield + * an array of values matching the corresponding given secret share by index, if the calling + * party is not a receiver, null is returned + */ + jiff_open_array: function (jiff, shares, parties, op_id) { + // Default values + if (parties == null) { + parties = []; + for (i = 1; i <= jiff.party_count; i++) { + parties.push(i); + } + } else { + jiff.helpers.sort_ids(parties); + } + + // Compute operation ids (one for each party that will receive a result + if (op_id == null) { + op_id = jiff.counters.gen_op_id2('open_array', parties, shares[0].holders); + } + + var promises = []; + for (var i = 0; i < shares.length; i++) { + var promise = jiff.open(shares[i], parties, op_id + ':' + i); + if (promise != null) { + promises.push(promise); + } + } + + if (promises.length === 0) { + return null; + } + + return Promise.all(promises); + } }; },{}],22:[function(require,module,exports){ -module.exports = { - /** - * Compute sum of bitwise secret shared number and a constant - * @function cadd - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares - * @param {number} constant - the constant - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length here will be max(|bits|, |constant|) + 1 - * in case of potential overflow / carry - */ - cadd: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cadd)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cadd', bits[0].holders); - } - - if (constant.toString() === '0') { - return bits; - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // decompose constant into bits - var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length - - // initialize results - var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - var sum = bits[0].icxor_bit(constant_bits[0]); - var carry = bits[0].icmult(constant_bits[0]); - - // put initial bit at head of result array - result.unshift(sum); - deferreds.unshift(null); - - // compute sum one bit at a time, propagating carry - jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, carry, function (i, carry) { - var sum; - if (i < bits.length) { - var and = bits[i].icmult(constant_bits[i]); - var xor = bits[i].icxor_bit(constant_bits[i]); - var xorAndCarry = xor.ismult(carry, op_id + ':smult:' + (i - 1)); - - sum = xor.isxor_bit(carry, op_id + ':sxor_bit:' + (i - 1)); - carry = and.isadd(xorAndCarry); // cheap or, xor and and cannot both be true! - } else { - // bits.length <= i < constant_bits.length - // and is zero, xor is constant_bits[i] - sum = carry.icxor_bit(constant_bits[i]); - carry = carry.icmult(constant_bits[i]); - } - - sum.wThen(deferreds[i].resolve); - return carry; - }); - - return result; - }, - /** - * Compute [secret bits] - [constant bits] - * @function csubl - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} constant - the constant - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - csubl: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.csubl)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.csubl', bits[0].holders); - } - - if (constant.toString() === '0') { - return bits; - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // decompose constant into bits - var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length - - // initialize results - var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - var diff = bits[0].icxor_bit(constant_bits[0]); - var borrow = bits[0].inot().icmult(constant_bits[0]); - - // put initial bit at head of result array - result.unshift(diff); - deferreds.unshift(null); - - // compute diff one bit at a time, propagating borrow - jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { - var diff; - if (i < bits.length) { - var xor = bits[i].icxor_bit(constant_bits[i]); - var andNot = bits[i].inot().icmult(constant_bits[i]); - - // save and update borrow - diff = xor.isxor_bit(borrow, op_id + ':sxor_bit:' + (i - 1)); - borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); - borrow = borrow.isadd(andNot); - } else { - // bits.length <= i < constant_bits.length - // xor and andNot are equal to the constant bit value since secret bit is always zero here - diff = borrow.icxor_bit(constant_bits[i]); - borrow = borrow.issub(borrow.icmult(constant_bits[i])); - borrow = borrow.icadd(constant_bits[i]); - } - - diff.wThen(deferreds[i].resolve); - return borrow; - }); - - return result; - }, - /** - * Compute [constant bits] - [secret bits] - * @function csubr - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} constant - the constant - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - csubr: function (jiff, constant, bits, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.csubr)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.csubr', bits[0].holders); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // decompose constant into bits - var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length - - // initialize results - var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - var diff = bits[0].icxor_bit(constant_bits[0]); - var borrow = bits[0].issub(bits[0].icmult(constant_bits[0])); - - // put initial bit at head of result array - result.unshift(diff); - deferreds.unshift(null); - - // compute diff one bit at a time, propagating borrow - jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { - var diff; - if (i < bits.length) { - var xor = bits[i].icxor_bit(constant_bits[i]); - var andNot = bits[i].issub(bits[i].icmult(constant_bits[i])); - - // save and update borrow - diff = xor.isxor_bit(borrow, op_id + ':sxor_bit:' + (i - 1)); - borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); - borrow = borrow.isadd(andNot); - } else { - // andNot is zero and xor is equal to the constant bit since secret bit is always zero here. - diff = borrow.icxor_bit(constant_bits[i]); - borrow = borrow.icmult(constant_bits[i] === 1 ? 0 : 1); - } - - diff.wThen(deferreds[i].resolve); - return borrow; - }); - - return result; - }, - /** - * - * Compute [secret bits1] + [secret bits2] - * @function sadd - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - the first bitwise shared number: array of secrets with index 0 being least significant bit - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number (length may be different) - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit - */ - sadd: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.sadd', bits1[0].holders); - } - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - var tmp = bits1.length > bits2.length ? bits1 : bits2; - bits2 = bits1.length > bits2.length ? bits2 : bits1; // shortest array - bits1 = tmp; // longest array - - // initialize results - var result = jiff.utils.many_secret_shares(bits1.length, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - var sum = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); - var carry = bits1[0].ismult(bits2[0], op_id + ':smult:initial'); - - // put initial bit at head of result array - result.unshift(sum); - deferreds.unshift(null); - - // compute sum one bit at a time, propagating carry - jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, carry, function (i, carry) { - var sum; - if (i < bits2.length) { - var and = bits1[i].ismult(bits2[i], op_id + ':smult1:' + (i - 1)); - var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); - var xorAndCarry = xor.ismult(carry, op_id + ':smult2:' + (i - 1)); - - sum = xor.isxor_bit(carry, op_id + ':sxor_bit2:' + (i - 1)); - carry = and.isadd(xorAndCarry); // cheap or, xor and and cannot both be true! - } else { - // and is always zero, xor is equal to bits1[i] - sum = bits1[i].isxor_bit(carry, op_id + ':sxor_bit1:' + (i - 1)); - carry = bits1[i].ismult(carry, op_id + ':smult1:' + (i - 1)); - } - - sum.wThen(deferreds[i].resolve); - return carry; - }); - - return result; - }, - /** - * Compute [secret bits1] - [secret bits2] - * @function ssub - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - first bitwise secret shared number: lower indices represent less significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - second bitwise secret shared number (length may be different) - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where - * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, - * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise - */ - ssub: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.ssub', bits1[0].holders); - } - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - // initialize results - var result = jiff.utils.many_secret_shares(Math.max(bits1.length, bits2.length), bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - var diff = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); - var borrow = bits1[0].inot().ismult(bits2[0], op_id + ':smult:initial'); - - // put initial bit at head of result array - result.unshift(diff); - deferreds.unshift(null); - - // compute diff one bit at a time, propagating borrow - jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { - var diff; - if (i < bits1.length && i < bits2.length) { - var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); - var andNot = bits1[i].inot().ismult(bits2[i], op_id + ':smult1:' + (i - 1)); - - // save and update borrow - diff = xor.isxor_bit(borrow, op_id + ':sxor_bit2:' + (i - 1)); - borrow = xor.inot().ismult(borrow, op_id + ':smult2:' + (i - 1)); - borrow = borrow.isadd(andNot); - } else if (i < bits1.length) { - // xor is equal to the value of bits1[i], andNot is equal to 0, since bits[2] is all zeros here - diff = bits1[i].isxor_bit(borrow, op_id + ':sxor_bit1:' + (i - 1)); - borrow = bits1[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); - } else { // i < bits2.length - // xor and andNot are equal to the value of bits2[i] - diff = bits2[i].isxor_bit(borrow, op_id + ':sxor_bit1:' + (i - 1)); - borrow = bits2[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); - borrow = borrow.isadd(bits2[i]); - } - - diff.wThen(deferreds[i].resolve); - return borrow; - }); - - return result; - }, - /** - * Compute [secret bits] * constant - * @function cmult - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - bitwise shared secret to multiply: lower indices represent less significant bits - * @param {number} constant - constant to multiply with - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits.length + ceil(log2(constant)), except - * if constant is zero, the result will then be [ zero share ] - */ - cmult: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cmult)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cmult', bits[0].holders); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // decompose constant into bits - var constant_bits = jiff.helpers.number_to_bits(constant); // do not pad - - // Initialize the result - var result = jiff.utils.many_secret_shares(bits.length + constant_bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - // Resolve result when ready - var final_deferred = new jiff.helpers.Deferred(); - final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, deferreds)); - - // get useless share of zero (just for padding) - var zero = new jiff.SecretShare(0, bits[0].holders, bits[0].threshold, bits[0].Zp); - var initial = [zero]; - - // special case - if (constant.toString() === '0') { - return initial; - } - - // main function - jiff.utils.bit_combinator(final_deferred, 0, constant_bits.length, initial, function (i, intermediate) { - // Shift bits to create the intermediate values, - // and sum if the corresponding bit in a is 1 - if (constant_bits[i].toString() === '1') { - intermediate = jiff.protocols.bits.sadd(intermediate, bits, op_id + ':bits.sadd:' + i); - } - - bits.unshift(zero); - return intermediate; - }, function (intermediate) { - // promise-ify an array of intermediate results - var promises = []; - for (var i = 0; i < intermediate.length; i++) { - promises.push(intermediate[i].value); - } - return Promise.all(promises); - }, function (result) { - // identity - return result; - }); - - return result; - }, - /** - * Compute [secret bits1] * [secret bits2] - * @function smult - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - bitwise shared secret to multiply: lower indices represent less significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - bitwise shared secret to multiply - * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits1.length + bits2.length - */ - smult: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.smult', bits1[0].holders); - } - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - // bits1 will be the longest array, bits2 will be the shortest - var tmp = bits1.length > bits2.length ? bits1 : bits2; - bits2 = bits1.length > bits2.length ? bits2 : bits1; - bits1 = tmp; - - // Initialize the result - var offset = bits2.length === 1 ? -1 : 0; - var result = jiff.utils.many_secret_shares(bits1.length + bits2.length + offset, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - var deferreds = result.deferreds; - result = result.shares; - - // Resolve result when ready - var final_deferred = new jiff.helpers.Deferred(); - final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, deferreds)); - - // Loop over *shortest* array one bit at a time - jiff.utils.bit_combinator(final_deferred, 0, bits2.length, bits2, function (i, intermediate) { - var this_bit = bits2[i]; - var bit_mult = []; // add bits1 or 0 to the result according to this bit - for (var j = 0; j < bits1.length; j++) { - bit_mult[j] = this_bit.iif_else(bits1[j], 0, op_id + ':if_else:' + i + ':' + j); - } - bits1.unshift(0); // increase magnitude - - if (i === 0) { - return bit_mult; - } - - return jiff.protocols.bits.sadd(intermediate, bit_mult, op_id + ':bits.sadd:' + i); - }, function (intermediate) { - // promise-ify an array of intermediate results - var promises = []; - for (var i = 0; i < intermediate.length; i++) { - promises.push(intermediate[i].value); - } - return Promise.all(promises); - }, function (result) { - // identity - return result; - }); - - return result; - }, - /** - * Computes integer division of [secret bits 1] / [secret bits 2] - * @function sdiv - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as bits1, - * and the remainder array has the same length as bits2 or bits1, whichever is smaller. - * Note: if bits2 represent 0, the returned result is the maximum - * number that fits in the number of bits (all 1), and the remainder - * is equal to bits1 - */ - sdiv: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.sdiv', bits1[0].holders); - } - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - // Initialize the result - var quotient = jiff.utils.many_secret_shares(bits1.length, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - var quotientDeferreds = quotient.deferreds; - quotient = quotient.shares; - - var remainder = jiff.utils.many_secret_shares(Math.min(bits1.length, bits2.length), bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - var remainderDeferreds = remainder.deferreds; - remainder = remainder.shares; - - // Resolve result when ready - var final_deferred = new jiff.helpers.Deferred(); - final_deferred.promise.then(function (result) { - jiff.utils.resolve_many_secrets(remainderDeferreds, result); - }); - - var initial = []; // initial remainder - jiff.utils.bit_combinator(final_deferred, bits1.length - 1, -1, initial, function (i, _remainder) { - var iterationCounter = (bits1.length - i - 1); - - // add bit i to the head of remainder (least significant bit) - _remainder.unshift(bits1[i]); - - // Get the next bit of the quotient - // and conditionally subtract b from the - // intermediate remainder to continue - var sub = jiff.protocols.bits.ssub(_remainder, bits2, op_id + ':bits.ssub:' + iterationCounter); - var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction - - // Get next bit of quotient - noUnderflow.wThen(quotientDeferreds[i].resolve); - - // Update remainder - for (var j = 0; j < _remainder.length; j++) { - // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| - _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); - } - - // Remainder cannot be greater than divisor at this point - while (_remainder.length > remainder.length) { - _remainder.pop(); - } - - return _remainder; - }, function (intermediate) { - // promise-ify an array of intermediate results - var promises = []; - for (var i = 0; i < intermediate.length; i++) { - promises.push(intermediate[i].value); - } - return Promise.all(promises); - }, function (result) { - // identity - return result; - }); - - return {quotient: quotient, remainder: remainder} - }, - /** - * Computes integer division of [secret bits] / constant - * @function cdivl - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - numerator: an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the denominator number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as bits, - * and the remainder array has the same length as - * constant or bits, whichever is smaller - * @throws if constant is 0. - */ - cdivl: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cdivl)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cdivl', bits[0].holders); - } - - if (constant.toString() === '0') { - throw new Error('constant cannot be 0 in bits.cdiv'); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // special case, divide by 1 - if (constant.toString() === '1') { - return { - quotient: bits, - remainder: [new jiff.SecretShare(0, bits[0].holders, bits[0].threshold, bits[0].Zp)] - } - } - - // Initialize the result - var quotient = jiff.utils.many_secret_shares(bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); - var quotientDeferreds = quotient.deferreds; - quotient = quotient.shares; - - var constantLessBits = jiff.helpers.ceil(jiff.helpers.bLog(constant, 2)); - constantLessBits = parseInt(constantLessBits.toString(), 10); - var remainder = jiff.utils.many_secret_shares(Math.min(constantLessBits, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); - var remainderDeferreds = remainder.deferreds; - remainder = remainder.shares; - - // Resolve result when ready - var final_deferred = new jiff.helpers.Deferred(); - final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, remainderDeferreds)); - - var initial = []; // initial remainder - jiff.utils.bit_combinator(final_deferred, bits.length - 1, -1, initial, function (i, _remainder) { - var iterationCounter = (bits.length - i - 1); - - // add bit i to the head of remainder (least significant bit) - _remainder.unshift(bits[i]); - - // Get the next bit of the quotient - // and conditionally subtract b from the - // intermediate remainder to continue - var sub = jiff.protocols.bits.csubl(_remainder, constant, op_id + ':bits.csubl:' + iterationCounter); - var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction - - // Get next bit of quotient - noUnderflow.wThen(quotientDeferreds[i].resolve); - - // Update remainder - for (var j = 0; j < _remainder.length; j++) { - // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| - _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); - } - - // Remainder cannot be greater than constant at this point - while (_remainder.length > remainder.length) { - _remainder.pop(); - } - - return _remainder; - }, function (intermediate) { - // promise-ify an array of intermediate results - var promises = []; - for (var i = 0; i < intermediate.length; i++) { - promises.push(intermediate[i].value); - } - return Promise.all(promises); - }, function (result) { - // identity - return result; - }); - - return {quotient: quotient, remainder: remainder}; - }, - /** - * Computes integer division of constant / [secret bits] - * @function cdivr - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} constant - the numerator number - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - denominator: an array of secret shares of bits, starting from least to most significant bits - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that - * the quotient array has the same length as the number of bits in constant, - * and the remainder array has the same length as bits or constant, whichever is smaller. - * Note: if bits represent 0, the returned result is the maximum - * number that fits in its bits (all 1), and the remainder - * is equal to constant - */ - cdivr: function (jiff, constant, bits, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cdivr)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cdivr', bits[0].holders); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // do not pad - var constant_bits = jiff.helpers.number_to_bits(constant); - - // Initialize the result - var quotient = jiff.utils.many_secret_shares(constant_bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); - var quotientDeferreds = quotient.deferreds; - quotient = quotient.shares; - - var remainder = jiff.utils.many_secret_shares(Math.min(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); - var remainderDeferreds = remainder.deferreds; - remainder = remainder.shares; - - // Resolve result when ready - var final_deferred = new jiff.helpers.Deferred(); - final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, remainderDeferreds)); - - var initial = []; // initial remainder - jiff.utils.bit_combinator(final_deferred, constant_bits.length - 1, -1, initial, function (i, _remainder) { - var iterationCounter = (constant_bits.length - i - 1); - - // add bit i to the head of remainder (least significant bit) - // turn into a secret without communication, just for typing - var cbit_share = new jiff.SecretShare(constant_bits[i], bits[0].holders, bits[0].threshold, bits[0].Zp); - _remainder.unshift(cbit_share); - - // Get the next bit of the quotient - // and conditionally subtract b from the - // intermediate remainder to continue - var sub = jiff.protocols.bits.ssub(_remainder, bits, op_id + ':bits.ssub:' + iterationCounter); - var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction - - // Get next bit of quotient - noUnderflow.wThen(quotientDeferreds[i].resolve); - - // Update remainder - for (var j = 0; j < _remainder.length; j++) { - // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| - _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); - } - - // cannot be bigger than divisor at this point - while (_remainder.length > remainder.length) { - _remainder.pop(); - } - - return _remainder; - }, function (intermediate) { - // promise-ify an array of intermediate results - var promises = []; - for (var i = 0; i < intermediate.length; i++) { - promises.push(intermediate[i].value); - } - return Promise.all(promises); - }, function (result) { - // identity - return result; - }); - - return {quotient: quotient, remainder: remainder}; - } -}; -},{}],23:[function(require,module,exports){ -module.exports = { - /** - * Checks whether the given bitwise secret shared number and numeric constant are equal - * @function ceq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if parameters are equal, 0 otherwise. If result is known - * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - ceq: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.ceq)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.ceq', bits[0].holders); - } - var result = jiff.protocols.bits.cneq(bits, constant, op_id); - if (result === true || result === false) { - return !result; - } - return result.inot(); - }, - /** - * Checks whether the given bitwise secret shared number and numeric constant are not equal - * @function cneq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if parameters are not equal, 0 otherwise. If result is known - * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - cneq: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cneq)'); - } - - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cneq', bits[0].holders); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); - if (constant_bits.length > bits.length) { - // Optimization: if constant has more bits, one of them must be 1, constant must be greater than bits. - return true; - } - - var deferred = new jiff.helpers.Deferred(); - var result = new jiff.SecretShare(deferred.promise, bits[0].holders, bits[0].threshold, bits[0].Zp); - - // big or of bitwise XORs - var initial = bits[0].icxor_bit(constant_bits[0]); - jiff.utils.bit_combinator(deferred, 1, bits.length, initial, function (i, prev) { - var xor = bits[i].icxor_bit(constant_bits[i]); - xor = prev.isor_bit(xor, op_id + ':sor_bit:' + (i - 1)); - return xor; - }); - - return result; - }, - /** - * Checks whether given secret shared bits are greater than the given constant - * @function cgt - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are greater than constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - cgt: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cgt)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cgt', bits[0].holders); - } - return jiff.protocols.bits.cgteq(bits, constant + 1, op_id); - }, - /** - * Checks whether given secret shared bits are greater or equal to the given constant - * @function cgteq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are greater or equal to constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit or constant is zero), the result is - * returned immediately as a boolean - */ - cgteq: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.cgteq)'); - } - - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.cgteq', bits[0].holders); - } - - // copy to avoid aliasing problems during execution - bits = bits.slice(); - - // Optimization: the bits are a share of non-negative number, if constant <= 0, return true - if (constant.toString().startsWith('-') || constant.toString() === '0') { - return true; - } - - // decompose result into bits - var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); - if (constant_bits.length > bits.length) { - // Optimization: if constant has more bits, one of them must be 1, constant must be greater than bits. - return false; - } - - // initialize result - var deferred = new jiff.helpers.Deferred(); - var result = new jiff.SecretShare(deferred.promise, bits[0].holders, bits[0].threshold, bits[0].Zp); - - // Subtract bits2 from bits1, only keeping track of borrow - var borrow = bits[0].inot().icmult(constant_bits[0]); - - // compute one bit at a time, propagating borrow - jiff.utils.bit_combinator(deferred, 1, bits.length, borrow, function (i, borrow) { - var xor = bits[i].icxor_bit(constant_bits[i]); - var andNot = bits[i].inot().icmult(constant_bits[i]); - - // save and update borrow - borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); - return borrow.isadd(andNot); - }); - - return result.inot(); - }, - /** - * Checks whether given secret shared bits are less than the given constant - * @function clt - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are less than the constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - clt: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.clt)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.clt', bits[0].holders); - } - var result = jiff.protocols.bits.cgteq(bits, constant, op_id); - if (result === true || result === false) { - return !result; - } - return result.inot(); - }, - /** - * Checks whether given secret shared bits are less or equal to the given constant - * @function clteq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number} constant - the constant number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {SecretShare|boolean} a secret share of 1 if bits are less or equal to constant, 0 otherwise, if result is known - * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is - * returned immediately as a boolean - */ - clteq: function (jiff, bits, constant, op_id) { - if (!(bits[0].isConstant(constant))) { - throw new Error('parameter should be a number (bits.clteq)'); - } - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.clteq', bits[0].holders); - } - var result = jiff.protocols.bits.cgt(bits, constant, op_id); - if (result === true || result === false) { - return !result; - } - return result.inot(); - }, - /** - * Checks whether the two given bitwise secret shared numbers are equal - * @function seq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are equal, 0 otherwise - */ - seq: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.seq', bits1[0].holders); - } - return jiff.protocols.bits.sneq(bits1, bits2, op_id).inot(); - }, - /** - * Checks whether the two given bitwise secret shared numbers are not equal - * @function sneq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are not equal, 0 otherwise - */ - sneq: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.sneq', bits1[0].holders); - } - - var tmp = bits1.length > bits2.length ? bits1 : bits2; - bits2 = bits1.length > bits2.length ? bits2 : bits1; // shortest array - bits1 = tmp; // longest array - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - // initialize result - var deferred = new jiff.helpers.Deferred(); - var result = new jiff.SecretShare(deferred.promise, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - - // big or of bitwise XORs - var initial = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); - jiff.utils.bit_combinator(deferred, 1, bits1.length, initial, function (i, prev) { - var next; - if (i < bits2.length) { - var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit:' + (i - 1)); - next = prev.isor_bit(xor, op_id + ':sor_bit:' + (i - 1)); - } else { - // xor is equal to bits1[i] since bits2[i] is zero - next = prev.isor_bit(bits1[i], op_id + ':sor_bit:' + (i - 1)); - } - return next; - }); - - return result; - }, - /** - * Checks whether the first given bitwise secret shared number is greater than the second bitwise secret shared number - * @function sgt - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater than the second, 0 otherwise - */ - sgt: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.sgt', bits1[0].holders); - } - - var gteq = jiff.protocols.bits.sgteq(bits1, bits2, op_id + ':bits.sgteq'); - var neq = jiff.protocols.bits.sneq(bits1, bits2, op_id + ':bits.sneq'); - return gteq.ismult(neq, op_id + ':smult'); - }, - /** - * Checks whether the first given bitwise secret shared number is greater than or equal to the second bitwise secret shared number - * @function sgteq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater or equal to the second, 0 otherwise - */ - sgteq: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.sgteq', bits1[0].holders); - } - - // copy to avoid aliasing problems during execution - bits1 = bits1.slice(); - bits2 = bits2.slice(); - - // initialize result - var deferred = new jiff.helpers.Deferred(); - var result = new jiff.SecretShare(deferred.promise, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); - - // Subtract bits2 from bits1, only keeping track of borrow - var borrow = bits1[0].inot().ismult(bits2[0], op_id + ':smult:initial'); - var n = Math.max(bits1.length, bits2.length); - jiff.utils.bit_combinator(deferred, 1, n, borrow, function (i, borrow) { - if (i < bits1.length && i < bits2.length) { - var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); - var andNot = bits1[i].inot().ismult(bits2[i], op_id + ':smult1:' + (i - 1)); - - // save and update borrow - borrow = xor.inot().ismult(borrow, op_id + ':smult2:' + (i - 1)); - borrow = borrow.isadd(andNot); - } else if (i < bits1.length) { - // xor is equal to the value of bits1[i], andNot is equal to 0, since bits[2] is all zeros here - borrow = bits1[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); - } else { // i < bits2.length - // xor and andNot are equal to the value of bits2[i] - borrow = bits2[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); - borrow = borrow.isadd(bits2[i]); - } - - return borrow; - }); - - return result.inot(); - }, - /** - * Checks whether the first given bitwise secret shared number is less than the second bitwise secret shared number - * @function slt - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than the second, 0 otherwise - */ - slt: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.slt', bits1[0].holders); - } - var result = jiff.protocols.bits.sgteq(bits1, bits2, op_id); - return result.inot(); - }, - /** - * Checks whether the first given bitwise secret shared number is less or equal to the second bitwise secret shared number - * @function slteq - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number - * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. - * default value should suffice when the code of all parties executes all instructions - * in the same exact order, otherwise, a unique base name is needed here - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than or equal to the second, 0 otherwise - */ - slteq: function (jiff, bits1, bits2, op_id) { - if (op_id == null) { - op_id = jiff.counters.gen_op_id('bits.slteq', bits1[0].holders); - } - var result = jiff.protocols.bits.sgt(bits1, bits2, op_id); - return result.inot(); - } +module.exports = { + /** + * Compute sum of bitwise secret shared number and a constant + * @function cadd + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {number} constant - the constant + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length here will be max(|bits|, |constant|) + 1 + * in case of potential overflow / carry + */ + cadd: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cadd)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cadd', bits[0].holders); + } + + if (constant.toString() === '0') { + return bits; + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // decompose constant into bits + var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length + + // initialize results + var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + var sum = bits[0].icxor_bit(constant_bits[0]); + var carry = bits[0].icmult(constant_bits[0]); + + // put initial bit at head of result array + result.unshift(sum); + deferreds.unshift(null); + + // compute sum one bit at a time, propagating carry + jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, carry, function (i, carry) { + var sum; + if (i < bits.length) { + var and = bits[i].icmult(constant_bits[i]); + var xor = bits[i].icxor_bit(constant_bits[i]); + var xorAndCarry = xor.ismult(carry, op_id + ':smult:' + (i - 1)); + + sum = xor.isxor_bit(carry, op_id + ':sxor_bit:' + (i - 1)); + carry = and.isadd(xorAndCarry); // cheap or, xor and and cannot both be true! + } else { + // bits.length <= i < constant_bits.length + // and is zero, xor is constant_bits[i] + sum = carry.icxor_bit(constant_bits[i]); + carry = carry.icmult(constant_bits[i]); + } + + sum.wThen(deferreds[i].resolve); + return carry; + }); + + return result; + }, + /** + * Compute [secret bits] - [constant bits] + * @function csubl + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} constant - the constant + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + csubl: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.csubl)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.csubl', bits[0].holders); + } + + if (constant.toString() === '0') { + return bits; + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // decompose constant into bits + var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length + + // initialize results + var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + var diff = bits[0].icxor_bit(constant_bits[0]); + var borrow = bits[0].inot().icmult(constant_bits[0]); + + // put initial bit at head of result array + result.unshift(diff); + deferreds.unshift(null); + + // compute diff one bit at a time, propagating borrow + jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { + var diff; + if (i < bits.length) { + var xor = bits[i].icxor_bit(constant_bits[i]); + var andNot = bits[i].inot().icmult(constant_bits[i]); + + // save and update borrow + diff = xor.isxor_bit(borrow, op_id + ':sxor_bit:' + (i - 1)); + borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); + borrow = borrow.isadd(andNot); + } else { + // bits.length <= i < constant_bits.length + // xor and andNot are equal to the constant bit value since secret bit is always zero here + diff = borrow.icxor_bit(constant_bits[i]); + borrow = borrow.issub(borrow.icmult(constant_bits[i])); + borrow = borrow.icadd(constant_bits[i]); + } + + diff.wThen(deferreds[i].resolve); + return borrow; + }); + + return result; + }, + /** + * Compute [constant bits] - [secret bits] + * @function csubr + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} constant - the constant + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - the bit wise secret shares + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + csubr: function (jiff, constant, bits, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.csubr)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.csubr', bits[0].holders); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // decompose constant into bits + var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); // pads with zeros to bits.length + + // initialize results + var result = jiff.utils.many_secret_shares(Math.max(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + var diff = bits[0].icxor_bit(constant_bits[0]); + var borrow = bits[0].issub(bits[0].icmult(constant_bits[0])); + + // put initial bit at head of result array + result.unshift(diff); + deferreds.unshift(null); + + // compute diff one bit at a time, propagating borrow + jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { + var diff; + if (i < bits.length) { + var xor = bits[i].icxor_bit(constant_bits[i]); + var andNot = bits[i].issub(bits[i].icmult(constant_bits[i])); + + // save and update borrow + diff = xor.isxor_bit(borrow, op_id + ':sxor_bit:' + (i - 1)); + borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); + borrow = borrow.isadd(andNot); + } else { + // andNot is zero and xor is equal to the constant bit since secret bit is always zero here. + diff = borrow.icxor_bit(constant_bits[i]); + borrow = borrow.icmult(constant_bits[i] === 1 ? 0 : 1); + } + + diff.wThen(deferreds[i].resolve); + return borrow; + }); + + return result; + }, + /** + * + * Compute [secret bits1] + [secret bits2] + * @function sadd + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - the first bitwise shared number: array of secrets with index 0 being least significant bit + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number (length may be different) + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit + */ + sadd: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.sadd', bits1[0].holders); + } + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + var tmp = bits1.length > bits2.length ? bits1 : bits2; + bits2 = bits1.length > bits2.length ? bits2 : bits1; // shortest array + bits1 = tmp; // longest array + + // initialize results + var result = jiff.utils.many_secret_shares(bits1.length, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + var sum = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); + var carry = bits1[0].ismult(bits2[0], op_id + ':smult:initial'); + + // put initial bit at head of result array + result.unshift(sum); + deferreds.unshift(null); + + // compute sum one bit at a time, propagating carry + jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, carry, function (i, carry) { + var sum; + if (i < bits2.length) { + var and = bits1[i].ismult(bits2[i], op_id + ':smult1:' + (i - 1)); + var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); + var xorAndCarry = xor.ismult(carry, op_id + ':smult2:' + (i - 1)); + + sum = xor.isxor_bit(carry, op_id + ':sxor_bit2:' + (i - 1)); + carry = and.isadd(xorAndCarry); // cheap or, xor and and cannot both be true! + } else { + // and is always zero, xor is equal to bits1[i] + sum = bits1[i].isxor_bit(carry, op_id + ':sxor_bit1:' + (i - 1)); + carry = bits1[i].ismult(carry, op_id + ':smult1:' + (i - 1)); + } + + sum.wThen(deferreds[i].resolve); + return carry; + }); + + return result; + }, + /** + * Compute [secret bits1] - [secret bits2] + * @function ssub + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - first bitwise secret shared number: lower indices represent less significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - second bitwise secret shared number (length may be different) + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result. Note that the length of the returned result is |bits|+1, where + * the bit at index 0 is the least significant bit. The bit at index 1 is the most significant bit, + * and the bit at index |bits| is 1 if the result overflows, or 0 otherwise + */ + ssub: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.ssub', bits1[0].holders); + } + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + // initialize results + var result = jiff.utils.many_secret_shares(Math.max(bits1.length, bits2.length), bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + var diff = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); + var borrow = bits1[0].inot().ismult(bits2[0], op_id + ':smult:initial'); + + // put initial bit at head of result array + result.unshift(diff); + deferreds.unshift(null); + + // compute diff one bit at a time, propagating borrow + jiff.utils.bit_combinator(deferreds[deferreds.length - 1], 1, deferreds.length - 1, borrow, function (i, borrow) { + var diff; + if (i < bits1.length && i < bits2.length) { + var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); + var andNot = bits1[i].inot().ismult(bits2[i], op_id + ':smult1:' + (i - 1)); + + // save and update borrow + diff = xor.isxor_bit(borrow, op_id + ':sxor_bit2:' + (i - 1)); + borrow = xor.inot().ismult(borrow, op_id + ':smult2:' + (i - 1)); + borrow = borrow.isadd(andNot); + } else if (i < bits1.length) { + // xor is equal to the value of bits1[i], andNot is equal to 0, since bits[2] is all zeros here + diff = bits1[i].isxor_bit(borrow, op_id + ':sxor_bit1:' + (i - 1)); + borrow = bits1[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); + } else { // i < bits2.length + // xor and andNot are equal to the value of bits2[i] + diff = bits2[i].isxor_bit(borrow, op_id + ':sxor_bit1:' + (i - 1)); + borrow = bits2[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); + borrow = borrow.isadd(bits2[i]); + } + + diff.wThen(deferreds[i].resolve); + return borrow; + }); + + return result; + }, + /** + * Compute [secret bits] * constant + * @function cmult + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - bitwise shared secret to multiply: lower indices represent less significant bits + * @param {number} constant - constant to multiply with + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits.length + ceil(log2(constant)), except + * if constant is zero, the result will then be [ zero share ] + */ + cmult: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cmult)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cmult', bits[0].holders); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // decompose constant into bits + var constant_bits = jiff.helpers.number_to_bits(constant); // do not pad + + // Initialize the result + var result = jiff.utils.many_secret_shares(bits.length + constant_bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + // Resolve result when ready + var final_deferred = new jiff.helpers.Deferred(); + final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, deferreds)); + + // get useless share of zero (just for padding) + var zero = new jiff.SecretShare(0, bits[0].holders, bits[0].threshold, bits[0].Zp); + var initial = [zero]; + + // special case + if (constant.toString() === '0') { + return initial; + } + + // main function + jiff.utils.bit_combinator(final_deferred, 0, constant_bits.length, initial, function (i, intermediate) { + // Shift bits to create the intermediate values, + // and sum if the corresponding bit in a is 1 + if (constant_bits[i].toString() === '1') { + intermediate = jiff.protocols.bits.sadd(intermediate, bits, op_id + ':bits.sadd:' + i); + } + + bits.unshift(zero); + return intermediate; + }, function (intermediate) { + // promise-ify an array of intermediate results + var promises = []; + for (var i = 0; i < intermediate.length; i++) { + promises.push(intermediate[i].value); + } + return Promise.all(promises); + }, function (result) { + // identity + return result; + }); + + return result; + }, + /** + * Compute [secret bits1] * [secret bits2] + * @function smult + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - bitwise shared secret to multiply: lower indices represent less significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - bitwise shared secret to multiply + * @param {string} [op_id=] - the base operation id to use when generating unique ids for communication. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare[]} bitwise sharing of the result, the length of the result will be bits1.length + bits2.length + */ + smult: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.smult', bits1[0].holders); + } + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + // bits1 will be the longest array, bits2 will be the shortest + var tmp = bits1.length > bits2.length ? bits1 : bits2; + bits2 = bits1.length > bits2.length ? bits2 : bits1; + bits1 = tmp; + + // Initialize the result + var offset = bits2.length === 1 ? -1 : 0; + var result = jiff.utils.many_secret_shares(bits1.length + bits2.length + offset, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + var deferreds = result.deferreds; + result = result.shares; + + // Resolve result when ready + var final_deferred = new jiff.helpers.Deferred(); + final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, deferreds)); + + // Loop over *shortest* array one bit at a time + jiff.utils.bit_combinator(final_deferred, 0, bits2.length, bits2, function (i, intermediate) { + var this_bit = bits2[i]; + var bit_mult = []; // add bits1 or 0 to the result according to this bit + for (var j = 0; j < bits1.length; j++) { + bit_mult[j] = this_bit.iif_else(bits1[j], 0, op_id + ':if_else:' + i + ':' + j); + } + bits1.unshift(0); // increase magnitude + + if (i === 0) { + return bit_mult; + } + + return jiff.protocols.bits.sadd(intermediate, bit_mult, op_id + ':bits.sadd:' + i); + }, function (intermediate) { + // promise-ify an array of intermediate results + var promises = []; + for (var i = 0; i < intermediate.length; i++) { + promises.push(intermediate[i].value); + } + return Promise.all(promises); + }, function (result) { + // identity + return result; + }); + + return result; + }, + /** + * Computes integer division of [secret bits 1] / [secret bits 2] + * @function sdiv + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as bits1, + * and the remainder array has the same length as bits2 or bits1, whichever is smaller. + * Note: if bits2 represent 0, the returned result is the maximum + * number that fits in the number of bits (all 1), and the remainder + * is equal to bits1 + */ + sdiv: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.sdiv', bits1[0].holders); + } + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + // Initialize the result + var quotient = jiff.utils.many_secret_shares(bits1.length, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + var quotientDeferreds = quotient.deferreds; + quotient = quotient.shares; + + var remainder = jiff.utils.many_secret_shares(Math.min(bits1.length, bits2.length), bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + var remainderDeferreds = remainder.deferreds; + remainder = remainder.shares; + + // Resolve result when ready + var final_deferred = new jiff.helpers.Deferred(); + final_deferred.promise.then(function (result) { + jiff.utils.resolve_many_secrets(remainderDeferreds, result); + }); + + var initial = []; // initial remainder + jiff.utils.bit_combinator(final_deferred, bits1.length - 1, -1, initial, function (i, _remainder) { + var iterationCounter = (bits1.length - i - 1); + + // add bit i to the head of remainder (least significant bit) + _remainder.unshift(bits1[i]); + + // Get the next bit of the quotient + // and conditionally subtract b from the + // intermediate remainder to continue + var sub = jiff.protocols.bits.ssub(_remainder, bits2, op_id + ':bits.ssub:' + iterationCounter); + var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction + + // Get next bit of quotient + noUnderflow.wThen(quotientDeferreds[i].resolve); + + // Update remainder + for (var j = 0; j < _remainder.length; j++) { + // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| + _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); + } + + // Remainder cannot be greater than divisor at this point + while (_remainder.length > remainder.length) { + _remainder.pop(); + } + + return _remainder; + }, function (intermediate) { + // promise-ify an array of intermediate results + var promises = []; + for (var i = 0; i < intermediate.length; i++) { + promises.push(intermediate[i].value); + } + return Promise.all(promises); + }, function (result) { + // identity + return result; + }); + + return {quotient: quotient, remainder: remainder} + }, + /** + * Computes integer division of [secret bits] / constant + * @function cdivl + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - numerator: an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the denominator number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as bits, + * and the remainder array has the same length as + * constant or bits, whichever is smaller + * @throws if constant is 0. + */ + cdivl: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cdivl)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cdivl', bits[0].holders); + } + + if (constant.toString() === '0') { + throw new Error('constant cannot be 0 in bits.cdiv'); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // special case, divide by 1 + if (constant.toString() === '1') { + return { + quotient: bits, + remainder: [new jiff.SecretShare(0, bits[0].holders, bits[0].threshold, bits[0].Zp)] + } + } + + // Initialize the result + var quotient = jiff.utils.many_secret_shares(bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); + var quotientDeferreds = quotient.deferreds; + quotient = quotient.shares; + + var constantLessBits = jiff.helpers.ceil(jiff.helpers.bLog(constant, 2)); + constantLessBits = parseInt(constantLessBits.toString(), 10); + var remainder = jiff.utils.many_secret_shares(Math.min(constantLessBits, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); + var remainderDeferreds = remainder.deferreds; + remainder = remainder.shares; + + // Resolve result when ready + var final_deferred = new jiff.helpers.Deferred(); + final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, remainderDeferreds)); + + var initial = []; // initial remainder + jiff.utils.bit_combinator(final_deferred, bits.length - 1, -1, initial, function (i, _remainder) { + var iterationCounter = (bits.length - i - 1); + + // add bit i to the head of remainder (least significant bit) + _remainder.unshift(bits[i]); + + // Get the next bit of the quotient + // and conditionally subtract b from the + // intermediate remainder to continue + var sub = jiff.protocols.bits.csubl(_remainder, constant, op_id + ':bits.csubl:' + iterationCounter); + var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction + + // Get next bit of quotient + noUnderflow.wThen(quotientDeferreds[i].resolve); + + // Update remainder + for (var j = 0; j < _remainder.length; j++) { + // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| + _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); + } + + // Remainder cannot be greater than constant at this point + while (_remainder.length > remainder.length) { + _remainder.pop(); + } + + return _remainder; + }, function (intermediate) { + // promise-ify an array of intermediate results + var promises = []; + for (var i = 0; i < intermediate.length; i++) { + promises.push(intermediate[i].value); + } + return Promise.all(promises); + }, function (result) { + // identity + return result; + }); + + return {quotient: quotient, remainder: remainder}; + }, + /** + * Computes integer division of constant / [secret bits] + * @function cdivr + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} constant - the numerator number + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - denominator: an array of secret shares of bits, starting from least to most significant bits + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {{quotient: module:jiff-client~JIFFClient#SecretShare[], remainder: module:jiff-client~JIFFClient#SecretShare[]}} the quotient and remainder bits arrays, note that + * the quotient array has the same length as the number of bits in constant, + * and the remainder array has the same length as bits or constant, whichever is smaller. + * Note: if bits represent 0, the returned result is the maximum + * number that fits in its bits (all 1), and the remainder + * is equal to constant + */ + cdivr: function (jiff, constant, bits, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cdivr)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cdivr', bits[0].holders); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // do not pad + var constant_bits = jiff.helpers.number_to_bits(constant); + + // Initialize the result + var quotient = jiff.utils.many_secret_shares(constant_bits.length, bits[0].holders, bits[0].threshold, bits[0].Zp); + var quotientDeferreds = quotient.deferreds; + quotient = quotient.shares; + + var remainder = jiff.utils.many_secret_shares(Math.min(constant_bits.length, bits.length), bits[0].holders, bits[0].threshold, bits[0].Zp); + var remainderDeferreds = remainder.deferreds; + remainder = remainder.shares; + + // Resolve result when ready + var final_deferred = new jiff.helpers.Deferred(); + final_deferred.promise.then(jiff.utils.resolve_many_secrets.bind(null, remainderDeferreds)); + + var initial = []; // initial remainder + jiff.utils.bit_combinator(final_deferred, constant_bits.length - 1, -1, initial, function (i, _remainder) { + var iterationCounter = (constant_bits.length - i - 1); + + // add bit i to the head of remainder (least significant bit) + // turn into a secret without communication, just for typing + var cbit_share = new jiff.SecretShare(constant_bits[i], bits[0].holders, bits[0].threshold, bits[0].Zp); + _remainder.unshift(cbit_share); + + // Get the next bit of the quotient + // and conditionally subtract b from the + // intermediate remainder to continue + var sub = jiff.protocols.bits.ssub(_remainder, bits, op_id + ':bits.ssub:' + iterationCounter); + var noUnderflow = sub.pop().inot(); // get the overflow bit, sub is now the result of subtraction + + // Get next bit of quotient + noUnderflow.wThen(quotientDeferreds[i].resolve); + + // Update remainder + for (var j = 0; j < _remainder.length; j++) { + // note, if noUnderflow, then |# bits in sub| <= |# bits in remainder| + _remainder[j] = noUnderflow.iif_else(sub[j], _remainder[j], op_id + ':if_else:' + iterationCounter + ':' + j); + } + + // cannot be bigger than divisor at this point + while (_remainder.length > remainder.length) { + _remainder.pop(); + } + + return _remainder; + }, function (intermediate) { + // promise-ify an array of intermediate results + var promises = []; + for (var i = 0; i < intermediate.length; i++) { + promises.push(intermediate[i].value); + } + return Promise.all(promises); + }, function (result) { + // identity + return result; + }); + + return {quotient: quotient, remainder: remainder}; + } +}; +},{}],23:[function(require,module,exports){ +module.exports = { + /** + * Checks whether the given bitwise secret shared number and numeric constant are equal + * @function ceq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if parameters are equal, 0 otherwise. If result is known + * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + ceq: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.ceq)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.ceq', bits[0].holders); + } + var result = jiff.protocols.bits.cneq(bits, constant, op_id); + if (result === true || result === false) { + return !result; + } + return result.inot(); + }, + /** + * Checks whether the given bitwise secret shared number and numeric constant are not equal + * @function cneq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if parameters are not equal, 0 otherwise. If result is known + * (e.g. constant has a greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + cneq: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cneq)'); + } + + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cneq', bits[0].holders); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); + if (constant_bits.length > bits.length) { + // Optimization: if constant has more bits, one of them must be 1, constant must be greater than bits. + return true; + } + + var deferred = new jiff.helpers.Deferred(); + var result = new jiff.SecretShare(deferred.promise, bits[0].holders, bits[0].threshold, bits[0].Zp); + + // big or of bitwise XORs + var initial = bits[0].icxor_bit(constant_bits[0]); + jiff.utils.bit_combinator(deferred, 1, bits.length, initial, function (i, prev) { + var xor = bits[i].icxor_bit(constant_bits[i]); + xor = prev.isor_bit(xor, op_id + ':sor_bit:' + (i - 1)); + return xor; + }); + + return result; + }, + /** + * Checks whether given secret shared bits are greater than the given constant + * @function cgt + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are greater than constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + cgt: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cgt)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cgt', bits[0].holders); + } + return jiff.protocols.bits.cgteq(bits, constant + 1, op_id); + }, + /** + * Checks whether given secret shared bits are greater or equal to the given constant + * @function cgteq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are greater or equal to constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit or constant is zero), the result is + * returned immediately as a boolean + */ + cgteq: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.cgteq)'); + } + + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.cgteq', bits[0].holders); + } + + // copy to avoid aliasing problems during execution + bits = bits.slice(); + + // Optimization: the bits are a share of non-negative number, if constant <= 0, return true + if (constant.toString().startsWith('-') || constant.toString() === '0') { + return true; + } + + // decompose result into bits + var constant_bits = jiff.helpers.number_to_bits(constant, bits.length); + if (constant_bits.length > bits.length) { + // Optimization: if constant has more bits, one of them must be 1, constant must be greater than bits. + return false; + } + + // initialize result + var deferred = new jiff.helpers.Deferred(); + var result = new jiff.SecretShare(deferred.promise, bits[0].holders, bits[0].threshold, bits[0].Zp); + + // Subtract bits2 from bits1, only keeping track of borrow + var borrow = bits[0].inot().icmult(constant_bits[0]); + + // compute one bit at a time, propagating borrow + jiff.utils.bit_combinator(deferred, 1, bits.length, borrow, function (i, borrow) { + var xor = bits[i].icxor_bit(constant_bits[i]); + var andNot = bits[i].inot().icmult(constant_bits[i]); + + // save and update borrow + borrow = xor.inot().ismult(borrow, op_id + ':smult:' + (i - 1)); + return borrow.isadd(andNot); + }); + + return result.inot(); + }, + /** + * Checks whether given secret shared bits are less than the given constant + * @function clt + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are less than the constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + clt: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.clt)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.clt', bits[0].holders); + } + var result = jiff.protocols.bits.cgteq(bits, constant, op_id); + if (result === true || result === false) { + return !result; + } + return result.inot(); + }, + /** + * Checks whether given secret shared bits are less or equal to the given constant + * @function clteq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number} constant - the constant number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {SecretShare|boolean} a secret share of 1 if bits are less or equal to constant, 0 otherwise, if result is known + * (e.g. constant has greater non-zero bit than bits' most significant bit), the result is + * returned immediately as a boolean + */ + clteq: function (jiff, bits, constant, op_id) { + if (!(bits[0].isConstant(constant))) { + throw new Error('parameter should be a number (bits.clteq)'); + } + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.clteq', bits[0].holders); + } + var result = jiff.protocols.bits.cgt(bits, constant, op_id); + if (result === true || result === false) { + return !result; + } + return result.inot(); + }, + /** + * Checks whether the two given bitwise secret shared numbers are equal + * @function seq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are equal, 0 otherwise + */ + seq: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.seq', bits1[0].holders); + } + return jiff.protocols.bits.sneq(bits1, bits2, op_id).inot(); + }, + /** + * Checks whether the two given bitwise secret shared numbers are not equal + * @function sneq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if bits are not equal, 0 otherwise + */ + sneq: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.sneq', bits1[0].holders); + } + + var tmp = bits1.length > bits2.length ? bits1 : bits2; + bits2 = bits1.length > bits2.length ? bits2 : bits1; // shortest array + bits1 = tmp; // longest array + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + // initialize result + var deferred = new jiff.helpers.Deferred(); + var result = new jiff.SecretShare(deferred.promise, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + + // big or of bitwise XORs + var initial = bits1[0].isxor_bit(bits2[0], op_id + ':sxor_bit:initial'); + jiff.utils.bit_combinator(deferred, 1, bits1.length, initial, function (i, prev) { + var next; + if (i < bits2.length) { + var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit:' + (i - 1)); + next = prev.isor_bit(xor, op_id + ':sor_bit:' + (i - 1)); + } else { + // xor is equal to bits1[i] since bits2[i] is zero + next = prev.isor_bit(bits1[i], op_id + ':sor_bit:' + (i - 1)); + } + return next; + }); + + return result; + }, + /** + * Checks whether the first given bitwise secret shared number is greater than the second bitwise secret shared number + * @function sgt + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater than the second, 0 otherwise + */ + sgt: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.sgt', bits1[0].holders); + } + + var gteq = jiff.protocols.bits.sgteq(bits1, bits2, op_id + ':bits.sgteq'); + var neq = jiff.protocols.bits.sneq(bits1, bits2, op_id + ':bits.sneq'); + return gteq.ismult(neq, op_id + ':smult'); + }, + /** + * Checks whether the first given bitwise secret shared number is greater than or equal to the second bitwise secret shared number + * @function sgteq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is greater or equal to the second, 0 otherwise + */ + sgteq: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.sgteq', bits1[0].holders); + } + + // copy to avoid aliasing problems during execution + bits1 = bits1.slice(); + bits2 = bits2.slice(); + + // initialize result + var deferred = new jiff.helpers.Deferred(); + var result = new jiff.SecretShare(deferred.promise, bits1[0].holders, Math.max(bits1[0].threshold, bits2[0].threshold), bits1[0].Zp); + + // Subtract bits2 from bits1, only keeping track of borrow + var borrow = bits1[0].inot().ismult(bits2[0], op_id + ':smult:initial'); + var n = Math.max(bits1.length, bits2.length); + jiff.utils.bit_combinator(deferred, 1, n, borrow, function (i, borrow) { + if (i < bits1.length && i < bits2.length) { + var xor = bits1[i].isxor_bit(bits2[i], op_id + ':sxor_bit1:' + (i - 1)); + var andNot = bits1[i].inot().ismult(bits2[i], op_id + ':smult1:' + (i - 1)); + + // save and update borrow + borrow = xor.inot().ismult(borrow, op_id + ':smult2:' + (i - 1)); + borrow = borrow.isadd(andNot); + } else if (i < bits1.length) { + // xor is equal to the value of bits1[i], andNot is equal to 0, since bits[2] is all zeros here + borrow = bits1[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); + } else { // i < bits2.length + // xor and andNot are equal to the value of bits2[i] + borrow = bits2[i].inot().ismult(borrow, op_id + ':smult1:' + (i - 1)); + borrow = borrow.isadd(bits2[i]); + } + + return borrow; + }); + + return result.inot(); + }, + /** + * Checks whether the first given bitwise secret shared number is less than the second bitwise secret shared number + * @function slt + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than the second, 0 otherwise + */ + slt: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.slt', bits1[0].holders); + } + var result = jiff.protocols.bits.sgteq(bits1, bits2, op_id); + return result.inot(); + }, + /** + * Checks whether the first given bitwise secret shared number is less or equal to the second bitwise secret shared number + * @function slteq + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits1 - an array of secret shares of bits, starting from least to most significant bits + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits2 - the second bitwise shared number + * @param {string} [op_id=] - the base operation id to use when generating unique ids for multiplications. + * default value should suffice when the code of all parties executes all instructions + * in the same exact order, otherwise, a unique base name is needed here + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of 1 if the first number is less than or equal to the second, 0 otherwise + */ + slteq: function (jiff, bits1, bits2, op_id) { + if (op_id == null) { + op_id = jiff.counters.gen_op_id('bits.slteq', bits1[0].holders); + } + var result = jiff.protocols.bits.sgt(bits1, bits2, op_id); + return result.inot(); + } }; },{}],24:[function(require,module,exports){ -module.exports = { - /** - * Retrieves preprocessed rejection_sampling bits or performs the rejection sampling on the fly if crypto_provider is enabled - * @function rejection_sampling - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff instance - * @param {number} [lower_bound=0] - the lower bound, included (can be a bigNumber if using bigNumber extension) - * @param {number} [upper_bound=jiff-instance.Zp] - the upper bound, excluded (can be a bigNumber if using bigNumber extension) - * @param {number} [threshold=parties.length] - the threshold of the resulting shares after sampling - * @param {Array} [parties=all_parties] - array of party ids that want to receive (or compute if needed) the sampling shares, by default, this includes all parties - * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly - * @returns {SecretShare[]} an array of secret shares, each representing a bit from the sampled value (from least to most significant) - */ - rejection_sampling: function (jiff, lower_bound, upper_bound, threshold, parties, Zp, op_id) { - // defaults - if (parties == null) { - parties = []; - for (var i = 1; i <= jiff.party_count; i++) { - parties.push(i); - } - } else { - jiff.helpers.sort_ids(parties); - } - - if (op_id == null) { - op_id = jiff.counters.gen_op_id('rejection_sampling', parties); - } - - // try to get preprocessed samples - var result = jiff.get_preprocessing(op_id); - if (result != null && result.ondemand !== true) { - return result; - } - - // Not ready, either preprocess it on demand, or use crypto provider! - lower_bound = lower_bound ? lower_bound : 0; - upper_bound = upper_bound ? upper_bound : jiff.Zp; - if (threshold == null) { - threshold = parties.length; - } - if (Zp == null) { - Zp = jiff.Zp; - } - - var finalLength = jiff.helpers.ceil(jiff.helpers.bLog(upper_bound, 2)); - finalLength = parseInt(finalLength.toString(), 10); - finalLength = Math.max(finalLength, 1); // special case: when upper_bound is 1! - - var many_shares = jiff.utils.many_secret_shares(finalLength, parties, threshold, Zp); - var final_deferreds = many_shares.deferreds; - - // Crypto provider - if (result == null) { - var promise = jiff.from_crypto_provider('numbers', parties, threshold, Zp, op_id, { - max: upper_bound, - min: lower_bound, - bitLength: finalLength, - count: 1 - }); - promise.then(function (result) { - jiff.utils.resolve_many_secrets(final_deferreds, result['shares']); - }); - } else { // preprocess on demand - delete jiff.preprocessing_table[op_id]; - jiff.preprocessing('rejection_sampling', 1, null, threshold, parties, parties, Zp, [op_id], { - lower_bound: lower_bound, - upper_bound: upper_bound - }); - jiff.executePreprocessing(function () { - jiff.utils.resolve_many_secrets(final_deferreds, jiff.get_preprocessing(op_id)); - }); - } - - return many_shares.shares; - }, - - /** - * Creates a secret share of the number represented by the given array of secret shared bits. - * Requires no communication, only local operations - * @function bit_composition - * @ignore - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits. - * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of the number represented by bits. - */ - bit_composition: function (bits) { - var result = bits[0]; - var pow = 1; - for (var i = 1; i < bits.length; i++) { - pow = pow * 2; - result = result.isadd(bits[i].icmult(pow)); - } - return result; - } +module.exports = { + /** + * Retrieves preprocessed rejection_sampling bits or performs the rejection sampling on the fly if crypto_provider is enabled + * @function rejection_sampling + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff instance + * @param {number} [lower_bound=0] - the lower bound, included (can be a bigNumber if using bigNumber extension) + * @param {number} [upper_bound=jiff-instance.Zp] - the upper bound, excluded (can be a bigNumber if using bigNumber extension) + * @param {number} [threshold=parties.length] - the threshold of the resulting shares after sampling + * @param {Array} [parties=all_parties] - array of party ids that want to receive (or compute if needed) the sampling shares, by default, this includes all parties + * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly + * @returns {SecretShare[]} an array of secret shares, each representing a bit from the sampled value (from least to most significant) + */ + rejection_sampling: function (jiff, lower_bound, upper_bound, threshold, parties, Zp, op_id) { + // defaults + if (parties == null) { + parties = []; + for (var i = 1; i <= jiff.party_count; i++) { + parties.push(i); + } + } else { + jiff.helpers.sort_ids(parties); + } + + if (op_id == null) { + op_id = jiff.counters.gen_op_id('rejection_sampling', parties); + } + + // try to get preprocessed samples + var result = jiff.get_preprocessing(op_id); + if (result != null && result.ondemand !== true) { + return result; + } + + // Not ready, either preprocess it on demand, or use crypto provider! + lower_bound = lower_bound ? lower_bound : 0; + upper_bound = upper_bound ? upper_bound : jiff.Zp; + if (threshold == null) { + threshold = parties.length; + } + if (Zp == null) { + Zp = jiff.Zp; + } + + var finalLength = jiff.helpers.ceil(jiff.helpers.bLog(upper_bound, 2)); + finalLength = parseInt(finalLength.toString(), 10); + finalLength = Math.max(finalLength, 1); // special case: when upper_bound is 1! + + var many_shares = jiff.utils.many_secret_shares(finalLength, parties, threshold, Zp); + var final_deferreds = many_shares.deferreds; + + // Crypto provider + if (result == null) { + var promise = jiff.from_crypto_provider('numbers', parties, threshold, Zp, op_id, { + max: upper_bound, + min: lower_bound, + bitLength: finalLength, + count: 1 + }); + promise.then(function (result) { + jiff.utils.resolve_many_secrets(final_deferreds, result['shares']); + }); + } else { // preprocess on demand + delete jiff.preprocessing_table[op_id]; + jiff.preprocessing('rejection_sampling', 1, null, threshold, parties, parties, Zp, [op_id], { + lower_bound: lower_bound, + upper_bound: upper_bound + }); + jiff.executePreprocessing(function () { + jiff.utils.resolve_many_secrets(final_deferreds, jiff.get_preprocessing(op_id)); + }); + } + + return many_shares.shares; + }, + + /** + * Creates a secret share of the number represented by the given array of secret shared bits. + * Requires no communication, only local operations + * @function bit_composition + * @ignore + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits. + * @returns {module:jiff-client~JIFFClient#SecretShare} a secret share of the number represented by bits. + */ + bit_composition: function (bits) { + var result = bits[0]; + var pow = 1; + for (var i = 1; i < bits.length; i++) { + pow = pow * 2; + result = result.isadd(bits[i].icmult(pow)); + } + return result; + } }; },{}],25:[function(require,module,exports){ -module.exports = { - /** - * Share a number as an array of secret bits - * This takes the same parameters as jiff-instance.share, but returns an array of secret bit shares per sending party. - * Each bit array starts with the least significant bit at index 0, and most significant bit at index length-1 - * @function share_bits - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} secret - the number to share (this party's input) - * @param {number} [bit_length=jiff_instance.Zp] - the number of generated bits, if the secret has less bits, it will be - * padded with zeros - * @param {number} [threshold=receivers_list.length] - threshold of each shared bit - * @param {Array} [receivers_list=all_parties] - receivers of every bits - * @param {Array} [senders_list=all_parties] - senders of evey bit - * @param {number} [Zp=jiff_instance.Zp] - the field of sharing for every bit - * @param {string|number} [share_id=auto_gen()] - synchronization id - * @returns {object} a map (of size equal to the number of parties) - * where the key is the party id (from 1 to n) - * and the value is an array of secret shared bits - */ - share_bits: function (jiff, secret, bit_length, threshold, receivers_list, senders_list, Zp, share_id) { - var i; - if (Zp == null) { - Zp = jiff.Zp; - } - if (receivers_list == null) { - receivers_list = []; - for (i = 1; i <= jiff.party_count; i++) { - receivers_list.push(i); - } - } else { - jiff.helpers.sort_ids(receivers_list); - } - if (senders_list == null) { - senders_list = []; - for (i = 1; i <= jiff.party_count; i++) { - senders_list.push(i); - } - } else { - jiff.helpers.sort_ids(senders_list); - } - - if (share_id == null) { - share_id = jiff.counters.gen_op_id2('share_bits', receivers_list, senders_list); - } - - if (bit_length == null) { - bit_length = Zp.toString(2).length; - } - - // to allow for secret=null when party is not a sender - var local_bits = []; - if (secret != null) { - local_bits = jiff.helpers.number_to_bits(secret, bit_length); - } - - var shared_bits = {}; - for (i = 0; i < senders_list.length; i++) { - shared_bits[senders_list[i]] = []; - } - - for (i = 0; i < bit_length; i++) { - var round = jiff.internal_share(local_bits[i], threshold, receivers_list, senders_list, Zp, share_id + ':' + i); - for (var si = 0; si < senders_list.length; si++) { - var pid = senders_list[si]; - shared_bits[pid].push(round[pid]); - } - } - - return shared_bits; - }, - /** - * Opens the given array of secret shared bits. - * This works regardless of whether the represented value fit inside the corresponding field or not - * @function open_bits - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits - * @param {number[]} parties - parties to open (same as jiff_instance.open) - * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open - * @returns {promise} a promise to the number represented by bits - */ - open_bits: function (jiff, bits, parties, op_id) { - // Default values - if (parties == null) { - parties = []; - for (var p = 1; p <= jiff.party_count; p++) { - parties.push(p); - } - } else { - jiff.helpers.sort_ids(parties); - } - - // Compute operation ids (one for each party that will receive a result - if (op_id == null) { - op_id = jiff.counters.gen_op_id2('bits.open', parties, bits[0].holders); - } - - var opened_bits = []; - for (var i = 0; i < bits.length; i++) { - opened_bits[i] = jiff.internal_open(bits[i], parties, op_id + ':' + i); - } - - return Promise.all(opened_bits).then(function (bits) { - return jiff.helpers.bits_to_number(bits, bits.length); - }); - }, - /** - * Receives an opening of an array of secret bits without owning shares of the underlying value. - * Similar to jiff.receive_open() but for bits. - * This works regardless of whether the represented value fit inside the corresponding field or not - * @function receive_open_bits - * @memberOf jiff-instance.protocols.bits - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares - * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result - * @param {number} [count=ceil(log2(Zp))] - the number of bits being opened - * @param {number} [threshold=parties.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders - * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string|number|object} [op_id=auto_gen()] - unique and consistent synchronization id between all parties - * @returns {promise} a (JQuery) promise to the open value of the secret - */ - receive_open_bits: function (jiff, senders, receivers, count, threshold, Zp, op_id) { - if (senders == null) { - throw new Error('Must provide "senders" parameter in receive_open'); - } - jiff.helpers.sort_ids(senders); - // Default values - if (receivers == null) { - receivers = []; - for (i = 1; i <= jiff.party_count; i++) { - receivers.push(i); - } - } else { - jiff.helpers.sort_ids(receivers); - } - - if (op_id == null) { - op_id = jiff.counters.gen_op_id2('bits.open', receivers, senders); - } - - if (count == null) { - if (Zp == null) { - Zp = jiff.Zp; - } - count = Zp.toString(2).length; - } - - var opened_bits = []; - for (var i = 0; i < count; i++) { - opened_bits[i] = jiff.receive_open(senders, receivers, threshold, Zp, op_id + ':' + i); - } - - return Promise.all(opened_bits).then(function (bits) { - return jiff.helpers.bits_to_number(bits, bits.length); - }); - } +module.exports = { + /** + * Share a number as an array of secret bits + * This takes the same parameters as jiff-instance.share, but returns an array of secret bit shares per sending party. + * Each bit array starts with the least significant bit at index 0, and most significant bit at index length-1 + * @function share_bits + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} secret - the number to share (this party's input) + * @param {number} [bit_length=jiff_instance.Zp] - the number of generated bits, if the secret has less bits, it will be + * padded with zeros + * @param {number} [threshold=receivers_list.length] - threshold of each shared bit + * @param {Array} [receivers_list=all_parties] - receivers of every bits + * @param {Array} [senders_list=all_parties] - senders of evey bit + * @param {number} [Zp=jiff_instance.Zp] - the field of sharing for every bit + * @param {string|number} [share_id=auto_gen()] - synchronization id + * @returns {object} a map (of size equal to the number of parties) + * where the key is the party id (from 1 to n) + * and the value is an array of secret shared bits + */ + share_bits: function (jiff, secret, bit_length, threshold, receivers_list, senders_list, Zp, share_id) { + var i; + if (Zp == null) { + Zp = jiff.Zp; + } + if (receivers_list == null) { + receivers_list = []; + for (i = 1; i <= jiff.party_count; i++) { + receivers_list.push(i); + } + } else { + jiff.helpers.sort_ids(receivers_list); + } + if (senders_list == null) { + senders_list = []; + for (i = 1; i <= jiff.party_count; i++) { + senders_list.push(i); + } + } else { + jiff.helpers.sort_ids(senders_list); + } + + if (share_id == null) { + share_id = jiff.counters.gen_op_id2('share_bits', receivers_list, senders_list); + } + + if (bit_length == null) { + bit_length = Zp.toString(2).length; + } + + // to allow for secret=null when party is not a sender + var local_bits = []; + if (secret != null) { + local_bits = jiff.helpers.number_to_bits(secret, bit_length); + } + + var shared_bits = {}; + for (i = 0; i < senders_list.length; i++) { + shared_bits[senders_list[i]] = []; + } + + for (i = 0; i < bit_length; i++) { + var round = jiff.internal_share(local_bits[i], threshold, receivers_list, senders_list, Zp, share_id + ':' + i); + for (var si = 0; si < senders_list.length; si++) { + var pid = senders_list[si]; + shared_bits[pid].push(round[pid]); + } + } + + return shared_bits; + }, + /** + * Opens the given array of secret shared bits. + * This works regardless of whether the represented value fit inside the corresponding field or not + * @function open_bits + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare[]} bits - an array of the secret shares of bits, starting from least to most significant bits + * @param {number[]} parties - parties to open (same as jiff_instance.open) + * @param {string|number} [op_id=auto_gen()] - same as jiff_instance.open + * @returns {promise} a promise to the number represented by bits + */ + open_bits: function (jiff, bits, parties, op_id) { + // Default values + if (parties == null) { + parties = []; + for (var p = 1; p <= jiff.party_count; p++) { + parties.push(p); + } + } else { + jiff.helpers.sort_ids(parties); + } + + // Compute operation ids (one for each party that will receive a result + if (op_id == null) { + op_id = jiff.counters.gen_op_id2('bits.open', parties, bits[0].holders); + } + + var opened_bits = []; + for (var i = 0; i < bits.length; i++) { + opened_bits[i] = jiff.internal_open(bits[i], parties, op_id + ':' + i); + } + + return Promise.all(opened_bits).then(function (bits) { + return jiff.helpers.bits_to_number(bits, bits.length); + }); + }, + /** + * Receives an opening of an array of secret bits without owning shares of the underlying value. + * Similar to jiff.receive_open() but for bits. + * This works regardless of whether the represented value fit inside the corresponding field or not + * @function receive_open_bits + * @memberOf jiff-instance.protocols.bits + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {Array} senders - an array with party ids (1 to n) specifying the parties sending the shares + * @param {Array} [receivers=all_parties] - an array with party ids (1 to n) specifying the parties receiving the result + * @param {number} [count=ceil(log2(Zp))] - the number of bits being opened + * @param {number} [threshold=parties.length] - the min number of parties needed to reconstruct the secret, defaults to all the senders + * @param {number} [Zp=jiff_instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string|number|object} [op_id=auto_gen()] - unique and consistent synchronization id between all parties + * @returns {promise} a (JQuery) promise to the open value of the secret + */ + receive_open_bits: function (jiff, senders, receivers, count, threshold, Zp, op_id) { + if (senders == null) { + throw new Error('Must provide "senders" parameter in receive_open'); + } + jiff.helpers.sort_ids(senders); + // Default values + if (receivers == null) { + receivers = []; + for (i = 1; i <= jiff.party_count; i++) { + receivers.push(i); + } + } else { + jiff.helpers.sort_ids(receivers); + } + + if (op_id == null) { + op_id = jiff.counters.gen_op_id2('bits.open', receivers, senders); + } + + if (count == null) { + if (Zp == null) { + Zp = jiff.Zp; + } + count = Zp.toString(2).length; + } + + var opened_bits = []; + for (var i = 0; i < count; i++) { + opened_bits[i] = jiff.receive_open(senders, receivers, threshold, Zp, op_id + ':' + i); + } + + return Promise.all(opened_bits).then(function (bits) { + return jiff.helpers.bits_to_number(bits, bits.length); + }); + } }; },{}],26:[function(require,module,exports){ -// Generic version of operations -module.exports = function (SecretShare) { - /** - * bitwise-XOR with a constant (BOTH BITS). - * @method cxor_bit - * @param {number} cst - the constant bit to XOR with (0 or 1). - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cxor_bit = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (^)'); - } - if (!this.jiff.share_helpers['binary'](cst)) { - throw new Error('parameter should be binary (^)'); - } - - return this.icadd(cst).issub(this.icmult(cst).icmult(2)); - }; - - /** - * bitwise-OR with a constant (BOTH BITS). - * @method cor_bit - * @param {number} cst - the constant bit to OR with (0 or 1). - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cor_bit = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (|)'); - } - if (!this.jiff.share_helpers['binary'](cst)) { - throw new Error('parameter should be binary (|)'); - } - - return this.icadd(cst).issub(this.icmult(cst)); - }; - - /** - * bitwise-XOR of two secret shares OF BITS. - * @method sxor_bit - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to XOR with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sxor_bit = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (^)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (^)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (^)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sxor_bit', this.holders); - } - - return this.isadd(o).issub(this.ismult(o, op_id + ':smult1').icmult(2)); - }; - - /** - * OR of two secret shares OF BITS. - * @method sor_bit - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to OR with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sor_bit = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (|)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (|)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (|)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sor_bit', this.holders); - } - - return this.isadd(o).issub(this.ismult(o, op_id + ':smult1')); - }; - - /** - * Negation of a bit. - * This has to be a share of a BIT in order for this to work properly. - * @method not - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result (negated bit). - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.not = function () { - return this.icmult(-1).icadd(1); - }; - - /** - * Simulate an oblivious If-else statement with a single return value. - * Should be called on a secret share of a bit: 0 representing false, and 1 representing true - * If this is a share of 1, a new sharing of the element represented by the first parameter is returned, - * otherwise, a new sharing of the second is returned. - * @method if_else - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {module:jiff-client~JIFFClient#SecretShare | number} trueVal - the value/share to return if this is a sharing of 1. - * @param {module:jiff-client~JIFFClient#SecretShare | number} falseVal - the value/share to return if this is a sharing of 0. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} a new sharing of the result of the if. - * - * @example - * // a and b are secret shares - * // cmp will be a secret share of either 1 or 0, depending on whether a or b is greater - * var cmp = a.gt(b); - * - * // max is set to the greater value, without revealing the value or the result of the inequality - * var max = cmp.if_else(a, b); - */ - SecretShare.prototype.if_else = function (trueVal, falseVal, op_id) { - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('if_else', this.holders); - } - - var const1 = this.isConstant(trueVal); - var const2 = this.isConstant(falseVal); - if (const1 && const2) { - return this.icmult(trueVal).isadd(this.inot().icmult(falseVal)); - } else if (const1) { - return this.inot().ismult(falseVal.icsub(trueVal), op_id + ':smult').icadd(trueVal); - } else if (const2) { - return this.ismult(trueVal.icsub(falseVal), op_id + ':smult').icadd(falseVal); - } else { - return this.ismult(trueVal.issub(falseVal), op_id + ':smult').isadd(falseVal); - } - }; +// Generic version of operations +module.exports = function (SecretShare) { + /** + * bitwise-XOR with a constant (BOTH BITS). + * @method cxor_bit + * @param {number} cst - the constant bit to XOR with (0 or 1). + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cxor_bit = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (^)'); + } + if (!this.jiff.share_helpers['binary'](cst)) { + throw new Error('parameter should be binary (^)'); + } + + return this.icadd(cst).issub(this.icmult(cst).icmult(2)); + }; + + /** + * bitwise-OR with a constant (BOTH BITS). + * @method cor_bit + * @param {number} cst - the constant bit to OR with (0 or 1). + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cor_bit = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (|)'); + } + if (!this.jiff.share_helpers['binary'](cst)) { + throw new Error('parameter should be binary (|)'); + } + + return this.icadd(cst).issub(this.icmult(cst)); + }; + + /** + * bitwise-XOR of two secret shares OF BITS. + * @method sxor_bit + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to XOR with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sxor_bit = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (^)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (^)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (^)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sxor_bit', this.holders); + } + + return this.isadd(o).issub(this.ismult(o, op_id + ':smult1').icmult(2)); + }; + + /** + * OR of two secret shares OF BITS. + * @method sor_bit + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to OR with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sor_bit = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (|)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (|)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (|)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sor_bit', this.holders); + } + + return this.isadd(o).issub(this.ismult(o, op_id + ':smult1')); + }; + + /** + * Negation of a bit. + * This has to be a share of a BIT in order for this to work properly. + * @method not + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result (negated bit). + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.not = function () { + return this.icmult(-1).icadd(1); + }; + + /** + * Simulate an oblivious If-else statement with a single return value. + * Should be called on a secret share of a bit: 0 representing false, and 1 representing true + * If this is a share of 1, a new sharing of the element represented by the first parameter is returned, + * otherwise, a new sharing of the second is returned. + * @method if_else + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {module:jiff-client~JIFFClient#SecretShare | number} trueVal - the value/share to return if this is a sharing of 1. + * @param {module:jiff-client~JIFFClient#SecretShare | number} falseVal - the value/share to return if this is a sharing of 0. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} a new sharing of the result of the if. + * + * @example + * // a and b are secret shares + * // cmp will be a secret share of either 1 or 0, depending on whether a or b is greater + * var cmp = a.gt(b); + * + * // max is set to the greater value, without revealing the value or the result of the inequality + * var max = cmp.if_else(a, b); + */ + SecretShare.prototype.if_else = function (trueVal, falseVal, op_id) { + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('if_else', this.holders); + } + + var const1 = this.isConstant(trueVal); + var const2 = this.isConstant(falseVal); + if (const1 && const2) { + return this.icmult(trueVal).isadd(this.inot().icmult(falseVal)); + } else if (const1) { + return this.inot().ismult(falseVal.icsub(trueVal), op_id + ':smult').icadd(trueVal); + } else if (const2) { + return this.ismult(trueVal.icsub(falseVal), op_id + ':smult').icadd(falseVal); + } else { + return this.ismult(trueVal.issub(falseVal), op_id + ':smult').isadd(falseVal); + } + }; }; },{}],27:[function(require,module,exports){ -// Generic version of operations -module.exports = function (SecretShare) { - /** - * Checks if the given parameter is a constant, used to determine whether constant or secret - * operations should be executed when the generic version of an operation is called - * @method isConstant - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {number/object} o - the parameter to determine. - * @return {boolean} true if o is a valid constant, false otherwise. - */ - SecretShare.prototype.isConstant = function (o) { - return typeof(o) === 'number'; - }; - - /** - * Generic Addition. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method add - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * - * @example - * var shares = jiffClient.share(input); - * // this will add two secret shared values together - * var sum1 = shares[1].add(shares[2]); - * // this will add 3 to the secret input from party 1 - * var sum2 = shares[1].add(3); - * // both sum1 and sum2 are SecretShares - */ - SecretShare.prototype.add = function (o) { - if (this.isConstant(o)) { - return this.cadd(o); - } - return this.sadd(o); - }; - - - /** - * Generic Subtraction. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method sub - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sub = function (o) { - if (this.isConstant(o)) { - return this.csub(o); - } - return this.ssub(o); - }; - - - /** - * Generic Multiplication. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method mult - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). - * This id must be unique, and must be passed by all parties to the same instruction. - * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id - * is generated by increasing a local counter, default ids suffice when all parties execute the - * instructions in the same order. Only used if secret multiplication is used. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.mult = function (o, op_id) { - if (this.isConstant(o)) { - return this.cmult(o); - } - return this.smult(o, op_id); - }; - - - /** - * Generic XOR for bits (both this and o have to be bits to work correctly). - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method xor_bit - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * Only used if secret xor is used.. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.xor_bit = function (o, op_id) { - if (this.isConstant(o)) { - return this.cxor_bit(o); - } - return this.sxor_bit(o, op_id); - }; - - /** - * Generic OR for bits (both this and o have to be bits to work correctly). - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method or_bit - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * Only used if secret or is used.. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.or_bit = function (o, op_id) { - if (this.isConstant(o)) { - return this.cor_bit(o); - } - return this.sor_bit(o, op_id); - }; - - /** - * Generic Greater or equal. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method gteq - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.gteq = function (o, op_id) { - if (this.isConstant(o)) { - return this.cgteq(o, op_id); - } - return this.sgteq(o); - }; - - - /** - * Generic Greater than. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method gt - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.gt = function (o, op_id) { - if (this.isConstant(o)) { - return this.cgt(o, op_id); - } - return this.sgt(o, op_id); - }; - - - /** - * Generic Less or equal. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method lteq - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.lteq = function (o, op_id) { - if (this.isConstant(o)) { - return this.clteq(o, op_id); - } - return this.slteq(o, op_id); - }; - - - /** - * Generic Less than. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method lt - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.lt = function (o, op_id) { - if (this.isConstant(o)) { - return this.clt(o, op_id); - } - return this.slt(o, op_id); - }; - - - /** - * Generic Equals. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method eq - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.eq = function (o, op_id) { - if (this.isConstant(o)) { - return this.ceq(o, op_id); - } - return this.seq(o, op_id); - }; - - - /** - * Generic Not Equals. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method neq - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.neq = function (o, op_id) { - if (this.isConstant(o)) { - return this.cneq(o, op_id); - } - return this.sneq(o, op_id); - }; - - - /** - * Generic Integer Divison. - * Uses either the constant or secret version of this operator depending on type of paramter. - * @method div - * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). - * @param {number} l - the maximum bit length of the two shares. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.div = function (o, l, op_id) { - if (this.isConstant(o)) { - return this.cdiv(o, l, op_id); - } - return this.sdiv(o, l, op_id); - }; +// Generic version of operations +module.exports = function (SecretShare) { + /** + * Checks if the given parameter is a constant, used to determine whether constant or secret + * operations should be executed when the generic version of an operation is called + * @method isConstant + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {number/object} o - the parameter to determine. + * @return {boolean} true if o is a valid constant, false otherwise. + */ + SecretShare.prototype.isConstant = function (o) { + return typeof(o) === 'number'; + }; + + /** + * Generic Addition. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method add + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * + * @example + * var shares = jiffClient.share(input); + * // this will add two secret shared values together + * var sum1 = shares[1].add(shares[2]); + * // this will add 3 to the secret input from party 1 + * var sum2 = shares[1].add(3); + * // both sum1 and sum2 are SecretShares + */ + SecretShare.prototype.add = function (o) { + if (this.isConstant(o)) { + return this.cadd(o); + } + return this.sadd(o); + }; + + + /** + * Generic Subtraction. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method sub + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sub = function (o) { + if (this.isConstant(o)) { + return this.csub(o); + } + return this.ssub(o); + }; + + + /** + * Generic Multiplication. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method mult + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). + * This id must be unique, and must be passed by all parties to the same instruction. + * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id + * is generated by increasing a local counter, default ids suffice when all parties execute the + * instructions in the same order. Only used if secret multiplication is used. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.mult = function (o, op_id) { + if (this.isConstant(o)) { + return this.cmult(o); + } + return this.smult(o, op_id); + }; + + + /** + * Generic XOR for bits (both this and o have to be bits to work correctly). + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method xor_bit + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * Only used if secret xor is used.. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.xor_bit = function (o, op_id) { + if (this.isConstant(o)) { + return this.cxor_bit(o); + } + return this.sxor_bit(o, op_id); + }; + + /** + * Generic OR for bits (both this and o have to be bits to work correctly). + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method or_bit + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * Only used if secret or is used.. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.or_bit = function (o, op_id) { + if (this.isConstant(o)) { + return this.cor_bit(o); + } + return this.sor_bit(o, op_id); + }; + + /** + * Generic Greater or equal. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method gteq + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.gteq = function (o, op_id) { + if (this.isConstant(o)) { + return this.cgteq(o, op_id); + } + return this.sgteq(o); + }; + + + /** + * Generic Greater than. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method gt + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.gt = function (o, op_id) { + if (this.isConstant(o)) { + return this.cgt(o, op_id); + } + return this.sgt(o, op_id); + }; + + + /** + * Generic Less or equal. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method lteq + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.lteq = function (o, op_id) { + if (this.isConstant(o)) { + return this.clteq(o, op_id); + } + return this.slteq(o, op_id); + }; + + + /** + * Generic Less than. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method lt + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.lt = function (o, op_id) { + if (this.isConstant(o)) { + return this.clt(o, op_id); + } + return this.slt(o, op_id); + }; + + + /** + * Generic Equals. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method eq + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.eq = function (o, op_id) { + if (this.isConstant(o)) { + return this.ceq(o, op_id); + } + return this.seq(o, op_id); + }; + + + /** + * Generic Not Equals. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method neq + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.neq = function (o, op_id) { + if (this.isConstant(o)) { + return this.cneq(o, op_id); + } + return this.sneq(o, op_id); + }; + + + /** + * Generic Integer Divison. + * Uses either the constant or secret version of this operator depending on type of paramter. + * @method div + * @param {number|module:jiff-client~JIFFClient#SecretShare} o - the other operand (can be either number or share). + * @param {number} l - the maximum bit length of the two shares. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.div = function (o, l, op_id) { + if (this.isConstant(o)) { + return this.cdiv(o, l, op_id); + } + return this.sdiv(o, l, op_id); + }; }; },{}],28:[function(require,module,exports){ -// Arithmetic operations on shares -module.exports = function (SecretShare) { - /** - * Addition with a constant. - * @method cadd - * @param {number} cst - the constant to add. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cadd = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (+)'); - } - - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['+'](self.value, cst), self.Zp); - }; - - return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); - }; - - /** - * Subtraction with a constant. - * @method csub - * @param {number} cst - the constant to subtract from this share. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.csub = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (-)'); - } - - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['-'](self.value, cst), self.Zp); - }; - - return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); - }; - - /** - * Multiplication by a constant. - * @method cmult - * @param {number} cst - the constant to multiply to this share. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cmult = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (*)'); - } - - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, cst), self.Zp); - }; - - return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); - }; - - /** - * Division by a constant factor of the number represented by the share. - * @method cdivfac - * @param {number} cst - the constant by which to divide the share. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cdivfac = function (cst) { - if (!(this.isConstant(cst))) { - throw new Error('Parameter should be a number (cdivfac)'); - } - - var inv = this.jiff.helpers.extended_gcd(cst, this.Zp)[0]; - - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, inv), self.Zp); - }; - - return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); - }; - - /** - * Addition of two secret shares. - * @method sadd - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to add to this share. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * - * @example - * // share a value with all parties, and sum the values of all shares - * var shares = jiff_instance.share(x); - * var sum = shares[1]; - * for (var i = 2; i <= jiff_instance.party_count; i++) { - * sum = sum.sadd(shares[i]); - * } - * - */ - SecretShare.prototype.sadd = function (o) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (+)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (+)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (+)'); - } - - // add the two shares when ready locally - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['+'](self.value, o.value), self.Zp); - }; +/* + * the IO object to be used for OT + * to pass as the IO parameter for 1-out-of-N. + * + */ +// IO send +const give = function (op_id,session_id,extras,tag,msg) { + /* give a message */ + const createMSGObj=function (msg,op_id,tag,jiff) { + var four_opts={}; + four_opts['opts']=msg; + four_opts['sender_id']=jiff.id; + four_opts['op_id']=op_id; + four_opts['tag']=tag; + return four_opts; + }; + var jiff=extras[0];//extras.length-1 + var ids=parse__OT_id(op_id); + var four_opts=createMSGObj(msg,op_id,tag,jiff) ; + four_opts = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'open', four_opts], 2); + msg=JSON.stringify(four_opts);// jason object + var to_party=ids[1]; + if (jiff.id===ids[1]) { + to_party=ids[0]; + } + var message_to_send = {tag: 'OT', party_id: to_party, message: msg, encrypted: true}; + message_to_send = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'custom', message_to_send], 2); + + if (message_to_send['encrypted'] !== false) { + message_to_send['message'] = jiff.hooks.encryptSign(jiff, message_to_send['message'], jiff.keymap[message_to_send['party_id']], jiff.secret_key); + message_to_send['encrypted'] = true; + } + + jiff.socket.safe_emit('OT', JSON.stringify(message_to_send)); + return ; +}; + + +// IO receive +const get = function (op_id,session_id, extras,tag) { + /* get a message */ + var jiff=extras[extras.length-1]; + var ids=parse__OT_id(op_id); + var shareid=op_id+'-'+tag; + var from_party=ids[0]; + if (jiff.id===ids[0]) { + from_party=ids[1]; + } + + if (jiff.deferreds[shareid] == null) { + jiff.deferreds[shareid] = {}; + } + if (jiff.deferreds[shareid][from_party] == null) { // not ready, setup a deferred + jiff.deferreds[shareid][from_party] = new jiff.helpers.Deferred(); + } + // resolving in customized listen + return jiff.deferreds[shareid][from_party].promise; +}; + +// helper function to get from_id and to_id from op_id +function parse__OT_id(op_id) { + var re=[]; + var temp=(op_id.split(':')[3]).split('-'); + var to=parseInt(temp[2]); // sending msg to partyid + var from=parseInt(temp[1]); + re.push(from); + re.push(to); + + return re; + +} + +module.exports = { + give: give, + get: get +}; - // promise to execute ready_add when both are ready - return new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, Math.max(this.threshold, o.threshold), this.Zp); - }; +},{}],29:[function(require,module,exports){ + +module.exports = function (SecretShare) { + /** + * xor of two secret shares. + * @method gmw_xor + * @param {module:jiff-client~JIFFClient#SecretShare} share2 - the share to xor with this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result( ci=ai^bi). + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * + * @example + * // share a value with all parties, and xor the values of two shares + * var shares = jiff_instance.gmw_share(x); + * var xor_re= shares[1].gmw_xor(shares[2]); + * jiff_instance.gmw_open(xor_re); + * + */ + + SecretShare.prototype.gmw_xor = function (share2) { + if (!(this.jiff === share2.jiff)) { + throw new Error('shares do not belong to the same instance (^)'); + } + if (!this.jiff.helpers.Zp_equals(this, share2)) { + throw new Error('shares must belong to the same field (^)'); + } + if (!this.jiff.helpers.array_equals(this.holders, share2.holders)) { + throw new Error('shares must be held by the same parties (^)'); + } + + // XOR the two shares when ready locally + var self = this; + var ready = function () { + var re=self.value ^ share2.value; + return re; + }; + // promise to execute ready_XOR when both are ready + return new this.jiff.SecretShare(this.when_both_ready(share2, ready), this.holders, Math.max(this.threshold, share2.threshold), this.Zp); + }; + + /** + * and of two secret shares. + * @method gmw_and + * @param {module:jiff-client~JIFFClient#SecretShare} share2 - the share to and with this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result( ci=ai&bi). + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * + * @example + * // share a value with all parties, and xor the values of two shares + * var shares = jiff_instance.gmw_share(x); + * var xor_re= shares[1].gmw_xor(shares[2]); + * var and_re= xor_re.gmw_and(shares[2]); + * jiff_instance.gmw_open(and_re); + * + */ + SecretShare.prototype.gmw_and = function (share2) { + if (!(this.jiff === share2.jiff)) { + throw new Error('shares do not belong to the same instance (^)'); + } + if (!(this.jiff.helpers.Zp_equals(this, share2)&& share2.Zp===2) ) { + throw new Error('shares must belong to the same field and shares\'Zp must equals 2 (^)'); + } + + if (!this.jiff.helpers.array_equals(this.holders, share2.holders)) { + throw new Error('shares must be held by the same parties (^)'); + } + + var self=this; + // AND the two shares when ready + var ready = function () { + var jiff=self.jiff; + var final_deferred = new jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var csecret=[]; + csecret.push(self.value); + csecret.push(share2.value); + var OT=jiff.OT; + + // receiving list of OT msg + var share_id ; + if (share_id==null) { + share_id= jiff.counters.gen_op_id2('otshare', self.holders, self.holders); + } + var my_count=[];//list of promises needs to be resolve + // generate OT msg + const four_opts=OTGate(csecret);//eg.[0,1,1,0] + // OT send process, send OT msg to small party_ids + OT.then(function (OT) { + for (var k=1;k} [parties=all_parties] - an array with party ids of receiving parties + * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages + * @returns {?promise} a (JQuery) promise to the open value of the secret, or null if the calling party is not a receiving party + * + */ + gmw_open: function (jiff, share, parties, op_id) { + var i; + if (!(share.jiff === jiff)) { + throw 'share does not belong to given instance'; + } + + // Default values + if (parties == null || parties === []) { + parties = []; + for (i = 1; i <= jiff.party_count; i++) { + parties.push(i); + } + } else { + jiff.helpers.sort_ids(parties); + } + + // If not a receiver nor holder, do nothing + + if (share.holders.indexOf(jiff.id) === -1 && parties.indexOf(jiff.id) === -1) { + return null; + } + + // Compute operation ids (one for each party that will receive a result + if (op_id == null) { + op_id = jiff.counters.gen_op_id2('GMW_open', parties, share.holders); + } + // Party is a holder + if (share.holders.indexOf(jiff.id) > -1) { + // Call hook + share = jiff.hooks.execute_array_hooks('beforeOpen', [jiff, share, parties], 1); + // The given share has been computed, broadcast it to all parties + jiff.counters.pending_opens++; + share.wThen(function () { + jiff.counters.pending_opens--; + jiff_broadcast(jiff, share, parties, op_id); + }, share.error); + } + + // Party is a receiver + if (parties.indexOf(jiff.id) > -1) { + var final_deferred = new jiff.helpers.Deferred(); // will be resolved when the final value is reconstructed + var final_promise = final_deferred.promise; + + if (jiff.deferreds[op_id] == null) { + jiff.deferreds[op_id] = {}; + } + + jiff.deferreds[op_id].deferred = final_deferred; + jiff.deferreds[op_id].threshold = share.threshold; + jiff.deferreds[op_id].total = share.holders.length; + if (jiff.deferreds[op_id].shares != null && jiff.deferreds[op_id].shares.length >= share.threshold) { + final_deferred.resolve(); + } + return final_promise.then(function () { + var shares = jiff.deferreds[op_id].shares; + + if (shares.length === jiff.deferreds[op_id].total) { + delete jiff.deferreds[op_id]; + } else { + jiff.deferreds[op_id].deferred = 'CLEAN'; + } + var recons_secret = gmw_reconstruct(jiff,shares); + recons_secret = jiff.hooks.execute_array_hooks('afterReconstructShare', [jiff, recons_secret], 1); + return recons_secret; + }); + } + + return null; + }, + +}; + - /** - * Subtraction of two secret shares. - * @method ssub - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to subtract from this share. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.ssub = function (o) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (-)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (-)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (-)'); - } - - // subtract the two shares when ready locally - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['-'](self.value, o.value), self.Zp); - }; - - // promise to execute ready_add when both are ready - return new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, Math.max(this.threshold, o.threshold), this.Zp); - }; - - /** - * Multiplication of two secret shares through Beaver Triplets. - * @method smult - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to multiply with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). - * This id must be unique, and must be passed by all parties to the same instruction. - * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id - * is generated by increasing a local counter, default ids suffice when all parties execute the - * instructions in the same order. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.smult = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (*)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (*)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (*)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('smult', this.holders); - } - - // final result - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, Math.max(this.threshold, o.threshold), this.Zp); - - // called when triplet is ready - var self = this; - var ready_triplet = function (triplet) { - var a = triplet[0]; - var b = triplet[1]; - var c = triplet[2]; - - // d = s - a. e = o - b. - var d = self.isadd(a.icmult(-1)); - var e = o.isadd(b.icmult(-1)); - - // Open d and e. - // The only communication cost. - var e_promise = self.jiff.internal_open(e, e.holders, op_id + ':open1'); - var d_promise = self.jiff.internal_open(d, d.holders, op_id + ':open2'); - Promise.all([e_promise, d_promise]).then(function (arr) { - var e_open = arr[0]; - var d_open = arr[1]; - - // result_share = d_open * e_open + d_open * b_share + e_open * a_share + c. - var t1 = self.jiff.helpers.mod(self.jiff.share_helpers['*'](d_open, e_open), self.Zp); - var t2 = b.icmult(d_open); - var t3 = a.icmult(e_open); - - // All this happens locally. - var final_result = t2.icadd(t1); - final_result = final_result.isadd(t3); - final_result = final_result.isadd(c); - - final_result.wThen(final_deferred.resolve); - }); - }; - - // Get shares of triplets. - var triplet = this.jiff.get_preprocessing(op_id + ':triplet'); - if (triplet == null) { - var promise = this.jiff.from_crypto_provider('triplet', this.holders, Math.max(this.threshold, o.threshold), this.Zp, op_id + ':triplet'); - promise.then(function (msg) { - ready_triplet(msg['shares']); - }); - } else { - ready_triplet(triplet); - } - - return result; - }; - - /** - * Multiplication of two secret shares through BGW protocol. - * @method smult_bgw - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to multiply with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). - * This id must be unique, and must be passed by all parties to the same instruction. - * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id - * is generated by increasing a local counter, default ids suffice when all parties execute the - * instructions in the same order. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.smult_bgw = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (bgw*)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (bgw*)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (bgw*)'); - } - if ((this.threshold - 1) + (o.threshold - 1) > this.holders.length - 1) { - throw new Error('threshold too high for BGW (*)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('smult_bgw', this.holders); - } - - // ensure thresholds are fine - var new_threshold = (this.threshold - 1) + (o.threshold - 1) + 1; - if (new_threshold > this.holders) { - var errorMsg = 'Threshold too large for smult_bgw: ' + new_threshold; - errorMsg += '. Shares: ' + this.toString() + ', ' + o.toString(); - throw new Error(errorMsg); - } - - // multiply via the BGW protocol - var self = this; - var ready = function () { - return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, o.value), self.Zp); - }; - - // reshare to reduce threshold and return when ready - var result = new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, new_threshold, this.Zp); - return this.jiff.reshare(result, Math.max(this.threshold, o.threshold), result.holders, result.holders, result.Zp, op_id + ':threshold'); - }; - - /** - * Integer divison with two shares (this / o) - * @method sdiv - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to divide by. - * @param {number} [l=ceil(log_2(this.Zp))] - the maximum bit length of either operands. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sdiv = function (o, l, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (!=)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (!=)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (!=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sdiv', this.holders); - } - - // figure out maximum output bit length - var lZp = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); - l = (l != null && l < lZp) ? l : lZp; - - // Convert to bits - var dividend_bits = this.bit_decomposition(op_id + ':decomposition1').slice(0, l); - var divisor_bits = o.bit_decomposition(op_id + ':decomposition2').slice(0, l); - - // Compute by long division - var quotient_bits = this.jiff.protocols.bits.sdiv(dividend_bits, divisor_bits, op_id + ':bits.sdiv').quotient; - - // Convert to number and return - return this.jiff.protocols.bits.bit_composition(quotient_bits); - }; - - /** - * Integer divison with a share and a constant (this / cst). - * @method cdiv - * @param {module:jiff-client~JIFFClient#SecretShare} cst - the constant to divide by. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cdiv = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (/)'); - } - - if (this.jiff.share_helpers['<='](cst, 0)) { - throw new Error('divisor must be > 0 (cst/): ' + cst); - } - - if (this.jiff.share_helpers['<='](this.Zp, cst)) { - throw new Error('divisor must be < share.Zp (' + this.Zp + ') in (cst/): ' + cst); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('cdiv', this.holders); - } - - // Allocate share for result to which the answer will be resolved once available - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); - - // Execute protocol when random in noise in [0, Zp) and quotient floor(noise/constant) is ready! - var self = this; - var ready_quotient = function (noise, nOVERc) { - // Use noise - var noisyX = self.isadd(noise); - self.jiff.internal_open(noisyX, noisyX.holders, op_id + ':open').then(function (noisyX) { - var wrapped = self.icgt(noisyX, op_id + ':wrap_cgt'); // 1 => x + noise wrapped around Zp, 0 otherwise - - // if we did not wrap - var noWrapDiv = self.jiff.share_helpers['floor/'](noisyX, cst); - var unCorrectedQuotient = nOVERc.icmult(-1).icadd(noWrapDiv).icsub(1); - var verify = self.issub(unCorrectedQuotient.icmult(cst)); - var isNotCorrect = verify.icgteq(cst, op_id + ':cor1'); - var noWrapAnswer = unCorrectedQuotient.isadd(isNotCorrect); // if incorrect => isNotCorrect = 1 => quotient = unCorrectedQuotient - 1 - - // if we wrapped - var wrapDiv = self.jiff.share_helpers['floor/'](self.jiff.share_helpers['+'](noisyX, self.Zp), cst); - unCorrectedQuotient = nOVERc.icmult(-1).icadd(wrapDiv).icsub(1); - verify = self.issub(unCorrectedQuotient.icmult(cst)); - isNotCorrect = verify.icgteq(cst, op_id + ':cor2'); - var wrapAnswer = unCorrectedQuotient.isadd(isNotCorrect); // if incorrect => isNotCorrect = 1 => quotient = unCorrectedQuotient - 1 - - var answer = noWrapAnswer.isadd(wrapped.ismult(wrapAnswer.issub(noWrapAnswer), op_id + ':smult')); - answer.wThen(final_deferred.resolve); - }); - }; - - // Preprocessing cases - var quotient = this.jiff.get_preprocessing(op_id + ':quotient'); - if (quotient == null) { // case 1: no preprocessing with crypto provider! - var promise = this.jiff.from_crypto_provider('quotient', this.holders, this.threshold, this.Zp, op_id + ':quotient', {constant: cst}); - promise.then(function (msg) { - ready_quotient(msg['shares'][0], msg['shares'][1]); - }); - } else if (quotient.ondemand === true) { // case 2: constant was not available at preprocessing time, must do it now! - this.jiff.preprocessing('quotient', 1, null, this.threshold, this.holders, this.holders, this.Zp, [op_id + ':quotient'], {constant: cst, namespace: 'base'}); - this.jiff.executePreprocessing(function () { - var quotient = self.jiff.get_preprocessing(op_id + ':quotient'); - ready_quotient(quotient.r, quotient.q); - }); - } else { // case 3: preprocessing is completed! - ready_quotient(quotient.r, quotient.q); - } - - // special case, if result is zero, sometimes we will get to -1 due to how correction happens above (.csub(1) and then compare) - var zeroIt = this.iclt(cst, op_id + ':zero_check').inot(); - return result.ismult(zeroIt, op_id + ':zero_it'); - }; - - /** - * Remainder with two shares (this % o) - * @method smod - * @param {module:jiff-client~JIFFClient#SecretShare} o - the modulus to apply - * @param {number} [l=ceil(log_2(this.Zp))] - the maximum bit length of either operands. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.smod = function (o, l, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (!=)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (!=)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (!=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('smod', this.holders); - } - - // figure out maximum output bit length - var lZp = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); - l = (l != null && l < lZp) ? l : lZp; - - // Convert to bits - var dividend_bits = this.bit_decomposition(op_id + ':decomposition1').slice(0, l); - var divisor_bits = o.bit_decomposition(op_id + ':decomposition2').slice(0, l); - - // Compute by long division - var remainder_bits = this.jiff.protocols.bits.sdiv(dividend_bits, divisor_bits, op_id + ':bits.sdiv').remainder; - - // Convert to number and return - return this.jiff.protocols.bits.bit_composition(remainder_bits); - }; - - /** - * Fast (modular) exponentiation with constant exponent via repeated squaring. - * @method cpow - * @param {number} cst - the constant to multiply to this share. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cpow = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (*)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('cpow', this.holders); - } - - // handle big numbers - var one = 1; - if (this.jiff.helpers.BigNumber) { - one = this.jiff.helpers.BigNumber(1); - cst = this.jiff.helpers.BigNumber(cst); - } - - // ensure exponent is non-negative - if (this.jiff.share_helpers['<'](cst, 0)) { - throw new Error('cpow supports non-negative exponents only, given ' + cst.toString()); - } - - // begin protocol - var evens = this; - var odds = new this.jiff.SecretShare(one, this.holders, this.threshold, this.Zp); - - // special case - if (cst.toString() === '0') { - return odds; - } - - for (var i = 0; this.jiff.share_helpers['<'](1, cst); i++) { - if (this.jiff.share_helpers['even'](cst)) { - evens = evens.smult(evens, op_id + ':smult0:'+i); - cst = this.jiff.share_helpers['/'](cst, 2); - } else { - odds = evens.smult(odds, op_id + ':smult0:'+i); - evens = evens.smult(evens, op_id + ':smult1:'+i); - cst = this.jiff.share_helpers['/'](this.jiff.share_helpers['-'](cst, 1), 2); - } - } - - return evens.smult(odds, op_id + ':smult0:' + i); - }; -}; -},{}],29:[function(require,module,exports){ -// Comparison operations on shares -module.exports = function (SecretShare) { - /** - * Greater than or equal with another share. - * @method sgteq - * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this >= o, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sgteq = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (>=)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (>=)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (>=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sgteq', this.holders); - } - - return this.islt(o, op_id).inot(); - }; - - /** - * Greater than with another share. - * @method sgt - * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this > o, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sgt = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (>)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (>)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (>)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sgt', this.holders); - } - - return o.islt(this, op_id); - }; - - /** - * Less than or equal with another share. - * @method slteq - * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this <= o, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.slteq = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (<=)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (<=)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (<=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('slteq', this.holders); - } - - return o.islt(this, op_id).inot(); - }; - - /** - * Less than with another share. - * @method slt - * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.slt = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (<)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (<)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (<)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('slt', this.holders); - } - - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, Math.max(this.threshold, o.threshold), this.Zp); - - var w = this.ilt_halfprime(op_id + ':halfprime:1'); - - var self = this; - w.wThen(function () { - var x = o.ilt_halfprime(op_id + ':halfprime:2'); - x.wThen(function () { - var y = self.issub(o).ilt_halfprime(op_id + ':halfprime:3'); - y.wThen(function () { - var xy = x.ismult(y, op_id + ':smult1'); - var answer = x.icmult(-1).icadd(1).issub(y).isadd(xy).isadd(w.ismult(x.isadd(y).issub(xy.icmult(2)), op_id + ':smult2')); - answer.wThen(final_deferred.resolve); - }); - }); - }); - - return result; - }; - - /** - * Greater than or equal with a constant. - * @method cgteqn - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this >= cst, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cgteq = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (>=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('cgteq', this.holders); - } - - return this.iclt(cst, op_id).inot(); - }; - - /** - * Greater than with a constant. - * @method cgt - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly.default ids suffice when all parties execute the - * instructions in the same order. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this > cst, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cgt = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (>)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('cgt', this.holders); - } - - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); - - var w = this.jiff.share_helpers['<'](cst, this.jiff.share_helpers['/'](this.Zp, 2)) ? 1 : 0; - var x = this.ilt_halfprime(op_id + ':halfprime:1'); - - var self = this; - x.wThen(function () { - var y = self.icmult(-1).icadd(cst).ilt_halfprime(op_id + ':halfprime:2'); - y.wThen(function () { - var xy = y.ismult(x, op_id + ':smult1'); - var answer = x.icmult(-1).icadd(1).issub(y).isadd(xy).isadd(x.isadd(y).issub(xy.icmult(2)).icmult(w)); - answer.wThen(final_deferred.resolve); - }); - }); - - return result; - }; - - /** - * Less than or equal with a constant. - * @method clteq - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this <= cst, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.clteq = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (<=)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('clteq', this.holders); - } - - return this.icgt(cst, op_id).inot(); - }; - - /** - * Less than with a constant. - * @method clt - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < cst, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.clt = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (<)'); - } - - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('clt', this.holders); - } - - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); - - var w = this.ilt_halfprime(op_id + ':halfprime:1'); - - var self = this; - w.wThen(function () { - var x = self.jiff.share_helpers['<'](cst, self.jiff.share_helpers['/'](self.Zp, 2)) ? 1 : 0; - var y = self.icsub(cst).ilt_halfprime(op_id + ':halfprime:2'); - y.wThen(function () { - var xy = y.icmult(x); - var answer = y.icmult(-1).icadd(1 - x).isadd(xy).isadd(w.ismult(y.icadd(x).issub(xy.icmult(2)), op_id + ':smult1')); - answer.wThen(final_deferred.resolve); - }); - }); - - return result; - }; - - /** - * Equality test with two shares. - * @method seq - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this = o, and 0 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.seq = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (==)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (==)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (==)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('seq', this.holders); - } - - return this.isneq(o, op_id).inot(); - }; - - /** - * Unequality test with two shares. - * @method sneq - * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.sneq = function (o, op_id) { - if (!(o.jiff === this.jiff)) { - throw new Error('shares do not belong to the same instance (!=)'); - } - if (!this.jiff.helpers.Zp_equals(this, o)) { - throw new Error('shares must belong to the same field (!=)'); - } - if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { - throw new Error('shares must be held by the same parties (!=)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('sneq', this.holders); - } - - return this.issub(o).icpow(this.jiff.share_helpers['-'](this.Zp, 1), op_id + ':cpow'); - }; - - /** - * Equality test with a constant. - * @method ceq - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.ceq = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (==)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('ceq', this.holders); - } - - return this.icneq(cst, op_id).inot(); - }; - - /** - * Unequality test with a constant. - * @method cneq - * @param {number} cst - the constant to compare with. - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.cneq = function (cst, op_id) { - if (!(this.isConstant(cst))) { - throw new Error('parameter should be a number (!=)'); - } - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('cneq', this.holders); - } - - return this.icsub(cst).icpow(this.jiff.share_helpers['-'](this.Zp, 1), op_id + ':cpow'); - }; - - /** - * Checks whether the share is less than half the field size. - * @method lt_halfprime - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. - */ - SecretShare.prototype.lt_halfprime = function (op_id) { - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('lt_halfprime', this.holders); - } - - // if share is even, then this is less than half the prime, otherwise, share is greater than half the prime - var share = this.icmult(2); - - // to check if share is even, we will use pre-shared bits as some form of a bit mask - var bitLength = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(share.Zp, 2)); - - // Create result share - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); - - // Execute protocol when randomly sampled bit-wise random number is ready - var self = this; - var ready_sampling = function (bits) { - // if 2*this is even, then this is less than half prime, otherwise this is greater or equal to half prime - if (bits.length !== bitLength) { - throw new Error('Preprocessed bits sequence has incorrect length, expected: ' + bitLength + ' actual: ' + bits.length); - } - - // bit composition: r = (rl ... r1 r0)_10 - var r = self.jiff.protocols.bits.bit_composition(bits); - // open share + noise, and utilize opened value with shared bit representation of noise to check the least significant digit of share. - share.jiff.internal_open(r.isadd(share), share.holders, op_id + ':open').then(function (result) { - var wrapped = self.jiff.protocols.bits.cgt(bits, result, op_id + ':bits.cgt'); - var isOdd = self.jiff.helpers.mod(result, 2); - isOdd = bits[0].icxor_bit(isOdd); - isOdd = isOdd.isxor_bit(wrapped, op_id + ':sxor_bit'); - - var answer = isOdd.inot(); - answer.wThen(final_deferred.resolve); - }); - }; - - // generate the bits of a random number less than our prime - var bits = this.jiff.get_preprocessing(op_id + ':sampling'); - if (bits == null) { - var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { - bitLength: bitLength, - count: 1, - max: this.Zp - }); - promise.then(function (msg) { - ready_sampling(msg['shares']); - }); - } else { - ready_sampling(bits); - } - - return result; - }; -}; -},{}],30:[function(require,module,exports){ -// general arithmetic protocols -module.exports = function (SecretShare) { - /** - * Reshares/refreshes the sharing of this number, used before opening to keep the share secret. - * @method refresh - * @param {string} [op_id=auto_gen()] - the operation id with which to tag the messages sent by this refresh, by default - * an automatic operation id is generated by increasing a local counter, default operation ids - * suffice when all parties execute the instructions in the same order. - * @returns {module:jiff-client~JIFFClient#SecretShare} a new share of the same number. - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.refresh = function (op_id) { - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('refresh', this.holders); - } - - // final result - var final_deferred = new this.jiff.helpers.Deferred(); - var final_promise = final_deferred.promise; - var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); - - // refresh - var self = this; - var ready_number = function (zero) { - self.isadd(zero).wThen(final_deferred.resolve); - }; - - // get shares of zero - var zero = this.jiff.get_preprocessing(op_id); - if (zero == null) { - var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id, { - number: 0, - count: 1 - }); - promise.then(function (msg) { - ready_number(msg['shares'][0]); - }); - } else { - ready_number(zero); - } - - return result; - }; - - /** - * Bit Decomposition: Transform existing share to an array of bit shares. - * @method bit_decomposition - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly. - * @returns {module:jiff-client~JIFFClient#SecretShare[]} an array of secret shares of bits of length [ceil(log_2(this.Zp))], where - * index 0 represents the least significant bit. - */ - SecretShare.prototype.bit_decomposition = function (op_id) { - if (op_id == null) { - op_id = this.jiff.counters.gen_op_id('bit_decomposition', this.holders); - } - - // bit length of this secret - var bitLength = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); - - // Create deferred shares to resolve to later when the computation completes - var many_shares = this.jiff.utils.many_secret_shares(bitLength, this.holders, this.threshold, this.Zp); - var deferreds = many_shares.deferreds; - var result = many_shares.shares; - - // Execute protocol when randomly sampled bit-wise random number is ready - var self = this; - var ready_sampling = function (bits) { - var r = self.jiff.protocols.bits.bit_composition(bits); - // add and reveal random number to this - self.jiff.internal_open(r.isadd(self), self.holders, op_id + ':open').then(function (result) { - // compute bits assuming r+this < Zp - var noWrap = self.jiff.protocols.bits.csubr(result, bits, op_id + ':bits.csubr:1'); - var didWrap = noWrap.pop(); - - // compute bits assuming r+this >= Zp - var withWrap = self.jiff.protocols.bits.csubr(self.jiff.share_helpers['+'](result, self.Zp), bits, op_id + ':bits.csubr:2'); - withWrap.pop(); // withWrap cannot underflow! - - // choose noWrap if first subtraction does not overflow (sign bit is zero), otherwise choose withWrap. - for (var i = 0; i < bitLength; i++) { - withWrap[i] = didWrap.iif_else(withWrap[i], noWrap[i], op_id + ':if_else:' + i); - } - self.jiff.utils.resolve_many_secrets(deferreds, withWrap); - }); - }; - - // generate the bits of a random number less than our prime - var bits = this.jiff.get_preprocessing(op_id + ':sampling'); - if (bits == null) { - var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { - bitLength: bitLength, - count: 1, - max: this.Zp - }); - promise.then(function (msg) { - ready_sampling(msg['shares']); - }); - } else { - ready_sampling(bits); - } - - return result; - }; -}; },{}],31:[function(require,module,exports){ -module.exports = { - /** - * Generates a random bit under MPC by xoring all bits sent by participating parties using smult / beaver triples - * @function generate_random_bit_bgw - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise' - */ - generate_random_bit_smult: function (jiff, threshold, receivers_list, compute_list, Zp, params) { - if (params.compute_threshold == null) { - params.compute_threshold = threshold; - } - - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_random_bit_smult', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - var op_id = params.op_id; - - // Generate random bit - var random_bit, promise; - if (compute_list.indexOf(jiff.id) > -1) { - var bit = jiff.helpers.random(2); - var bit_shares = jiff.internal_share(bit, params.compute_threshold, compute_list, compute_list, Zp, op_id + ':share'); - - random_bit = bit_shares[compute_list[0]]; - for (var i = 1; i < compute_list.length; i++) { - var party_id = compute_list[i]; - var obit = bit_shares[party_id]; - random_bit = random_bit.isxor_bit(obit, op_id + ':sxor_bit:' + i); - } - - promise = random_bit.value; - } - - // Reshare - random_bit = jiff.reshare(random_bit, threshold, receivers_list, compute_list, Zp, op_id + ':reshare'); - if (receivers_list.indexOf(jiff.id) > -1) { - promise = random_bit.value; - } - return {share: random_bit, promise: promise}; - }, - /** - * Generates a random bit under MPC by xoring all bits sent by participating parties using smult_bgw - * @function generate_random_bit_bgw - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise' - */ - generate_random_bit_bgw: function (jiff, threshold, receivers_list, compute_list, Zp, params) { - if (params.compute_threshold == null) { - params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW - } - - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_random_bit_bgw', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - - var op_id = params.op_id; - - // Generate random bit - var random_bit, promise; - if (compute_list.indexOf(jiff.id) > -1) { - var bit = jiff.helpers.random(2); - var bit_shares = jiff.internal_share(bit, params.compute_threshold, compute_list, compute_list, Zp, op_id + ':share'); - - random_bit = bit_shares[compute_list[0]]; - for (var i = 1; i < compute_list.length; i++) { - var party_id = compute_list[i]; - var obit = bit_shares[party_id]; - random_bit = random_bit.isadd(obit).issub(random_bit.ismult_bgw(obit, op_id + ':smult' + i).icmult(2)); - } - - promise = random_bit.value; - } - - // Reshare - random_bit = jiff.reshare(random_bit, threshold, receivers_list, compute_list, Zp, op_id + ':reshare'); - if (receivers_list.indexOf(jiff.id) > -1) { - promise = random_bit.value; - } - return {share: random_bit, promise: promise}; - }, - /** - * Generates a sequence of random bits under MPC - * @function generate_random_bits - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} [threshold=receivers_list.length] - the threshold of the bit when stored by receivers after generation - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - count: how many random bits to generate - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @param {object} protocols - the protocols to use for preprocessing - * @return {Object} contains 'share' (array of secret shares bits) and 'promise' - */ - generate_random_bits: function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { - if (params.count == null) { - params.count = 1; - } - - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_random_bits', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - - var op_id = params.op_id; - var _params = params; - - var promises = []; - var bits = []; - for (var i = 0; i < params.count; i++) { - params = Object.assign({}, _params); - params.op_id = op_id + ':' + i; - - var bit = protocols.generate_random_bit(threshold, receivers_list, compute_list, Zp, params, protocols); - - promises.push(bit.value); - if (bit.share != null) { - bits.push(bit.share); - } - } + +/** + * the function to compute the shares of input (can be overridden using hooks). + * @ignore + * @function gmw_compute_share + * @param {module:jiff-client~JIFFClient} jiff - the jiff instance + * @param {number} the secret to share + * @param {Array} parties_list - array of party ids to share with. + * @param {number} threshold - the min number of parties needed to reconstruct the secret, defaults to all the receivers. + * @param {number} Zp - the mod. + * @returns {object} a map between party number and its share + */ +function gmw_compute_share(jiff,input,parties_list, threshold, Zp) { + var ls={};// potential shares of length n + var i; + var len=parties_list.length; + for (i=0;i receivers_list.length) { + threshold = receivers_list.length; + } + + // if party is uninvolved in the share, do nothing + if (receivers_list.indexOf(jiff.id) === -1 && senders_list.indexOf(jiff.id) === -1) { + return {}; + } + + + // compute operation id + if (share_id == null) { + share_id = jiff.counters.gen_op_id2('GMW_share', receivers_list, senders_list); + } + + // stage sending of shares + if (senders_list.indexOf(jiff.id) > -1) { + // Call hook + secret = jiff.hooks.execute_array_hooks('beforeShare', [jiff, secret, threshold, receivers_list, senders_list, Zp], 1); + + // compute shares + var shares=gmw_compute_share(jiff,secret,receivers_list, threshold, Zp); + + // Call hook + + shares = jiff.hooks.execute_array_hooks('afterComputeShare', [jiff, shares, threshold, receivers_list, senders_list, Zp], 1); + + // send shares + for (i = 0; i < receivers_list.length; i++) { + p_id = receivers_list[i]; + if (p_id === jiff.id) { + continue; + } + + // send encrypted and signed shares_id[p_id] to party p_id + var msg = {party_id: p_id, share: shares[p_id], op_id: share_id}; + msg = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'share', msg], 2); + msg['share'] = jiff.hooks.encryptSign(jiff, msg['share'].toString(10), jiff.keymap[msg['party_id']], jiff.secret_key); + jiff.socket.safe_emit('share', JSON.stringify(msg)); + + } + } + + // stage receiving of shares + var result = {}; + if (receivers_list.indexOf(jiff.id) > -1) { + // setup a map of deferred for every received share + if (jiff.deferreds[share_id] == null) { + jiff.deferreds[share_id] = {}; + } + + var _remaining = senders_list.length; + for (i = 0; i < senders_list.length; i++) { + p_id = senders_list[i]; + if (p_id === jiff.id) { // Keep party's own share + var my_share = jiff.hooks.execute_array_hooks('receiveShare', [jiff, p_id, shares[p_id]], 2); + + result[p_id] = new jiff.SecretShare(my_share, receivers_list, threshold, Zp); + _remaining--; + continue; + } + + // check if a deferred is set up (maybe the message was previously received) + if (jiff.deferreds[share_id][p_id] == null) { // not ready, setup a deferred + jiff.deferreds[share_id][p_id] = new jiff.helpers.Deferred(); + + } + + var promise = jiff.deferreds[share_id][p_id].promise; + // destroy deferred when done + (function (promise, p_id) { // p_id is modified in a for loop, must do this to avoid scoping issues. + promise.then(function () { + delete jiff.deferreds[share_id][p_id]; + _remaining--; + if (_remaining === 0) { + delete jiff.deferreds[share_id]; + } + }); + })(promise, p_id); + + // receive share_i[id] from party p_id + result[p_id] = new jiff.SecretShare(promise, receivers_list, threshold, Zp); + } + } + + return result; + +} + + +module.exports = { + gmw_share:gmw_share +}; + + + + - if (bits.length === 0) { - bits = null; - } - return {share: bits, promise: Promise.all(promises)}; - } -}; },{}],32:[function(require,module,exports){ -/** - * Can be used to generate shares of a random number, or shares of zero. - * For a random number, every party generates a local random number and secret share it, - * then every party sums its share, resulting in a single share of an unknown random number for every party. - * The same approach is followed for zero, but instead, all the parties know that the total number is zero, but they - * do not know the value of any resulting share (except their own) - * @function jiff_share_all_number - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} n - the number to share - * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers - * @param {Array} [receivers_list=all_parties] - array of party ids to receive the result, by default, this includes all parties - * @param {Array} [compute_list=all_parties] - array of party ids to perform the protocol, by default, this includes all parties - * @param {number} [Zp=jiff.Zp] - the mod - * @param {object} [params={}] - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the result) and 'promise' - */ -var jiff_share_all_number = function (jiff, n, threshold, receivers_list, compute_list, Zp, params) { - var isSender = compute_list.indexOf(jiff.id) > -1; - var isReceiver = receivers_list.indexOf(jiff.id) > -1; - - if (!isSender && !isReceiver) { - return {}; - } - - if (params.compute_threshold == null) { - params.compute_threshold = Math.min(threshold, compute_list.length); - } - - var result, promise; - if (isSender) { - var shares = jiff.internal_share(n, params.compute_threshold, compute_list, compute_list, Zp, params.op_id + ':share'); - result = shares[compute_list[0]]; - for (var i = 1; i < compute_list.length; i++) { - result = result.isadd(shares[compute_list[i]]); - } - promise = result.value; - } - - result = jiff.reshare(result, threshold, receivers_list, compute_list, Zp, params.op_id + ':reshare'); - if (receivers_list.indexOf(jiff.id) > -1) { - promise = result.value; - } - - return {share: result, promise: promise}; -}; - -module.exports = { - /** - * Creates shares of an unknown random number. Every party comes up with its own random number and shares it. - * Then every party combines all the received shares to construct one share of the random unknown number - * @function generate_random_number - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the result) and 'promise' - */ - generate_random_number: function (jiff, threshold, receivers_list, compute_list, Zp, params) { - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_random_number', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - return jiff_share_all_number(jiff, jiff.helpers.random(Zp), threshold, receivers_list, compute_list, Zp, params); - }, - /** - * Creates shares of 0, such that no party knows the other parties' shares. - * Every party secret shares 0, then every party sums all the shares they received, resulting - * in a new share of 0 for every party - * @function generate_zero - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff instance - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * @return {Object} contains 'share' (this party's share of the result) and 'promise' - */ - generate_zero: function (jiff, threshold, receivers_list, compute_list, Zp, params) { - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_zero', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - return jiff_share_all_number(jiff, 0, threshold, receivers_list, compute_list, Zp, params); - } +// Arithmetic operations on shares +module.exports = function (SecretShare) { + /** + * Addition with a constant. + * @method cadd + * @param {number} cst - the constant to add. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cadd = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (+)'); + } + + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['+'](self.value, cst), self.Zp); + }; + + return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); + }; + + /** + * Subtraction with a constant. + * @method csub + * @param {number} cst - the constant to subtract from this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.csub = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (-)'); + } + + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['-'](self.value, cst), self.Zp); + }; + + return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); + }; + + /** + * Multiplication by a constant. + * @method cmult + * @param {number} cst - the constant to multiply to this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cmult = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (*)'); + } + + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, cst), self.Zp); + }; + + return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); + }; + + /** + * Division by a constant factor of the number represented by the share. + * @method cdivfac + * @param {number} cst - the constant by which to divide the share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cdivfac = function (cst) { + if (!(this.isConstant(cst))) { + throw new Error('Parameter should be a number (cdivfac)'); + } + + var inv = this.jiff.helpers.extended_gcd(cst, this.Zp)[0]; + + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, inv), self.Zp); + }; + + return new this.jiff.SecretShare(this.wThen(ready), this.holders, this.threshold, this.Zp); + }; + + /** + * Addition of two secret shares. + * @method sadd + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to add to this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * + * @example + * // share a value with all parties, and sum the values of all shares + * var shares = jiff_instance.share(x); + * var sum = shares[1]; + * for (var i = 2; i <= jiff_instance.party_count; i++) { + * sum = sum.sadd(shares[i]); + * } + * + */ + SecretShare.prototype.sadd = function (o) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (+)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (+)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (+)'); + } + + // add the two shares when ready locally + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['+'](self.value, o.value), self.Zp); + }; + + // promise to execute ready_add when both are ready + return new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, Math.max(this.threshold, o.threshold), this.Zp); + }; + + /** + * Subtraction of two secret shares. + * @method ssub + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to subtract from this share. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.ssub = function (o) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (-)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (-)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (-)'); + } + + // subtract the two shares when ready locally + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['-'](self.value, o.value), self.Zp); + }; + + // promise to execute ready_add when both are ready + return new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, Math.max(this.threshold, o.threshold), this.Zp); + }; + + /** + * Multiplication of two secret shares through Beaver Triplets. + * @method smult + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to multiply with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). + * This id must be unique, and must be passed by all parties to the same instruction. + * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id + * is generated by increasing a local counter, default ids suffice when all parties execute the + * instructions in the same order. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.smult = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (*)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (*)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (*)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('smult', this.holders); + } + + // final result + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, Math.max(this.threshold, o.threshold), this.Zp); + + // called when triplet is ready + var self = this; + var ready_triplet = function (triplet) { + var a = triplet[0]; + var b = triplet[1]; + var c = triplet[2]; + + // d = s - a. e = o - b. + var d = self.isadd(a.icmult(-1)); + var e = o.isadd(b.icmult(-1)); + + // Open d and e. + // The only communication cost. + var e_promise = self.jiff.internal_open(e, e.holders, op_id + ':open1'); + var d_promise = self.jiff.internal_open(d, d.holders, op_id + ':open2'); + Promise.all([e_promise, d_promise]).then(function (arr) { + var e_open = arr[0]; + var d_open = arr[1]; + + // result_share = d_open * e_open + d_open * b_share + e_open * a_share + c. + var t1 = self.jiff.helpers.mod(self.jiff.share_helpers['*'](d_open, e_open), self.Zp); + var t2 = b.icmult(d_open); + var t3 = a.icmult(e_open); + + // All this happens locally. + var final_result = t2.icadd(t1); + final_result = final_result.isadd(t3); + final_result = final_result.isadd(c); + + final_result.wThen(final_deferred.resolve); + }); + }; + + // Get shares of triplets. + var triplet = this.jiff.get_preprocessing(op_id + ':triplet'); + if (triplet == null) { + var promise = this.jiff.from_crypto_provider('triplet', this.holders, Math.max(this.threshold, o.threshold), this.Zp, op_id + ':triplet'); + promise.then(function (msg) { + ready_triplet(msg['shares']); + }); + } else { + ready_triplet(triplet); + } + + return result; + }; + + /** + * Multiplication of two secret shares through BGW protocol. + * @method smult_bgw + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to multiply with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). + * This id must be unique, and must be passed by all parties to the same instruction. + * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id + * is generated by increasing a local counter, default ids suffice when all parties execute the + * instructions in the same order. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.smult_bgw = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (bgw*)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (bgw*)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (bgw*)'); + } + if ((this.threshold - 1) + (o.threshold - 1) > this.holders.length - 1) { + throw new Error('threshold too high for BGW (*)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('smult_bgw', this.holders); + } + + // ensure thresholds are fine + var new_threshold = (this.threshold - 1) + (o.threshold - 1) + 1; + if (new_threshold > this.holders) { + var errorMsg = 'Threshold too large for smult_bgw: ' + new_threshold; + errorMsg += '. Shares: ' + this.toString() + ', ' + o.toString(); + throw new Error(errorMsg); + } + + // multiply via the BGW protocol + var self = this; + var ready = function () { + return self.jiff.helpers.mod(self.jiff.share_helpers['*'](self.value, o.value), self.Zp); + }; + + // reshare to reduce threshold and return when ready + var result = new this.jiff.SecretShare(this.when_both_ready(o, ready), this.holders, new_threshold, this.Zp); + return this.jiff.reshare(result, Math.max(this.threshold, o.threshold), result.holders, result.holders, result.Zp, op_id + ':threshold'); + }; + + /** + * Integer divison with two shares (this / o) + * @method sdiv + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to divide by. + * @param {number} [l=ceil(log_2(this.Zp))] - the maximum bit length of either operands. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sdiv = function (o, l, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (!=)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (!=)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (!=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sdiv', this.holders); + } + + // figure out maximum output bit length + var lZp = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); + l = (l != null && l < lZp) ? l : lZp; + + // Convert to bits + var dividend_bits = this.bit_decomposition(op_id + ':decomposition1').slice(0, l); + var divisor_bits = o.bit_decomposition(op_id + ':decomposition2').slice(0, l); + + // Compute by long division + var quotient_bits = this.jiff.protocols.bits.sdiv(dividend_bits, divisor_bits, op_id + ':bits.sdiv').quotient; + + // Convert to number and return + return this.jiff.protocols.bits.bit_composition(quotient_bits); + }; + + /** + * Integer divison with a share and a constant (this / cst). + * @method cdiv + * @param {module:jiff-client~JIFFClient#SecretShare} cst - the constant to divide by. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cdiv = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (/)'); + } + + if (this.jiff.share_helpers['<='](cst, 0)) { + throw new Error('divisor must be > 0 (cst/): ' + cst); + } + + if (this.jiff.share_helpers['<='](this.Zp, cst)) { + throw new Error('divisor must be < share.Zp (' + this.Zp + ') in (cst/): ' + cst); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('cdiv', this.holders); + } + + // Allocate share for result to which the answer will be resolved once available + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); + + // Execute protocol when random in noise in [0, Zp) and quotient floor(noise/constant) is ready! + var self = this; + var ready_quotient = function (noise, nOVERc) { + // Use noise + var noisyX = self.isadd(noise); + self.jiff.internal_open(noisyX, noisyX.holders, op_id + ':open').then(function (noisyX) { + var wrapped = self.icgt(noisyX, op_id + ':wrap_cgt'); // 1 => x + noise wrapped around Zp, 0 otherwise + + // if we did not wrap + var noWrapDiv = self.jiff.share_helpers['floor/'](noisyX, cst); + var unCorrectedQuotient = nOVERc.icmult(-1).icadd(noWrapDiv).icsub(1); + var verify = self.issub(unCorrectedQuotient.icmult(cst)); + var isNotCorrect = verify.icgteq(cst, op_id + ':cor1'); + var noWrapAnswer = unCorrectedQuotient.isadd(isNotCorrect); // if incorrect => isNotCorrect = 1 => quotient = unCorrectedQuotient - 1 + + // if we wrapped + var wrapDiv = self.jiff.share_helpers['floor/'](self.jiff.share_helpers['+'](noisyX, self.Zp), cst); + unCorrectedQuotient = nOVERc.icmult(-1).icadd(wrapDiv).icsub(1); + verify = self.issub(unCorrectedQuotient.icmult(cst)); + isNotCorrect = verify.icgteq(cst, op_id + ':cor2'); + var wrapAnswer = unCorrectedQuotient.isadd(isNotCorrect); // if incorrect => isNotCorrect = 1 => quotient = unCorrectedQuotient - 1 + + var answer = noWrapAnswer.isadd(wrapped.ismult(wrapAnswer.issub(noWrapAnswer), op_id + ':smult')); + answer.wThen(final_deferred.resolve); + }); + }; + + // Preprocessing cases + var quotient = this.jiff.get_preprocessing(op_id + ':quotient'); + if (quotient == null) { // case 1: no preprocessing with crypto provider! + var promise = this.jiff.from_crypto_provider('quotient', this.holders, this.threshold, this.Zp, op_id + ':quotient', {constant: cst}); + promise.then(function (msg) { + ready_quotient(msg['shares'][0], msg['shares'][1]); + }); + } else if (quotient.ondemand === true) { // case 2: constant was not available at preprocessing time, must do it now! + this.jiff.preprocessing('quotient', 1, null, this.threshold, this.holders, this.holders, this.Zp, [op_id + ':quotient'], {constant: cst, namespace: 'base'}); + this.jiff.executePreprocessing(function () { + var quotient = self.jiff.get_preprocessing(op_id + ':quotient'); + ready_quotient(quotient.r, quotient.q); + }); + } else { // case 3: preprocessing is completed! + ready_quotient(quotient.r, quotient.q); + } + + // special case, if result is zero, sometimes we will get to -1 due to how correction happens above (.csub(1) and then compare) + var zeroIt = this.iclt(cst, op_id + ':zero_check').inot(); + return result.ismult(zeroIt, op_id + ':zero_it'); + }; + + /** + * Remainder with two shares (this % o) + * @method smod + * @param {module:jiff-client~JIFFClient#SecretShare} o - the modulus to apply + * @param {number} [l=ceil(log_2(this.Zp))] - the maximum bit length of either operands. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.smod = function (o, l, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (!=)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (!=)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (!=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('smod', this.holders); + } + + // figure out maximum output bit length + var lZp = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); + l = (l != null && l < lZp) ? l : lZp; + + // Convert to bits + var dividend_bits = this.bit_decomposition(op_id + ':decomposition1').slice(0, l); + var divisor_bits = o.bit_decomposition(op_id + ':decomposition2').slice(0, l); + + // Compute by long division + var remainder_bits = this.jiff.protocols.bits.sdiv(dividend_bits, divisor_bits, op_id + ':bits.sdiv').remainder; + + // Convert to number and return + return this.jiff.protocols.bits.bit_composition(remainder_bits); + }; + + /** + * Fast (modular) exponentiation with constant exponent via repeated squaring. + * @method cpow + * @param {number} cst - the constant to multiply to this share. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cpow = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (*)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('cpow', this.holders); + } + + // handle big numbers + var one = 1; + if (this.jiff.has_extension('bignumber')) { + one = this.jiff.helpers.BigNumber(1); + cst = this.jiff.helpers.BigNumber(cst); + } + + // ensure exponent is non-negative + if (this.jiff.share_helpers['<'](cst, 0)) { + throw new Error('cpow supports non-negative exponents only, given ' + cst.toString()); + } + + // begin protocol + var evens = this; + var odds = new this.jiff.SecretShare(one, this.holders, this.threshold, this.Zp); + + // special case + if (cst.toString() === '0') { + return odds; + } + + for (var i = 0; this.jiff.share_helpers['<'](1, cst); i++) { + if (this.jiff.share_helpers['even'](cst)) { + evens = evens.ismult(evens, op_id + ':smult0:'+i); + cst = this.jiff.share_helpers['/'](cst, 2); + } else { + odds = evens.ismult(odds, op_id + ':smult0:'+i); + evens = evens.ismult(evens, op_id + ':smult1:'+i); + cst = this.jiff.share_helpers['/'](this.jiff.share_helpers['-'](cst, 1), 2); + } + } + + return evens.ismult(odds, op_id + ':smult0:' + i); + }; }; },{}],33:[function(require,module,exports){ -/** - * Creates shares of r and x, such that r is a uniform random number between 0 and Zp, and x is floor(r/constant) - * where constant is provided by the extra params - * @function generate_random_and_quotient - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed - * @param {Array} receivers_list - array of party ids to receive the result - * @param {Array} compute_list - array of party ids to perform the protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - compute_threshold: the threshold to use during computation: defaults to compute_list.length - * - constant: the constant to divide the random number by. - * - output_op_id: the set op id of the output quotient and noise - * @return {Object} contains 'share' (this party's share of the result) and 'promise' - */ -module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { - // consistent and unique op_id for compute and receiver parties - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_random_and_quotient', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - - if (params.compute_threshold == null) { - params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW - } - - var constant = params.constant; - var op_id = params.op_id; - Zp = Zp ? jiff.Zp : Zp; - - // stores the result - var r, q; - - // for compute parties - var promise; - if (compute_list.indexOf(jiff.id) > -1) { - var largestQuotient = jiff.share_helpers['floor'](jiff.share_helpers['/'](Zp, constant)); - var largestMultiple = jiff.share_helpers['*'](largestQuotient, constant); - - // Uniform random number between [0, Zp) - var r_bits = jiff.protocols.bits.rejection_sampling(0, Zp, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection1'); - var cmp = jiff.protocols.bits.cgteq(r_bits, largestMultiple, params.output_op_id + ':bits_cgteq'); - var r1 = jiff.protocols.bits.bit_composition(r_bits); - - // Uniform random number between [0, Math.floor(Zp / constant)) - var quotient = jiff.protocols.bits.rejection_sampling(0, largestQuotient, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection2'); - quotient = jiff.protocols.bits.bit_composition(quotient); - - // Uniform random number between [0, constant) - var remainder = jiff.protocols.bits.rejection_sampling(0, constant, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection3'); - remainder = jiff.protocols.bits.bit_composition(remainder); - var r2 = quotient.icmult(constant).isadd(remainder); - - // choose either (r1, largestQuotient) or (r2, quotient) based on cmp result - r = cmp.iif_else(r1, r2, params.output_op_id + ':ifelse1'); - q = cmp.iif_else(largestQuotient, quotient, params.output_op_id + ':ifelse2'); - promise = Promise.all([r.value, q.value]); - } - - // reshare the result with the designated receivers - r = jiff.reshare(r, threshold, receivers_list, compute_list, Zp, op_id + ':reshare1'); - q = jiff.reshare(q, threshold, receivers_list, compute_list, Zp, op_id + ':reshare2'); - - // return result - if (receivers_list.indexOf(jiff.id) > -1) { - promise = Promise.all([r.value, q.value]); - } - return {share: {r: r, q: q}, promise: promise}; +// Comparison operations on shares +module.exports = function (SecretShare) { + /** + * Greater than or equal with another share. + * @method sgteq + * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this >= o, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sgteq = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (>=)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (>=)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (>=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sgteq', this.holders); + } + + return this.islt(o, op_id).inot(); + }; + + /** + * Greater than with another share. + * @method sgt + * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this > o, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sgt = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (>)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (>)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (>)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sgt', this.holders); + } + + return o.islt(this, op_id); + }; + + /** + * Less than or equal with another share. + * @method slteq + * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this <= o, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.slteq = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (<=)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (<=)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (<=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('slteq', this.holders); + } + + return o.islt(this, op_id).inot(); + }; + + /** + * Less than with another share. + * @method slt + * @param {module:jiff-client~JIFFClient#SecretShare} o - the other share. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < o, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.slt = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (<)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (<)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (<)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('slt', this.holders); + } + + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, Math.max(this.threshold, o.threshold), this.Zp); + + var w = this.ilt_halfprime(op_id + ':halfprime:1'); + + var self = this; + w.wThen(function () { + var x = o.ilt_halfprime(op_id + ':halfprime:2'); + x.wThen(function () { + var y = self.issub(o).ilt_halfprime(op_id + ':halfprime:3'); + y.wThen(function () { + var xy = x.ismult(y, op_id + ':smult1'); + var answer = x.icmult(-1).icadd(1).issub(y).isadd(xy).isadd(w.ismult(x.isadd(y).issub(xy.icmult(2)), op_id + ':smult2')); + answer.wThen(final_deferred.resolve); + }); + }); + }); + + return result; + }; + + /** + * Greater than or equal with a constant. + * @method cgteqn + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this >= cst, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cgteq = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (>=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('cgteq', this.holders); + } + + return this.iclt(cst, op_id).inot(); + }; + + /** + * Greater than with a constant. + * @method cgt + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly.default ids suffice when all parties execute the + * instructions in the same order. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this > cst, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cgt = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (>)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('cgt', this.holders); + } + + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); + + var w = this.jiff.share_helpers['<'](cst, this.jiff.share_helpers['/'](this.Zp, 2)) ? 1 : 0; + var x = this.ilt_halfprime(op_id + ':halfprime:1'); + + var self = this; + x.wThen(function () { + var y = self.icmult(-1).icadd(cst).ilt_halfprime(op_id + ':halfprime:2'); + y.wThen(function () { + var xy = y.ismult(x, op_id + ':smult1'); + var answer = x.icmult(-1).icadd(1).issub(y).isadd(xy).isadd(x.isadd(y).issub(xy.icmult(2)).icmult(w)); + answer.wThen(final_deferred.resolve); + }); + }); + + return result; + }; + + /** + * Less than or equal with a constant. + * @method clteq + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this <= cst, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.clteq = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (<=)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('clteq', this.holders); + } + + return this.icgt(cst, op_id).inot(); + }; + + /** + * Less than with a constant. + * @method clt + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this < cst, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.clt = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (<)'); + } + + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('clt', this.holders); + } + + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); + + var w = this.ilt_halfprime(op_id + ':halfprime:1'); + + var self = this; + w.wThen(function () { + var x = self.jiff.share_helpers['<'](cst, self.jiff.share_helpers['/'](self.Zp, 2)) ? 1 : 0; + var y = self.icsub(cst).ilt_halfprime(op_id + ':halfprime:2'); + y.wThen(function () { + var xy = y.icmult(x); + var answer = y.icmult(-1).icadd(1 - x).isadd(xy).isadd(w.ismult(y.icadd(x).issub(xy.icmult(2)), op_id + ':smult1')); + answer.wThen(final_deferred.resolve); + }); + }); + + return result; + }; + + /** + * Equality test with two shares. + * @method seq + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 1 if this = o, and 0 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.seq = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (==)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (==)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (==)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('seq', this.holders); + } + + return this.isneq(o, op_id).inot(); + }; + + /** + * Unequality test with two shares. + * @method sneq + * @param {module:jiff-client~JIFFClient#SecretShare} o - the share to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.sneq = function (o, op_id) { + if (!(o.jiff === this.jiff)) { + throw new Error('shares do not belong to the same instance (!=)'); + } + if (!this.jiff.helpers.Zp_equals(this, o)) { + throw new Error('shares must belong to the same field (!=)'); + } + if (!this.jiff.helpers.array_equals(this.holders, o.holders)) { + throw new Error('shares must be held by the same parties (!=)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('sneq', this.holders); + } + + return this.issub(o).icpow(this.jiff.share_helpers['-'](this.Zp, 1), op_id + ':cpow'); + }; + + /** + * Equality test with a constant. + * @method ceq + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.ceq = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (==)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('ceq', this.holders); + } + + return this.icneq(cst, op_id).inot(); + }; + + /** + * Unequality test with a constant. + * @method cneq + * @param {number} cst - the constant to compare with. + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result, the final result is 0 if this = o, and 1 otherwise. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.cneq = function (cst, op_id) { + if (!(this.isConstant(cst))) { + throw new Error('parameter should be a number (!=)'); + } + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('cneq', this.holders); + } + + return this.icsub(cst).icpow(this.jiff.share_helpers['-'](this.Zp, 1), op_id + ':cpow'); + }; + + /** + * Checks whether the share is less than half the field size. + * @method lt_halfprime + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @return {module:jiff-client~JIFFClient#SecretShare} this party's share of the result. + */ + SecretShare.prototype.lt_halfprime = function (op_id) { + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('lt_halfprime', this.holders); + } + + // if share is even, then this is less than half the prime, otherwise, share is greater than half the prime + var share = this.icmult(2); + + // to check if share is even, we will use pre-shared bits as some form of a bit mask + var bitLength = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(share.Zp, 2)); + + // Create result share + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); + + // Execute protocol when randomly sampled bit-wise random number is ready + var self = this; + var ready_sampling = function (bits) { + // if 2*this is even, then this is less than half prime, otherwise this is greater or equal to half prime + if (bits.length !== bitLength) { + throw new Error('Preprocessed bits sequence has incorrect length, expected: ' + bitLength + ' actual: ' + bits.length); + } + + // bit composition: r = (rl ... r1 r0)_10 + var r = self.jiff.protocols.bits.bit_composition(bits); + // open share + noise, and utilize opened value with shared bit representation of noise to check the least significant digit of share. + share.jiff.internal_open(r.isadd(share), share.holders, op_id + ':open').then(function (result) { + var wrapped = self.jiff.protocols.bits.cgt(bits, result, op_id + ':bits.cgt'); + var isOdd = self.jiff.helpers.mod(result, 2); + isOdd = bits[0].icxor_bit(isOdd); + isOdd = isOdd.isxor_bit(wrapped, op_id + ':sxor_bit'); + + var answer = isOdd.inot(); + answer.wThen(final_deferred.resolve); + }); + }; + + // generate the bits of a random number less than our prime + var bits = this.jiff.get_preprocessing(op_id + ':sampling'); + if (bits == null) { + var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { + bitLength: bitLength, + count: 1, + max: this.Zp + }); + promise.then(function (msg) { + ready_sampling(msg['shares']); + }); + } else { + ready_sampling(bits); + } + + return result; + }; }; },{}],34:[function(require,module,exports){ -var sample = function (jiff, range, compute_list, Zp, params, protocols, reject_count) { - // Transform sampling range into bit size - var bitLength = jiff.helpers.ceil(jiff.helpers.bLog(range, 2)); - bitLength = parseInt(bitLength.toString(), 10); - - var paramsCopy = Object.assign({}, params); - paramsCopy['count'] = bitLength; - paramsCopy['op_id'] = params.op_id + ':sampling:' + reject_count; - return protocols.generate_random_bits(params.compute_threshold, compute_list, compute_list, Zp, paramsCopy, protocols).share; -}; - -var one_round_sampling = function (jiff, lower_bound, upper_bound, compute_list, Zp, params, protocols, finalLength, reject_count) { - // Figure out sampling range - var range; - if (upper_bound.isBigNumber === true) { - range = upper_bound.minus(lower_bound); - } else { - range = upper_bound - lower_bound; - } - - // Special cases - if (range.toString() === '0') { - throw new Error('rejection sampling called with range 0, no numbers to sample!'); - } - if (range.toString() === '1') { - var zero = protocols.generate_zero(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; - // special case: cadd can be performed locally on bit arrays of length 1! - var resultOne = jiff.protocols.bits.cadd([zero], lower_bound); - while (resultOne.length > finalLength) { - resultOne.pop(); - } - return {share: resultOne, promise: true}; - } - - // Rejection protocol - var bits = sample(jiff, range, compute_list, Zp, params, protocols, reject_count); - var cmp = jiff.protocols.bits.clt(bits, range, params.output_op_id + ':bits.clt:' + reject_count); - var bits_add = jiff.protocols.bits.cadd(bits, lower_bound, params.output_op_id + ':bits.cadd:' + reject_count); - - if (cmp === true) { - return {share: bits_add, promise: true}; - } else if (cmp === false) { // need to resample - return {share: bits_add, promise: false}; - } - - var promise = jiff.internal_open(cmp, compute_list, params.output_op_id + ':open:' + reject_count); - return {share: bits_add, promise: promise.then( - function (cmp) { - return cmp.toString() === '1'; - } - )}; -}; - -var computeParty = function (jiff, lower_bound, upper_bound, threshold, receivers_list, compute_list, Zp, params, protocols, op_id, finalLength, reject_count) { - var result = one_round_sampling(jiff, lower_bound, upper_bound, compute_list, Zp, params, protocols, finalLength, reject_count); - - // Case 1: we know whether sampling succeeded or not - if (result.promise === true) { - return reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, result.share); - } - if (result.promise === false) { - return {share: 'RETRY', promise: jiff.utils.all_promises(result.share)}; - } - - // Case 2: we only have a promise to whether the sampling succeeded or not - var many_shares = jiff.utils.many_secret_shares(finalLength, compute_list, threshold, Zp); - var final_deferreds = many_shares.deferreds; - - result.promise.then(function (promiseVal) { - // RETRY and PLACEHOLDER shares are cleaned up later in the preprocessing pipeline - if (promiseVal === false) { - for (var i = 0; i < final_deferreds.length; i++) { - final_deferreds[i].resolve('RETRY'); - } - return; - } - - // Need to make sure party only executes the reshare operation if sampling succeeds - var reshared = reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, result.share); - - if (receivers_list.indexOf(jiff.id) > -1) { - jiff.utils.resolve_many_secrets(final_deferreds, reshared.share); - } else { - for (i = 0; i < final_deferreds.length; i++) { - final_deferreds[i].resolve('PLACEHOLDER'); - } - } - }); - - return {share: many_shares.shares, promise: jiff.utils.all_promises(many_shares.shares)}; -}; - -var reshareResult = function (jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, shares) { - // fix threshold and parties - var promises = []; - for (var i = 0; i < finalLength; i++) { - if (compute_list.indexOf(jiff.id) > -1) { - promises[i] = shares[i].value; - } - shares[i] = jiff.reshare(shares[i], threshold, receivers_list, compute_list, Zp, op_id + ':reshare:' + i); - if (receivers_list.indexOf(jiff.id) > -1) { - promises[i] = shares[i].value; - } - } - - // return output - if (receivers_list.indexOf(jiff.id) === -1) { - shares = null; - } - - // handle rejection case - return {share: shares, promise: Promise.all(promises)}; -}; - -/** - * Wrapper for when doing rejection sampling during pre processing - * - * Do not use this function directly, especially during online computation time, use jiffClient.protocols.bits.rejection_sampling instead - * - * @function sampling - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} [threshold=receivers_list.length] - the threshold of the resulting shares after sampling - * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the sampling shares, by default, this includes all parties - * @param {Array} [compute_list=all_parties] - array of party ids that will perform this protocol, by default, this includes all parties - * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. - * This id must be unique, and must be passed by all parties to the same instruction, to - * ensure that corresponding instructions across different parties are matched correctly - * @param {object} [params={}] - an object containing extra parameters passed by the user - * Expects: - * - compute_threshold, an optional number compute_threshold parameter, which specifies threshold used - * during the protocol execution. By default, this is (|compute_list|+1)/2 - * - optional 'lower_bound' and 'upper_bound', numeric parameters, default to 0 and Zp respectively - * - op_id, the base op_id to tag operations inside this protocol with, defaults to auto generated - * - output_op_id, the tag id for the output result - * - retry_count, how many times rejection sampling have been retried! - * @param {object} [protocols=defaults] - the protocols to use for preprocessing, any protocol(s) not provided will be replaced with defaults - * @returns {Object} an object containing keys: 'share', and 'promise'. The promise is resolved when the rejection sampling is completed. - * The object is consumed by .preprocessing: - * - 'share' attribute contains the resulting array of secret shared bits representing the sampled value, and is stored in the preprocessing table internally - * - The promise is consumed and a new promise is returned by .preprocessing that is resolved after this returned promise (and all other promise generated by that .preprocessing call) are resolved - */ -module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { - // Internal version: set parameters (e.g. receivers_list) do not need defaults - // defaults (for internal preprocessing) - var lower_bound = params.lower_bound != null ? params.lower_bound : 0; - var upper_bound = params.upper_bound != null ? params.upper_bound : Zp; - if (params.compute_threshold == null) { // honest majority BGW - params.compute_threshold = Math.floor((compute_list.length + 1) / 2); - } - - // Figure out final bit size (after adding back lower) - var finalLength = jiff.helpers.ceil(jiff.helpers.bLog(upper_bound, 2)); - finalLength = parseInt(finalLength.toString(), 10); - finalLength = Math.max(finalLength, 1); // special case: when upper_bound is 1! - - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('rejection_sampling', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - var op_id = params.op_id; - - // Rejection count - var reject_count = params.reject_count || 0; - - if (compute_list.indexOf(jiff.id) === -1) { - return reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, []) - } - - return computeParty(jiff, lower_bound, upper_bound, threshold, receivers_list, compute_list, Zp, params, protocols, op_id, finalLength, reject_count); +// general arithmetic protocols +module.exports = function (SecretShare) { + /** + * Reshares/refreshes the sharing of this number, used before opening to keep the share secret. + * @method refresh + * @param {string} [op_id=auto_gen()] - the operation id with which to tag the messages sent by this refresh, by default + * an automatic operation id is generated by increasing a local counter, default operation ids + * suffice when all parties execute the instructions in the same order. + * @returns {module:jiff-client~JIFFClient#SecretShare} a new share of the same number. + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.refresh = function (op_id) { + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('refresh', this.holders); + } + + // final result + var final_deferred = new this.jiff.helpers.Deferred(); + var final_promise = final_deferred.promise; + var result = new this.jiff.SecretShare(final_promise, this.holders, this.threshold, this.Zp); + + // refresh + var self = this; + var ready_number = function (zero) { + self.isadd(zero).wThen(final_deferred.resolve); + }; + + // get shares of zero + var zero = this.jiff.get_preprocessing(op_id); + if (zero == null) { + var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id, { + number: 0, + count: 1 + }); + promise.then(function (msg) { + ready_number(msg['shares'][0]); + }); + } else { + ready_number(zero); + } + + return result; + }; + + /** + * Bit Decomposition: Transform existing share to an array of bit shares. + * @method bit_decomposition + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly. + * @returns {module:jiff-client~JIFFClient#SecretShare[]} an array of secret shares of bits of length [ceil(log_2(this.Zp))], where + * index 0 represents the least significant bit. + */ + SecretShare.prototype.bit_decomposition = function (op_id) { + if (op_id == null) { + op_id = this.jiff.counters.gen_op_id('bit_decomposition', this.holders); + } + + // bit length of this secret + var bitLength = this.jiff.share_helpers['ceil'](this.jiff.helpers.bLog(this.Zp, 2)); + + // Create deferred shares to resolve to later when the computation completes + var many_shares = this.jiff.utils.many_secret_shares(bitLength, this.holders, this.threshold, this.Zp); + var deferreds = many_shares.deferreds; + var result = many_shares.shares; + + // Execute protocol when randomly sampled bit-wise random number is ready + var self = this; + var ready_sampling = function (bits) { + var r = self.jiff.protocols.bits.bit_composition(bits); + // add and reveal random number to this + self.jiff.internal_open(r.isadd(self), self.holders, op_id + ':open').then(function (result) { + // compute bits assuming r+this < Zp + var noWrap = self.jiff.protocols.bits.csubr(result, bits, op_id + ':bits.csubr:1'); + var didWrap = noWrap.pop(); + + // compute bits assuming r+this >= Zp + var withWrap = self.jiff.protocols.bits.csubr(self.jiff.share_helpers['+'](result, self.Zp), bits, op_id + ':bits.csubr:2'); + withWrap.pop(); // withWrap cannot underflow! + + // choose noWrap if first subtraction does not overflow (sign bit is zero), otherwise choose withWrap. + for (var i = 0; i < bitLength; i++) { + withWrap[i] = didWrap.iif_else(withWrap[i], noWrap[i], op_id + ':if_else:' + i); + } + self.jiff.utils.resolve_many_secrets(deferreds, withWrap); + }); + }; + + // generate the bits of a random number less than our prime + var bits = this.jiff.get_preprocessing(op_id + ':sampling'); + if (bits == null) { + var promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { + bitLength: bitLength, + count: 1, + max: this.Zp + }); + promise.then(function (msg) { + ready_sampling(msg['shares']); + }); + } else { + ready_sampling(bits); + } + + return result; + }; }; - },{}],35:[function(require,module,exports){ -/** - * Generation of beaver triplet via MPC, uses the server for communication channels, but not for generation - * @function generate_beaver_bgw - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {number} threshold - the threshold of the triplets when stored by receivers after generation - * @param {Array} receivers_list - array of party ids that want to receive the triplet shares - * @param {Array} compute_list - array of party ids that will perform this protocol - * @param {number} Zp - the mod - * @param {object} params - an object containing extra parameters passed by the user - * Expects: - * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated - * - an optional number compute_threshold parameter, which specifies threshold used - * during the protocol execution. By default, this is the length of the (compute_list+1)/2 - * @param {object} protocols - the sub protocols to use for preprocessing - * @return {object} all pre-processing protocols must return an object with these keys: - * { - * 'share': the share(s)/value(s) to store attached to op_id for later use by the computation (i.e. the result of preprocessing), - * 'promise': a promise for when this protocol is fully completed (could be null if the protocol was already completed) - * } - * In this case, 'share' is an array of this party's shares of the resulting triplet, a,b,c such that a*b=c - */ -module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { - if (params.compute_threshold == null) { - params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW - } - if (params.op_id == null && params.output_op_id == null) { - params.op_id = jiff.counters.gen_op_id2('generate_beaver_bgw', receivers_list, compute_list); - } else if (params.op_id == null) { - params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); - } - - var op_id = params.op_id; - var _params = params; - - var a, b, c, promises; - if (compute_list.indexOf(jiff.id) > -1) { - params = Object.assign({}, _params); - params.op_id = op_id + ':share_a'; - a = protocols.generate_random_number(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; - - params = Object.assign({}, _params); - params.op_id = op_id + ':share_b'; - b = protocols.generate_random_number(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; - - c = a.ismult_bgw(b, op_id + ':smult_bgw'); - promises = [a.value, b.value, c.value]; - } - - a = jiff.reshare(a, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_a'); - b = jiff.reshare(b, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_b'); - c = jiff.reshare(c, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_c'); - if (receivers_list.indexOf(jiff.id) > -1) { - promises = [a.value, b.value, c.value]; - } - - return { share: [a, b, c], promise: Promise.all(promises) }; +module.exports = { + /** + * Generates a random bit under MPC by xoring all bits sent by participating parties using smult / beaver triples + * @function generate_random_bit_bgw + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise' + */ + generate_random_bit_smult: function (jiff, threshold, receivers_list, compute_list, Zp, params) { + if (params.compute_threshold == null) { + params.compute_threshold = threshold; + } + + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_random_bit_smult', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + var op_id = params.op_id; + + // Generate random bit + var random_bit, promise; + if (compute_list.indexOf(jiff.id) > -1) { + var bit = jiff.helpers.random(2); + var bit_shares = jiff.internal_share(bit, params.compute_threshold, compute_list, compute_list, Zp, op_id + ':share'); + + random_bit = bit_shares[compute_list[0]]; + for (var i = 1; i < compute_list.length; i++) { + var party_id = compute_list[i]; + var obit = bit_shares[party_id]; + random_bit = random_bit.isxor_bit(obit, op_id + ':sxor_bit:' + i); + } + + promise = random_bit.value; + } + + // Reshare + random_bit = jiff.reshare(random_bit, threshold, receivers_list, compute_list, Zp, op_id + ':reshare'); + if (receivers_list.indexOf(jiff.id) > -1) { + promise = random_bit.value; + } + return {share: random_bit, promise: promise}; + }, + /** + * Generates a random bit under MPC by xoring all bits sent by participating parties using smult_bgw + * @function generate_random_bit_bgw + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the generated bit) and 'promise' + */ + generate_random_bit_bgw: function (jiff, threshold, receivers_list, compute_list, Zp, params) { + if (params.compute_threshold == null) { + params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW + } + + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_random_bit_bgw', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + + var op_id = params.op_id; + + // Generate random bit + var random_bit, promise; + if (compute_list.indexOf(jiff.id) > -1) { + var bit = jiff.helpers.random(2); + var bit_shares = jiff.internal_share(bit, params.compute_threshold, compute_list, compute_list, Zp, op_id + ':share'); + + random_bit = bit_shares[compute_list[0]]; + for (var i = 1; i < compute_list.length; i++) { + var party_id = compute_list[i]; + var obit = bit_shares[party_id]; + random_bit = random_bit.isadd(obit).issub(random_bit.ismult_bgw(obit, op_id + ':smult' + i).icmult(2)); + } + + promise = random_bit.value; + } + + // Reshare + random_bit = jiff.reshare(random_bit, threshold, receivers_list, compute_list, Zp, op_id + ':reshare'); + if (receivers_list.indexOf(jiff.id) > -1) { + promise = random_bit.value; + } + return {share: random_bit, promise: promise}; + }, + /** + * Generates a sequence of random bits under MPC + * @function generate_random_bits + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} [threshold=receivers_list.length] - the threshold of the bit when stored by receivers after generation + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - count: how many random bits to generate + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @param {object} protocols - the protocols to use for preprocessing + * @return {Object} contains 'share' (array of secret shares bits) and 'promise' + */ + generate_random_bits: function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { + if (params.count == null) { + params.count = 1; + } + + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_random_bits', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + + var op_id = params.op_id; + var _params = params; + + var promises = []; + var bits = []; + for (var i = 0; i < params.count; i++) { + params = Object.assign({}, _params); + params.op_id = op_id + ':' + i; + + var bit = protocols.generate_random_bit(threshold, receivers_list, compute_list, Zp, params, protocols); + + promises.push(bit.value); + if (bit.share != null) { + bits.push(bit.share); + } + } + + if (bits.length === 0) { + bits = null; + } + return {share: bits, promise: Promise.all(promises)}; + } }; - },{}],36:[function(require,module,exports){ -/** - * Share the given share to all the parties in the jiff instance. - * @function jiff_broadcast - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. - * @param {module:jiff-client~JIFFClient#SecretShare} share - the share. - * @param {Array} parties - the parties to broadcast the share to. - * @param {number|string} op_id - a unique operation id, used to tag outgoing messages. - * - */ -var jiff_broadcast = function (jiff, share, parties, op_id) { - for (var index = 0; index < parties.length; index++) { - var i = parties[index]; // Party id - if (i === jiff.id) { - jiff.handlers.receive_open({ party_id: i, share: share.value, op_id: op_id, Zp: share.Zp }); - continue; - } - - // encrypt, sign and send - var msg = {party_id: i, share: share.value, op_id: op_id, Zp: share.Zp}; - msg = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'open', msg], 2); - - msg['share'] = jiff.hooks.encryptSign(jiff, msg['share'].toString(), jiff.keymap[msg['party_id']], jiff.secret_key); - jiff.socket.safe_emit('open', JSON.stringify(msg)); - } -}; - -module.exports = { - /** - * Open up the given share to the participating parties. - * @function jiff_open - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. - * @param {module:jiff-client~JIFFClient#SecretShare} share - the share of the secret to open that belongs to this party - * @param {Array} [parties=all_parties] - an array with party ids of receiving parties - * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages - * @returns {?promise} a (JQuery) promise to the open value of the secret, or null if the calling party is not a receiving party - * - */ - jiff_open: function (jiff, share, parties, op_id) { - var i; - - if (!(share.jiff === jiff)) { - throw 'share does not belong to given instance'; - } - - // Default values - if (parties == null || parties === []) { - parties = []; - for (i = 1; i <= jiff.party_count; i++) { - parties.push(i); - } - } else { - jiff.helpers.sort_ids(parties); - } - - // If not a receiver nor holder, do nothing - if (share.holders.indexOf(jiff.id) === -1 && parties.indexOf(jiff.id) === -1) { - return null; - } - - // Compute operation ids (one for each party that will receive a result - if (op_id == null) { - op_id = jiff.counters.gen_op_id2('open', parties, share.holders); - } - - // Party is a holder - if (share.holders.indexOf(jiff.id) > -1) { - // Call hook - share = jiff.hooks.execute_array_hooks('beforeOpen', [jiff, share, parties], 1); - - // refresh/reshare, so that the original share remains secret, instead - // a new share is sent/open without changing the actual value. - share = share.refresh(op_id + ':refresh'); - - // The given share has been computed, broadcast it to all parties - jiff.counters.pending_opens++; - share.wThen(function () { - jiff.counters.pending_opens--; - jiff_broadcast(jiff, share, parties, op_id); - }, share.error); - } - - // Party is a receiver - if (parties.indexOf(jiff.id) > -1) { - var final_deferred = new jiff.helpers.Deferred(); // will be resolved when the final value is reconstructed - var final_promise = final_deferred.promise; - - if (jiff.deferreds[op_id] == null) { - jiff.deferreds[op_id] = {}; - } - - jiff.deferreds[op_id].deferred = final_deferred; - jiff.deferreds[op_id].threshold = share.threshold; - jiff.deferreds[op_id].total = share.holders.length; - if (jiff.deferreds[op_id].shares != null && jiff.deferreds[op_id].shares.length >= share.threshold) { - final_deferred.resolve(); - } - - return final_promise.then(function () { - var shares = jiff.deferreds[op_id].shares; - - if (shares.length === jiff.deferreds[op_id].total) { - delete jiff.deferreds[op_id]; - } else { - jiff.deferreds[op_id].deferred = 'CLEAN'; - } - - var recons_secret = jiff.hooks.reconstructShare(jiff, shares); - recons_secret = jiff.hooks.execute_array_hooks('afterReconstructShare', [jiff, recons_secret], 1); - return recons_secret; - }); - } - - return null; - }, - /** - * Uses Lagrange polynomials to interpolate the polynomial - * described by the given shares (points) - * @function jiff_lagrange - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {Array} shares - an array of objects representing shares to reconstruct, every object has 3 attributes: value, sender_id, Zp - * @returns {number} the value of the polynomial at x=0 (the secret value) - * - */ - jiff_lagrange: function (jiff, shares) { - var lagrange_coeff = []; // will contain shares.length many elements. - - // Compute the Langrange coefficients at 0. - for (var i = 0; i < shares.length; i++) { - var pi = jiff.helpers.get_party_number(shares[i].sender_id); - lagrange_coeff[pi] = 1; - - for (var j = 0; j < shares.length; j++) { - var pj = jiff.helpers.get_party_number(shares[j].sender_id); - if (pj !== pi) { - var inv = jiff.helpers.extended_gcd(pi - pj, shares[i].Zp)[0]; - lagrange_coeff[pi] = jiff.helpers.mod(lagrange_coeff[pi] * (0 - pj), shares[i].Zp) * inv; - lagrange_coeff[pi] = jiff.helpers.mod(lagrange_coeff[pi], shares[i].Zp); - } - } - } - - // Reconstruct the secret via Lagrange interpolation - var recons_secret = 0; - for (var p = 0; p < shares.length; p++) { - var party = jiff.helpers.get_party_number(shares[p].sender_id); - var tmp = jiff.helpers.mod((shares[p].value * lagrange_coeff[party]), shares[p].Zp); - recons_secret = jiff.helpers.mod((recons_secret + tmp), shares[p].Zp); - } - - return recons_secret; - } +/** + * Can be used to generate shares of a random number, or shares of zero. + * For a random number, every party generates a local random number and secret share it, + * then every party sums its share, resulting in a single share of an unknown random number for every party. + * The same approach is followed for zero, but instead, all the parties know that the total number is zero, but they + * do not know the value of any resulting share (except their own) + * @function jiff_share_all_number + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} n - the number to share + * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers + * @param {Array} [receivers_list=all_parties] - array of party ids to receive the result, by default, this includes all parties + * @param {Array} [compute_list=all_parties] - array of party ids to perform the protocol, by default, this includes all parties + * @param {number} [Zp=jiff.Zp] - the mod + * @param {object} [params={}] - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the result) and 'promise' + */ +var jiff_share_all_number = function (jiff, n, threshold, receivers_list, compute_list, Zp, params) { + var isSender = compute_list.indexOf(jiff.id) > -1; + var isReceiver = receivers_list.indexOf(jiff.id) > -1; + + if (!isSender && !isReceiver) { + return {}; + } + + if (params.compute_threshold == null) { + params.compute_threshold = Math.min(threshold, compute_list.length); + } + + var result, promise; + if (isSender) { + var shares = jiff.internal_share(n, params.compute_threshold, compute_list, compute_list, Zp, params.op_id + ':share'); + result = shares[compute_list[0]]; + for (var i = 1; i < compute_list.length; i++) { + result = result.isadd(shares[compute_list[i]]); + } + promise = result.value; + } + + result = jiff.reshare(result, threshold, receivers_list, compute_list, Zp, params.op_id + ':reshare'); + if (receivers_list.indexOf(jiff.id) > -1) { + promise = result.value; + } + + return {share: result, promise: promise}; +}; + +module.exports = { + /** + * Creates shares of an unknown random number. Every party comes up with its own random number and shares it. + * Then every party combines all the received shares to construct one share of the random unknown number + * @function generate_random_number + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the result) and 'promise' + */ + generate_random_number: function (jiff, threshold, receivers_list, compute_list, Zp, params) { + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_random_number', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + return jiff_share_all_number(jiff, jiff.helpers.random(Zp), threshold, receivers_list, compute_list, Zp, params); + }, + /** + * Creates shares of 0, such that no party knows the other parties' shares. + * Every party secret shares 0, then every party sums all the shares they received, resulting + * in a new share of 0 for every party + * @function generate_zero + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff instance + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * @return {Object} contains 'share' (this party's share of the result) and 'promise' + */ + generate_zero: function (jiff, threshold, receivers_list, compute_list, Zp, params) { + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_zero', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + return jiff_share_all_number(jiff, 0, threshold, receivers_list, compute_list, Zp, params); + } }; },{}],37:[function(require,module,exports){ -/** - * re-share an existing share (value) under a new threshold or to a new set of parties or both. - * Do not use this to refresh a share (use {@link jiff-client~JIFFClient#SecretShare#refresh} instead) - * @function reshare - * @ignore - * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance - * @param {module:jiff-client~JIFFClient#SecretShare} [share=null] - the share you would like to reshare (null if you are a receiver but not a sender) - * @param {number} [threshold=receivers_list.length] - the new threshold, defaults to the length of receivers_list param - * @param {Array} [receivers_list=all_parties] - array of party ids to receive from, by default, this includes all parties - * @param {Array} [senders_list=all_parties] - array of party ids that posses the share and will reshare it with the receivers, by default, this includes all parties - * @param {number} [Zp=jiff.Zp] - the Zp of the existing share - * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). - * This id must be unique, and must be passed by all parties to the same instruction. - * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id - * is generated by increasing a local counter, default ids suffice when all parties execute the - * instructions in the same order - * @return {SecretShare} this party's share of the result under the new threshold, or null if this party is not a receiver - */ -module.exports = function (jiff, share, threshold, receivers_list, senders_list, Zp, op_id) { - var i; - - // default values - if (receivers_list == null) { - receivers_list = []; - for (i = 1; i <= jiff.party_count; i++) { - receivers_list.push(i); - } - } else { - jiff.helpers.sort_ids(receivers_list); - } - if (senders_list == null) { - senders_list = []; - for (i = 1; i <= jiff.party_count; i++) { - senders_list.push(i); - } - } else { - jiff.helpers.sort_ids(senders_list); - } - - if (threshold == null) { - threshold = receivers_list.length; - } - if (Zp == null) { - Zp = jiff.Zp; - } - - if (op_id == null) { - op_id = jiff.counters.gen_op_id('reshare', senders_list); - } - - // Check if this party is a sender or receiver - var isSender = senders_list.indexOf(jiff.id) > -1; - var isReceiver = receivers_list.indexOf(jiff.id) > -1; - if (!isSender && !isReceiver) { - return null; - } - - // optimization, if nothing changes, keep share - if (share != null && JSON.stringify(receivers_list) === JSON.stringify(senders_list) && threshold === share.threshold) { - return share; - } - - // Setup the result - var final_deferred; - var result = null; - if (isReceiver) { - final_deferred = new jiff.helpers.Deferred(); - result = new jiff.SecretShare(final_deferred.promise, receivers_list, threshold, Zp); - } - - // This function is called when the share is ready: the value of the share has been received. - var ready_share = function () { - var intermediate_shares = jiff.internal_share(isSender ? share.value : null, threshold, receivers_list, senders_list, Zp, op_id); - - if (isReceiver) { - var promises = []; - for (var i = 0; i < senders_list.length; i++) { - var party_id = senders_list[i]; - promises.push(intermediate_shares[party_id].value); - } - - // Reconstruct share under new threshold - Promise.all(promises).then(function () { - var reconstruct_parts = []; - for (var i = 0; i < senders_list.length; i++) { - var party_id = senders_list[i]; - //shamir reconstruct takes an array of objects - //has attributes: {value: x, sender_id: y, Zp: jiff_instance.Zp} - reconstruct_parts[i] = {value: intermediate_shares[party_id].value, sender_id: party_id, Zp: Zp}; - } - var value = jiff.hooks.reconstructShare(jiff, reconstruct_parts); - final_deferred.resolve(value); - }); - } - }; - - if (isSender && !share.ready) { - share.value.then(ready_share); - } else { // either a receiver or share is ready - ready_share(); - } - - return result; +/** + * Creates shares of r and x, such that r is a uniform random number between 0 and Zp, and x is floor(r/constant) + * where constant is provided by the extra params + * @function generate_random_and_quotient + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} threshold - the min number of parties needed to reconstruct the secret after it is computed + * @param {Array} receivers_list - array of party ids to receive the result + * @param {Array} compute_list - array of party ids to perform the protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - compute_threshold: the threshold to use during computation: defaults to compute_list.length + * - constant: the constant to divide the random number by. + * - output_op_id: the set op id of the output quotient and noise + * @return {Object} contains 'share' (this party's share of the result) and 'promise' + */ +module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { + // consistent and unique op_id for compute and receiver parties + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_random_and_quotient', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + + if (params.compute_threshold == null) { + params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW + } + + var constant = params.constant; + var op_id = params.op_id; + Zp = Zp ? jiff.Zp : Zp; + + // stores the result + var r, q; + + // for compute parties + var promise; + if (compute_list.indexOf(jiff.id) > -1) { + var largestQuotient = jiff.share_helpers['floor'](jiff.share_helpers['/'](Zp, constant)); + var largestMultiple = jiff.share_helpers['*'](largestQuotient, constant); + + // Uniform random number between [0, Zp) + var r_bits = jiff.protocols.bits.rejection_sampling(0, Zp, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection1'); + var cmp = jiff.protocols.bits.cgteq(r_bits, largestMultiple, params.output_op_id + ':bits_cgteq'); + var r1 = jiff.protocols.bits.bit_composition(r_bits); + + // Uniform random number between [0, Math.floor(Zp / constant)) + var quotient = jiff.protocols.bits.rejection_sampling(0, largestQuotient, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection2'); + quotient = jiff.protocols.bits.bit_composition(quotient); + + // Uniform random number between [0, constant) + var remainder = jiff.protocols.bits.rejection_sampling(0, constant, params.compute_threshold, compute_list, Zp, params.output_op_id + ':rejection3'); + remainder = jiff.protocols.bits.bit_composition(remainder); + var r2 = quotient.icmult(constant).isadd(remainder); + + // choose either (r1, largestQuotient) or (r2, quotient) based on cmp result + r = cmp.iif_else(r1, r2, params.output_op_id + ':ifelse1'); + q = cmp.iif_else(largestQuotient, quotient, params.output_op_id + ':ifelse2'); + promise = Promise.all([r.value, q.value]); + } + + // reshare the result with the designated receivers + r = jiff.reshare(r, threshold, receivers_list, compute_list, Zp, op_id + ':reshare1'); + q = jiff.reshare(q, threshold, receivers_list, compute_list, Zp, op_id + ':reshare2'); + + // return result + if (receivers_list.indexOf(jiff.id) > -1) { + promise = Promise.all([r.value, q.value]); + } + return {share: {r: r, q: q}, promise: promise}; }; },{}],38:[function(require,module,exports){ -module.exports = { - /** - * Default way of computing shares (can be overridden using hooks). - * Compute the shares of the secret (as many shares as parties) using Shamir secret sharing - * @ignore - * @function jiff_compute_shares - * @param {module:jiff-client~JIFFClient} jiff - the jiff instance - * @param {number} secret - the secret to share. - * @param {Array} parties_list - array of party ids to share with. - * @param {number} threshold - the min number of parties needed to reconstruct the secret, defaults to all the receivers. - * @param {number} Zp - the mod. - * @returns {object} a map between party number and its share, this means that (party number, share) is a - * point from the polynomial. - * - */ - jiff_compute_shares: function (jiff, secret, parties_list, threshold, Zp) { - var shares = {}; // Keeps the shares - var i; - - // Each player's random polynomial f must have - // degree threshold - 1, so that threshold many points are needed - // to interpolate/reconstruct. - var t = threshold - 1; - var polynomial = Array(t + 1); // stores the coefficients - - // Each players's random polynomial f must be constructed - // such that f(0) = secret - polynomial[0] = secret; - - // Compute the random polynomial f's coefficients - for (i = 1; i <= t; i++) { - polynomial[i] = jiff.helpers.random(Zp); - } - - // Compute each players share such that share[i] = f(i) - for (i = 0; i < parties_list.length; i++) { - var p_id = parties_list[i]; - shares[p_id] = polynomial[0]; - var power = jiff.helpers.get_party_number(p_id); - - for (var j = 1; j < polynomial.length; j++) { - var tmp = jiff.helpers.mod((polynomial[j] * power), Zp); - shares[p_id] = jiff.helpers.mod((shares[p_id] + tmp), Zp); - power = jiff.helpers.mod(power * jiff.helpers.get_party_number(p_id), Zp); - } - } - - return shares; - }, - /** - * Share given secret to the participating parties. - * @ignore - * @function jiff_share - * @param {module:jiff-client~JIFFClient} jiff - the jiff instance - * @param {number} secret - the secret to share. - * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. - * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. - * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. - * @param {number} [Zp=jiff.Zp] - the mod (if null then the default Zp for the instance is used). - * @param {string|number} [share_id=auto_gen()] - the tag used to tag the messages sent by this share operation, this tag is used - * so that parties distinguish messages belonging to this share operation from other - * share operations between the same parties (when the order of execution is not - * deterministic). An automatic id is generated by increasing a local counter, default - * ids suffice when all parties execute all sharing operations with the same senders - * and receivers in the same order. - * @returns {object} a map where the key is the sender party id - * and the value is the share object that wraps - * what was sent from that party (the internal value maybe deferred). - * if the party that calls this function is not a receiver then the map - * will be empty. - */ - jiff_share: function (jiff, secret, threshold, receivers_list, senders_list, Zp, share_id) { - var i, p_id; - - // defaults - if (Zp == null) { - Zp = jiff.Zp; - } - if (receivers_list == null) { - receivers_list = []; - for (i = 1; i <= jiff.party_count; i++) { - receivers_list.push(i); - } - } else { - jiff.helpers.sort_ids(receivers_list); - } - if (senders_list == null) { - senders_list = []; - for (i = 1; i <= jiff.party_count; i++) { - senders_list.push(i); - } - } else { - jiff.helpers.sort_ids(senders_list); - } - if (threshold == null) { - threshold = receivers_list.length; - } - if (threshold < 0) { - threshold = 2; - } - if (threshold > receivers_list.length) { - threshold = receivers_list.length; - } - - // if party is uninvolved in the share, do nothing - if (receivers_list.indexOf(jiff.id) === -1 && senders_list.indexOf(jiff.id) === -1) { - return {}; - } - - // compute operation id - if (share_id == null) { - share_id = jiff.counters.gen_op_id2('share', receivers_list, senders_list); - } - - // stage sending of shares - if (senders_list.indexOf(jiff.id) > -1) { - // Call hook - secret = jiff.hooks.execute_array_hooks('beforeShare', [jiff, secret, threshold, receivers_list, senders_list, Zp], 1); - - // compute shares - var shares = jiff.hooks.computeShares(jiff, secret, receivers_list, threshold, Zp); - - // Call hook - shares = jiff.hooks.execute_array_hooks('afterComputeShare', [jiff, shares, threshold, receivers_list, senders_list, Zp], 1); - - // send shares - for (i = 0; i < receivers_list.length; i++) { - p_id = receivers_list[i]; - if (p_id === jiff.id) { - continue; - } - - // send encrypted and signed shares_id[p_id] to party p_id - var msg = {party_id: p_id, share: shares[p_id], op_id: share_id}; - msg = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'share', msg], 2); - - msg['share'] = jiff.hooks.encryptSign(jiff, msg['share'].toString(10), jiff.keymap[msg['party_id']], jiff.secret_key); - jiff.socket.safe_emit('share', JSON.stringify(msg)); - } - } - - // stage receiving of shares - var result = {}; - if (receivers_list.indexOf(jiff.id) > -1) { - // setup a map of deferred for every received share - if (jiff.deferreds[share_id] == null) { - jiff.deferreds[share_id] = {}; - } - - var _remaining = senders_list.length; - for (i = 0; i < senders_list.length; i++) { - p_id = senders_list[i]; - if (p_id === jiff.id) { // Keep party's own share - var my_share = jiff.hooks.execute_array_hooks('receiveShare', [jiff, p_id, shares[p_id]], 2); - result[p_id] = new jiff.SecretShare(my_share, receivers_list, threshold, Zp); - _remaining--; - continue; - } - - // check if a deferred is set up (maybe the message was previously received) - if (jiff.deferreds[share_id][p_id] == null) { // not ready, setup a deferred - jiff.deferreds[share_id][p_id] = new jiff.helpers.Deferred(); - } - - var promise = jiff.deferreds[share_id][p_id].promise; - // destroy deferred when done - (function (promise, p_id) { // p_id is modified in a for loop, must do this to avoid scoping issues. - promise.then(function () { - delete jiff.deferreds[share_id][p_id]; - _remaining--; - if (_remaining === 0) { - delete jiff.deferreds[share_id]; - } - }); - })(promise, p_id); - - // receive share_i[id] from party p_id - result[p_id] = new jiff.SecretShare(promise, receivers_list, threshold, Zp); - } - } +var sample = function (jiff, range, compute_list, Zp, params, protocols, reject_count) { + // Transform sampling range into bit size + var bitLength = jiff.helpers.ceil(jiff.helpers.bLog(range, 2)); + bitLength = parseInt(bitLength.toString(), 10); + + var paramsCopy = Object.assign({}, params); + paramsCopy['count'] = bitLength; + paramsCopy['op_id'] = params.op_id + ':sampling:' + reject_count; + return protocols.generate_random_bits(params.compute_threshold, compute_list, compute_list, Zp, paramsCopy, protocols).share; +}; + +var one_round_sampling = function (jiff, lower_bound, upper_bound, compute_list, Zp, params, protocols, finalLength, reject_count) { + // Figure out sampling range + var range; + if (upper_bound.isBigNumber === true) { + range = upper_bound.minus(lower_bound); + } else { + range = upper_bound - lower_bound; + } + + // Special cases + if (range.toString() === '0') { + throw new Error('rejection sampling called with range 0, no numbers to sample!'); + } + if (range.toString() === '1') { + var zero = protocols.generate_zero(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; + // special case: cadd can be performed locally on bit arrays of length 1! + var resultOne = jiff.protocols.bits.cadd([zero], lower_bound); + while (resultOne.length > finalLength) { + resultOne.pop(); + } + return {share: resultOne, promise: true}; + } + + // Rejection protocol + var bits = sample(jiff, range, compute_list, Zp, params, protocols, reject_count); + var cmp = jiff.protocols.bits.clt(bits, range, params.output_op_id + ':bits.clt:' + reject_count); + var bits_add = jiff.protocols.bits.cadd(bits, lower_bound, params.output_op_id + ':bits.cadd:' + reject_count); + + if (cmp === true) { + return {share: bits_add, promise: true}; + } else if (cmp === false) { // need to resample + return {share: bits_add, promise: false}; + } + + var promise = jiff.internal_open(cmp, compute_list, params.output_op_id + ':open:' + reject_count); + return {share: bits_add, promise: promise.then( + function (cmp) { + return cmp.toString() === '1'; + } + )}; +}; + +var computeParty = function (jiff, lower_bound, upper_bound, threshold, receivers_list, compute_list, Zp, params, protocols, op_id, finalLength, reject_count) { + var result = one_round_sampling(jiff, lower_bound, upper_bound, compute_list, Zp, params, protocols, finalLength, reject_count); + + // Case 1: we know whether sampling succeeded or not + if (result.promise === true) { + return reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, result.share); + } + if (result.promise === false) { + return {share: 'RETRY', promise: jiff.utils.all_promises(result.share)}; + } + + // Case 2: we only have a promise to whether the sampling succeeded or not + var many_shares = jiff.utils.many_secret_shares(finalLength, compute_list, threshold, Zp); + var final_deferreds = many_shares.deferreds; + + result.promise.then(function (promiseVal) { + // RETRY and PLACEHOLDER shares are cleaned up later in the preprocessing pipeline + if (promiseVal === false) { + for (var i = 0; i < final_deferreds.length; i++) { + final_deferreds[i].resolve('RETRY'); + } + return; + } + + // Need to make sure party only executes the reshare operation if sampling succeeds + var reshared = reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, result.share); + + if (receivers_list.indexOf(jiff.id) > -1) { + jiff.utils.resolve_many_secrets(final_deferreds, reshared.share); + } else { + for (i = 0; i < final_deferreds.length; i++) { + final_deferreds[i].resolve('PLACEHOLDER'); + } + } + }); + + return {share: many_shares.shares, promise: jiff.utils.all_promises(many_shares.shares)}; +}; + +var reshareResult = function (jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, shares) { + // fix threshold and parties + var promises = []; + for (var i = 0; i < finalLength; i++) { + if (compute_list.indexOf(jiff.id) > -1) { + promises[i] = shares[i].value; + } + shares[i] = jiff.reshare(shares[i], threshold, receivers_list, compute_list, Zp, op_id + ':reshare:' + i); + if (receivers_list.indexOf(jiff.id) > -1) { + promises[i] = shares[i].value; + } + } + + // return output + if (receivers_list.indexOf(jiff.id) === -1) { + shares = null; + } + + // handle rejection case + return {share: shares, promise: Promise.all(promises)}; +}; + +/** + * Wrapper for when doing rejection sampling during pre processing + * + * Do not use this function directly, especially during online computation time, use jiffClient.protocols.bits.rejection_sampling instead + * + * @function sampling + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} [threshold=receivers_list.length] - the threshold of the resulting shares after sampling + * @param {Array} [receivers_list=all_parties] - array of party ids that want to receive the sampling shares, by default, this includes all parties + * @param {Array} [compute_list=all_parties] - array of party ids that will perform this protocol, by default, this includes all parties + * @param {number} [Zp=jiff-instance.Zp] - the mod (if null then the default Zp for the instance is used) + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this operation. + * This id must be unique, and must be passed by all parties to the same instruction, to + * ensure that corresponding instructions across different parties are matched correctly + * @param {object} [params={}] - an object containing extra parameters passed by the user + * Expects: + * - compute_threshold, an optional number compute_threshold parameter, which specifies threshold used + * during the protocol execution. By default, this is (|compute_list|+1)/2 + * - optional 'lower_bound' and 'upper_bound', numeric parameters, default to 0 and Zp respectively + * - op_id, the base op_id to tag operations inside this protocol with, defaults to auto generated + * - output_op_id, the tag id for the output result + * - retry_count, how many times rejection sampling have been retried! + * @param {object} [protocols=defaults] - the protocols to use for preprocessing, any protocol(s) not provided will be replaced with defaults + * @returns {Object} an object containing keys: 'share', and 'promise'. The promise is resolved when the rejection sampling is completed. + * The object is consumed by .preprocessing: + * - 'share' attribute contains the resulting array of secret shared bits representing the sampled value, and is stored in the preprocessing table internally + * - The promise is consumed and a new promise is returned by .preprocessing that is resolved after this returned promise (and all other promise generated by that .preprocessing call) are resolved + */ +module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { + // Internal version: set parameters (e.g. receivers_list) do not need defaults + // defaults (for internal preprocessing) + var lower_bound = params.lower_bound != null ? params.lower_bound : 0; + var upper_bound = params.upper_bound != null ? params.upper_bound : Zp; + if (params.compute_threshold == null) { // honest majority BGW + params.compute_threshold = Math.floor((compute_list.length + 1) / 2); + } + + // Figure out final bit size (after adding back lower) + var finalLength = jiff.helpers.ceil(jiff.helpers.bLog(upper_bound, 2)); + finalLength = parseInt(finalLength.toString(), 10); + finalLength = Math.max(finalLength, 1); // special case: when upper_bound is 1! + + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('rejection_sampling', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + var op_id = params.op_id; + + // Rejection count + var reject_count = params.reject_count || 0; + + if (compute_list.indexOf(jiff.id) === -1) { + return reshareResult(jiff, upper_bound, threshold, receivers_list, compute_list, Zp, op_id, finalLength, []) + } + + return computeParty(jiff, lower_bound, upper_bound, threshold, receivers_list, compute_list, Zp, params, protocols, op_id, finalLength, reject_count); +}; - return result; - } -}; },{}],39:[function(require,module,exports){ -var genericProtocols = require('./protocols/generic.js'); -var arithmetic = require('./protocols/numbers/arithmetic.js'); -var comparison = require('./protocols/numbers/comparison.js'); -var protocols = require('./protocols/numbers/protocols.js'); -var booleans = require('./protocols/booleans/boolean.js'); - -// a metaclass that creates SecretShare classes when given a jiff instance -// alternatively, we can think of this as a factory for a secret share prototypes/constructors given a jiff instance -module.exports = function (jiff) { - // Look at jiff-client#SecretShare - function SecretShare(value, holders, threshold, Zp) { - // sort holders - jiff.helpers.sort_ids(holders); - - /** - * Indicates if the secret share's value is ready or still a promise - * @member {boolean} ready - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - this.ready = (value.then == null); - - /** - * The value of the share (or a promise to it) - * @member {number|promise} value - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - this.value = value; - - /** - * Array of party ids who hold shares of the corresponding secret - * @member {Array} holders - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - this.holders = holders; - /** - * The sharing threshold - * @member {number} threshold - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - this.threshold = threshold; - - /** - * The field prime under which the corresponding secret is shared - * @member {number} Zp - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - this.Zp = Zp; - - // when the promise is resolved, acquire the value of the share and set ready to true - if (!this.ready) { - this.value = this.value.then(this.promise_handler.bind(this), this.error.bind(this)); - this.jiff.add_to_barriers(this.value); - } - - // return the share - return jiff.hooks.execute_array_hooks('createSecretShare', [jiff, this], 1); - } - - /** - * The jiff client instance this share belongs to - * @member {module:jiff-client~JIFFClient} jiff - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.jiff = jiff; - - // Basic operations in prototype of SecretShare - /** - * Gets the value of this share - * @method valueOf - * @returns {number} the value (undefined if not ready yet) - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.valueOf = function () { - if (this.ready) { - return this.value; - } else { - return undefined; - } - }; - - /** - * Gets a string representation of this share - * @method toString - * @returns {string} the id and value of the share as a string - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - */ - SecretShare.prototype.toString = function () { - var val = this.ready ? this.value : ''; - return 'share: ' + val + '. Holders: ' + JSON.stringify(this.holders) + '. Threshold: ' + this.threshold + '. Zp: ' + this.Zp.toString() + '.'; - }; - - /** - * Logs an error. Passes the error on to the associated jiff client instance's {@link handlers.error} - * @method error - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {string|error} error - the error to log - */ - SecretShare.prototype.error = function (error) { - this.jiff.handlers.error('SecretShare', error); - }; - - /** - * Logs the value represented by this share to the console - * WARNING: THIS LEAKS INFORMATION AND MUST BE USED ONLY TO DEBUG ON FAKE DATA - * @method logLEAK - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {string} tag - accompanying tag to display in the console - * @param {Array} [parties=[holders[0]] - the parties which will display the log - * @param {string|number|object} [op_id=auto_gen()] - same as {@link module:jiff-client:JIFFClient#open} - * @return {?promise} a promise to the value represented by this share after logging it, null if party is not in parties - */ - SecretShare.prototype.logLEAK = function (tag, parties, op_id) { - if (parties == null) { - parties = [this.holders[0]]; - } - var promise = this.open(parties, tag, op_id); - if (promise != null) { - promise = promise.then(function (result) { - console.log(tag, result.toString()); - return result; - }, this.error); - } - return promise; - }; - - /** - * Handler for when this share's promise (if any) is resolved - * @method promise_handler - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {number} value - the value of the share after it was resolved - */ - SecretShare.prototype.promise_handler = function (value) { - this.value = value; - this.ready = true; - return this.value; - }; - - /** - * Executes callback when both this share and o are ready and returns the result (or a promise to the result) - * @method when_both_ready - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {SecretShare} o - the other share object. - * @param {function()} cb - the callback to execute. - * @returns {value|promise} either the return value of cb() or a promise to it - */ - SecretShare.prototype.when_both_ready = function (o, cb) { - if (this.ready && o.ready) { - return cb(); - } - - if (this.ready) { - return o.value.then(cb, this.error); - } else if (o.ready) { - return this.value.then(cb, this.error); - } else { - return Promise.all([this.value, o.value]).then(cb, this.error); - } - }; - - /** - * Shortcut for opening/revealing the value of this share. Alias for open in jiff-instance - * @see jiff-instance#open - * @method open - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties - * @param {string|number|object} [op_id=auto_gen()] - same as {@link module:jiff-client:JIFFClient#open} - * @returns {?promise} a (JQuery) promise to the open value of the secret, null if the party is not specified in - * the parties array as a receiver - */ - SecretShare.prototype.open = function (parties, op_id) { - return this.jiff.open(this, parties, op_id); - }; - - /** - * Wrapper around share.value.then. - * In case share is ready (its promise is resolved and cleared) - * The callback is executed immediately. - * Does not support chaining - * @method wThen - * @memberof module:jiff-client~JIFFClient#SecretShare - * @instance - * @param {function} onFulfilled - callback for success, called with this.value as parameter - * @param {function} [onRejected=this.error] - callback for errors - * @return {promise|value} either the result of executing onFulfilled or a promise to it - */ - SecretShare.prototype.wThen = function (onFulfilled, onRejected) { - if (this.ready) { - return onFulfilled(this.value); - } else { - if (onRejected == null) { - onRejected = this.error; - } - return this.value.then(onFulfilled, onRejected); - } - }; - - // Complex protocols in prototype of SecretShare - genericProtocols(SecretShare); - arithmetic(SecretShare); - comparison(SecretShare); - protocols(SecretShare); - booleans(SecretShare); - - // internal variant of primitives, to use internally by other primitives - var internals = ['cadd', 'csub', 'cmult', 'sadd', 'ssub', 'smult', 'smult_bgw', - 'cxor_bit', 'sxor_bit', 'cor_bit', 'sor_bit', - 'slt', 'slteq', 'sgt', 'sgteq', 'seq', 'sneq', - 'clt', 'clteq', 'cgt', 'cgteq', 'ceq', 'cneq', - 'sdiv', 'cdiv', 'not', 'cpow', 'lt_halfprime', 'if_else']; - for (var i = 0; i < internals.length; i++) { - var key = internals[i]; - SecretShare.prototype['i' + key] = SecretShare.prototype[key]; - } +/** + * Generation of beaver triplet via MPC, uses the server for communication channels, but not for generation + * @function generate_beaver_bgw + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {number} threshold - the threshold of the triplets when stored by receivers after generation + * @param {Array} receivers_list - array of party ids that want to receive the triplet shares + * @param {Array} compute_list - array of party ids that will perform this protocol + * @param {number} Zp - the mod + * @param {object} params - an object containing extra parameters passed by the user + * Expects: + * - op_id: the base id to use for operation during the execution of this protocol, defaults to auto generated + * - an optional number compute_threshold parameter, which specifies threshold used + * during the protocol execution. By default, this is the length of the (compute_list+1)/2 + * @param {object} protocols - the sub protocols to use for preprocessing + * @return {object} all pre-processing protocols must return an object with these keys: + * { + * 'share': the share(s)/value(s) to store attached to op_id for later use by the computation (i.e. the result of preprocessing), + * 'promise': a promise for when this protocol is fully completed (could be null if the protocol was already completed) + * } + * In this case, 'share' is an array of this party's shares of the resulting triplet, a,b,c such that a*b=c + */ +module.exports = function (jiff, threshold, receivers_list, compute_list, Zp, params, protocols) { + if (params.compute_threshold == null) { + params.compute_threshold = Math.floor((compute_list.length + 1) / 2); // honest majority BGW + } + if (params.op_id == null && params.output_op_id == null) { + params.op_id = jiff.counters.gen_op_id2('generate_beaver_bgw', receivers_list, compute_list); + } else if (params.op_id == null) { + params.op_id = 'preprocessing:' + params.output_op_id + ':' + compute_list.join(','); + } + + var op_id = params.op_id; + var _params = params; + + var a, b, c, promises; + if (compute_list.indexOf(jiff.id) > -1) { + params = Object.assign({}, _params); + params.op_id = op_id + ':share_a'; + a = protocols.generate_random_number(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; + + params = Object.assign({}, _params); + params.op_id = op_id + ':share_b'; + b = protocols.generate_random_number(params.compute_threshold, compute_list, compute_list, Zp, params, protocols).share; + + c = a.ismult_bgw(b, op_id + ':smult_bgw'); + promises = [a.value, b.value, c.value]; + } + + a = jiff.reshare(a, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_a'); + b = jiff.reshare(b, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_b'); + c = jiff.reshare(c, threshold, receivers_list, compute_list, Zp, op_id + ':reshare_c'); + if (receivers_list.indexOf(jiff.id) > -1) { + promises = [a.value, b.value, c.value]; + } + + return { share: [a, b, c], promise: Promise.all(promises) }; +}; - return SecretShare; -}; -},{"./protocols/booleans/boolean.js":26,"./protocols/generic.js":27,"./protocols/numbers/arithmetic.js":28,"./protocols/numbers/comparison.js":29,"./protocols/numbers/protocols.js":30}],40:[function(require,module,exports){ -module.exports = { - '+': function (v1, v2) { - return v1 + v2; - }, - '-': function (v1, v2) { - return v1 - v2; - }, - '*': function (v1, v2) { - return v1 * v2; - }, - '/': function (v1, v2) { - return v1 / v2; - }, - '<': function (v1, v2) { - return v1 < v2; - }, - '<=': function (v1, v2) { - return v1 <= v2; - }, - 'floor': function (v) { - return Math.floor(v); - }, - 'ceil': function (v) { - return Math.ceil(v); - }, - 'floor/': function (v1, v2) { - return Math.floor(v1 / v2); - }, - 'pow': function (v1, v2) { - return Math.pow(v1, v2); - }, - 'binary': function (v) { - return v === 1 || v === 0; - }, - 'abs': function (v) { - return Math.abs(v); - }, - '==': function (v1, v2) { - return v1 === v2; - }, - 'even': function (v1) { - return (v1 % 2) === 0; - } +},{}],40:[function(require,module,exports){ +/** + * Share the given share to all the parties in the jiff instance. + * @function jiff_broadcast + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. + * @param {module:jiff-client~JIFFClient#SecretShare} share - the share. + * @param {Array} parties - the parties to broadcast the share to. + * @param {number|string} op_id - a unique operation id, used to tag outgoing messages. + * + */ +var jiff_broadcast = function (jiff, share, parties, op_id) { + for (var index = 0; index < parties.length; index++) { + var i = parties[index]; // Party id + if (i === jiff.id) { + jiff.handlers.receive_open({ party_id: i, share: share.value, op_id: op_id, Zp: share.Zp }); + continue; + } + + // encrypt, sign and send + var msg = {party_id: i, share: share.value, op_id: op_id, Zp: share.Zp}; + msg = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'open', msg], 2); + + msg['share'] = jiff.hooks.encryptSign(jiff, msg['share'].toString(), jiff.keymap[msg['party_id']], jiff.secret_key); + jiff.socket.safe_emit('open', JSON.stringify(msg)); + } +}; + +module.exports = { + /** + * Open up the given share to the participating parties. + * @function jiff_open + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance. + * @param {module:jiff-client~JIFFClient#SecretShare} share - the share of the secret to open that belongs to this party + * @param {Array} [parties=all_parties] - an array with party ids of receiving parties + * @param {string|number} [op_id=auto_gen()] - the operation id to be used to tag outgoing messages + * @returns {?promise} a (JQuery) promise to the open value of the secret, or null if the calling party is not a receiving party + * + */ + jiff_open: function (jiff, share, parties, op_id) { + var i; + + if (!(share.jiff === jiff)) { + throw 'share does not belong to given instance'; + } + + // Default values + if (parties == null || parties === []) { + parties = []; + for (i = 1; i <= jiff.party_count; i++) { + parties.push(i); + } + } else { + jiff.helpers.sort_ids(parties); + } + + // If not a receiver nor holder, do nothing + if (share.holders.indexOf(jiff.id) === -1 && parties.indexOf(jiff.id) === -1) { + return null; + } + + // Compute operation ids (one for each party that will receive a result + if (op_id == null) { + op_id = jiff.counters.gen_op_id2('open', parties, share.holders); + } + + // Party is a holder + if (share.holders.indexOf(jiff.id) > -1) { + // Call hook + share = jiff.hooks.execute_array_hooks('beforeOpen', [jiff, share, parties], 1); + + // refresh/reshare, so that the original share remains secret, instead + // a new share is sent/open without changing the actual value. + share = share.refresh(op_id + ':refresh'); + + // The given share has been computed, broadcast it to all parties + jiff.counters.pending_opens++; + share.wThen(function () { + jiff.counters.pending_opens--; + jiff_broadcast(jiff, share, parties, op_id); + }, share.error); + } + + // Party is a receiver + if (parties.indexOf(jiff.id) > -1) { + var final_deferred = new jiff.helpers.Deferred(); // will be resolved when the final value is reconstructed + var final_promise = final_deferred.promise; + + if (jiff.deferreds[op_id] == null) { + jiff.deferreds[op_id] = {}; + } + + jiff.deferreds[op_id].deferred = final_deferred; + jiff.deferreds[op_id].threshold = share.threshold; + jiff.deferreds[op_id].total = share.holders.length; + if (jiff.deferreds[op_id].shares != null && jiff.deferreds[op_id].shares.length >= share.threshold) { + final_deferred.resolve(); + } + + return final_promise.then(function () { + var shares = jiff.deferreds[op_id].shares; + + if (shares.length === jiff.deferreds[op_id].total) { + delete jiff.deferreds[op_id]; + } else { + jiff.deferreds[op_id].deferred = 'CLEAN'; + } + + var recons_secret = jiff.hooks.reconstructShare(jiff, shares); + recons_secret = jiff.hooks.execute_array_hooks('afterReconstructShare', [jiff, recons_secret], 1); + return recons_secret; + }); + } + + return null; + }, + /** + * Uses Lagrange polynomials to interpolate the polynomial + * described by the given shares (points) + * @function jiff_lagrange + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {Array} shares - an array of objects representing shares to reconstruct, every object has 3 attributes: value, sender_id, Zp + * @returns {number} the value of the polynomial at x=0 (the secret value) + * + */ + jiff_lagrange: function (jiff, shares) { + var lagrange_coeff = []; // will contain shares.length many elements. + + // Compute the Langrange coefficients at 0. + for (var i = 0; i < shares.length; i++) { + var pi = jiff.helpers.get_party_number(shares[i].sender_id); + lagrange_coeff[pi] = 1; + + for (var j = 0; j < shares.length; j++) { + var pj = jiff.helpers.get_party_number(shares[j].sender_id); + if (pj !== pi) { + var inv = jiff.helpers.extended_gcd(pi - pj, shares[i].Zp)[0]; + lagrange_coeff[pi] = jiff.helpers.mod(lagrange_coeff[pi] * (0 - pj), shares[i].Zp) * inv; + lagrange_coeff[pi] = jiff.helpers.mod(lagrange_coeff[pi], shares[i].Zp); + } + } + } + + // Reconstruct the secret via Lagrange interpolation + var recons_secret = 0; + for (var p = 0; p < shares.length; p++) { + var party = jiff.helpers.get_party_number(shares[p].sender_id); + var tmp = jiff.helpers.mod((shares[p].value * lagrange_coeff[party]), shares[p].Zp); + recons_secret = jiff.helpers.mod((recons_secret + tmp), shares[p].Zp); + } + + return recons_secret; + } }; },{}],41:[function(require,module,exports){ -module.exports = function (JIFFClient) { - /** - * Initialize socket listeners and events - * @memberof module:jiff-client.JIFFClient - * @method - */ - JIFFClient.prototype.initSocket = function () { - var jiffClient = this; - - // set on('connect') handler once! - this.socket.on('connect', jiffClient.handlers.connected); - - // Store the id when server sends it back - this.socket.on('initialization', jiffClient.handlers.initialized); - - // Public keys were updated on the server, and it sent us the updates - jiffClient.socket.on('public_keys', function (msg, callback) { - callback(true); - - msg = JSON.parse(msg); - msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'public_keys', msg], 2); - - jiffClient.handlers.store_public_keys(msg.public_keys); - }); - - // Setup receiving matching shares - this.socket.on('share', function (msg, callback) { - callback(true); // send ack to server - - // parse message - var json_msg = JSON.parse(msg); - var sender_id = json_msg['party_id']; - - if (jiffClient.keymap[sender_id] != null) { - jiffClient.handlers.receive_share(json_msg); - } else { - if (jiffClient.messagesWaitingKeys[sender_id] == null) { - jiffClient.messagesWaitingKeys[sender_id] = []; - } - jiffClient.messagesWaitingKeys[sender_id].push({label: 'share', msg: json_msg}); - } - }); - - this.socket.on('open', function (msg, callback) { - callback(true); // send ack to server - - // parse message - var json_msg = JSON.parse(msg); - var sender_id = json_msg['party_id']; - - if (jiffClient.keymap[sender_id] != null) { - jiffClient.handlers.receive_open(json_msg); - } else { - if (jiffClient.messagesWaitingKeys[sender_id] == null) { - jiffClient.messagesWaitingKeys[sender_id] = []; - } - jiffClient.messagesWaitingKeys[sender_id].push({label: 'open', msg: json_msg}); - } - }); - - // handle custom messages - this.socket.on('custom', function (msg, callback) { - callback(true); // send ack to server - - var json_msg = JSON.parse(msg); - var sender_id = json_msg['party_id']; - var encrypted = json_msg['encrypted']; - - if (jiffClient.keymap[sender_id] != null || encrypted !== true) { - jiffClient.handlers.receive_custom(json_msg); - } else { - // key must not exist yet for sender_id, and encrypted must be true - if (jiffClient.messagesWaitingKeys[sender_id] == null) { - jiffClient.messagesWaitingKeys[sender_id] = []; - } - jiffClient.messagesWaitingKeys[sender_id].push({label: 'custom', msg: json_msg}); - } - }); - - this.socket.on('crypto_provider', function (msg, callback) { - callback(true); // send ack to server - jiffClient.handlers.receive_crypto_provider(JSON.parse(msg)); - }); - - this.socket.on('error', function (msg) { - try { - msg = JSON.parse(msg); - jiffClient.handlers.error(msg['label'], msg['error']); - } catch (error) { - jiffClient.handlers.error('socket.io', msg); - } - }); - - this.socket.on('disconnect', function (reason) { - if (reason !== 'io client disconnect') { - // check that the reason is an error and not a user initiated disconnect - console.log('Disconnected!', jiffClient.id, reason); - } - - jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'disconnect', reason], -1); - }); - }; - - /** - * Executes all callbacks for which the wait condition has been satisfied. - * Remove all executed callbacks so that they would not be executed in the future. - * @memberof module:jiff-client.JIFFClient - * @method - */ - JIFFClient.prototype.execute_wait_callbacks = function () { - var copy_callbacks = this.wait_callbacks; - this.wait_callbacks = []; - for (var i = 0; i < copy_callbacks.length; i++) { - var wait = copy_callbacks[i]; - var parties = wait.parties; - var callback = wait.callback; - var initialization = wait.initialization; - - // Check if the parties to wait for are now known - var parties_satisfied = this.__initialized || !initialization; - for (var j = 0; j < parties.length; j++) { - var party_id = parties[j]; - if (this.keymap == null || this.keymap[party_id] == null) { - parties_satisfied = false; - break; - } - } - - if (parties_satisfied) { - callback(this); - } else { - this.wait_callbacks.push(wait); - } - } - }; - - /** - * Resolves all messages that were pending because their senders primary key was previously unknown. - * These messages are decrypted and verified and handled appropriatly before being removed from the wait queue. - * @memberof module:jiff-client.JIFFClient - * @method - */ - JIFFClient.prototype.resolve_messages_waiting_for_keys = function () { - for (var party_id in this.keymap) { - if (!this.keymap.hasOwnProperty(party_id)) { - continue; - } - - var messageQueue = this.messagesWaitingKeys[party_id]; - if (messageQueue == null) { - continue; - } - for (var i = 0; i < messageQueue.length; i++) { - var msg = messageQueue[i]; - if (msg.label === 'share') { - this.handlers.receive_share(msg.msg); - } else if (msg.label === 'open') { - this.handlers.receive_open(msg.msg); - } else if (msg.label === 'custom') { - this.handlers.receive_custom(msg.msg); - } else { - throw new Error('Error resolving pending message: unknown label ' + msg.label); - } - } - - this.messagesWaitingKeys[party_id] = null; - } - }; +/** + * re-share an existing share (value) under a new threshold or to a new set of parties or both. + * Do not use this to refresh a share (use {@link jiff-client~JIFFClient#SecretShare#refresh} instead) + * @function reshare + * @ignore + * @param {module:jiff-client~JIFFClient} jiff - the jiff client instance + * @param {module:jiff-client~JIFFClient#SecretShare} [share=null] - the share you would like to reshare (null if you are a receiver but not a sender) + * @param {number} [threshold=receivers_list.length] - the new threshold, defaults to the length of receivers_list param + * @param {Array} [receivers_list=all_parties] - array of party ids to receive from, by default, this includes all parties + * @param {Array} [senders_list=all_parties] - array of party ids that posses the share and will reshare it with the receivers, by default, this includes all parties + * @param {number} [Zp=jiff.Zp] - the Zp of the existing share + * @param {string} [op_id=auto_gen()] - the operation id which is used to identify this multiplication (and internally, the corresponding beaver triplet). + * This id must be unique, and must be passed by all parties to the same instruction. + * this ensures that every party gets a share from the same triplet for every matching instruction. An automatic id + * is generated by increasing a local counter, default ids suffice when all parties execute the + * instructions in the same order + * @return {SecretShare} this party's share of the result under the new threshold, or null if this party is not a receiver + */ +module.exports = function (jiff, share, threshold, receivers_list, senders_list, Zp, op_id) { + var i; + + // default values + if (receivers_list == null) { + receivers_list = []; + for (i = 1; i <= jiff.party_count; i++) { + receivers_list.push(i); + } + } else { + jiff.helpers.sort_ids(receivers_list); + } + if (senders_list == null) { + senders_list = []; + for (i = 1; i <= jiff.party_count; i++) { + senders_list.push(i); + } + } else { + jiff.helpers.sort_ids(senders_list); + } + + if (threshold == null) { + threshold = receivers_list.length; + } + if (Zp == null) { + Zp = jiff.Zp; + } + + if (op_id == null) { + op_id = jiff.counters.gen_op_id('reshare', senders_list); + } + + // Check if this party is a sender or receiver + var isSender = senders_list.indexOf(jiff.id) > -1; + var isReceiver = receivers_list.indexOf(jiff.id) > -1; + if (!isSender && !isReceiver) { + return null; + } + + // optimization, if nothing changes, keep share + if (share != null && JSON.stringify(receivers_list) === JSON.stringify(senders_list) && threshold === share.threshold) { + return share; + } + + // Setup the result + var final_deferred; + var result = null; + if (isReceiver) { + final_deferred = new jiff.helpers.Deferred(); + result = new jiff.SecretShare(final_deferred.promise, receivers_list, threshold, Zp); + } + + // This function is called when the share is ready: the value of the share has been received. + var ready_share = function () { + var intermediate_shares = jiff.internal_share(isSender ? share.value : null, threshold, receivers_list, senders_list, Zp, op_id); + + if (isReceiver) { + var promises = []; + for (var i = 0; i < senders_list.length; i++) { + var party_id = senders_list[i]; + promises.push(intermediate_shares[party_id].value); + } + + // Reconstruct share under new threshold + Promise.all(promises).then(function () { + var reconstruct_parts = []; + for (var i = 0; i < senders_list.length; i++) { + var party_id = senders_list[i]; + //shamir reconstruct takes an array of objects + //has attributes: {value: x, sender_id: y, Zp: jiff_instance.Zp} + reconstruct_parts[i] = {value: intermediate_shares[party_id].value, sender_id: party_id, Zp: Zp}; + } + var value = jiff.hooks.reconstructShare(jiff, reconstruct_parts); + final_deferred.resolve(value); + }); + } + }; + + if (isSender && !share.ready) { + share.value.then(ready_share); + } else { // either a receiver or share is ready + ready_share(); + } + + return result; }; },{}],42:[function(require,module,exports){ -module.exports = function (jiffClient, __internal_socket) { - __internal_socket.safe_emit = function (label, msg) { - if (label === 'free') { - jiffClient.hooks.execute_array_hooks('afterOperation', [this.jiffClient, 'free', msg], 2); - return; - } - - __internal_socket.emit(label, msg); - }; - - __internal_socket.resend_mailbox = function () {}; - - __internal_socket.disconnect = function () { - jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'disconnect', {}], -1); - }; - - __internal_socket.safe_disconnect = function (free, callback) { - if (free) { - jiffClient.free(); - } - jiffClient.socket.disconnect(); - if (callback != null) { - callback(); - } - }; - - return __internal_socket; -}; -},{}],43:[function(require,module,exports){ -var io = require('socket.io-client'); - -var linked_list = require('../../common/linkedlist.js'); -var constants = require('../util/constants.js'); - -var defaultSocketOptions = { - reconnectionDelay: constants.reconnectionDelay, - reconnectionDelayMax: constants.reconnectionDelayMax, - randomizationFactor: constants.randomizationFactor, - autoConnect: false -}; - -/** - * A guarded socket with an attached mailbox. - * - * The socket uses the mailbox to store all outgoing messages, and removes them from the mailbox only when - * the server acknowledges their receipt. The socket resends mailbox upon re-connection. Extends {@link https://socket.io/docs/client-api/#Socket}. - * @see {@link module:jiff-client~JIFFClient#socket} - * @name GuardedSocket - * @alias GuardedSocket - * @constructor - */ - -function guardedSocket(jiffClient) { - jiffClient.options.socketOptions = Object.assign({}, defaultSocketOptions, jiffClient.options.socketOptions); - - // Create plain socket io object which we will wrap in this - var socket = io(jiffClient.hostname, jiffClient.options.socketOptions); - socket.old_disconnect = socket.disconnect; - socket.mailbox = linked_list(); // for outgoing messages - socket.empty_deferred = null; // gets resolved whenever the mailbox is empty - socket.jiffClient = jiffClient; - - // add functionality to socket - socket.safe_emit = safe_emit.bind(socket); - socket.resend_mailbox = resend_mailbox.bind(socket); - socket.disconnect = disconnect.bind(socket); - socket.safe_disconnect = safe_disconnect.bind(socket); - socket.is_empty = is_empty.bind(socket); - - return socket; -} - -/** - * Safe emit: stores message in the mailbox until acknowledgment is received, results in socket.emit(label, msg) call(s) - * @method safe_emit - * @memberof GuardedSocket - * @instance - * @param {string} label - the label given to the message - * @param {string} msg - the message to send - */ -var safe_emit = function (label, msg) { - // add message to mailbox - var mailbox_pointer = this.mailbox.add({ label: label, msg: msg }); - if (this.connected) { - var self = this; - // emit the message, if an acknowledgment is received, remove it from mailbox - this.emit(label, msg, function (status) { - if (status) { - self.mailbox.remove(mailbox_pointer); - if (this.is_empty() && self.empty_deferred != null) { - self.empty_deferred.resolve(); - } - - if (label === 'free') { - this.jiffClient.hooks.execute_array_hooks('afterOperation', [this.jiffClient, 'free', msg], 2); - } - } - }); - } -}; - -/** - * Re-sends all pending messages - * @method resend_mailbox - * @memberof GuardedSocket - * @instance - */ -var resend_mailbox = function () { - // Create a new mailbox, since the current mailbox will be resent and - // will contain new backups. - var old_mailbox = this.mailbox; - this.mailbox = linked_list(); - - // loop over all stored messages and emit them - var current_node = old_mailbox.head; - while (current_node != null) { - var label = current_node.object.label; - var msg = current_node.object.msg; - this.safe_emit(label, msg); - current_node = current_node.next; - } +module.exports = { + /** + * Default way of computing shares (can be overridden using hooks). + * Compute the shares of the secret (as many shares as parties) using Shamir secret sharing + * @ignore + * @function jiff_compute_shares + * @param {module:jiff-client~JIFFClient} jiff - the jiff instance + * @param {number} secret - the secret to share. + * @param {Array} parties_list - array of party ids to share with. + * @param {number} threshold - the min number of parties needed to reconstruct the secret, defaults to all the receivers. + * @param {number} Zp - the mod. + * @returns {object} a map between party number and its share, this means that (party number, share) is a + * point from the polynomial. + * + */ + jiff_compute_shares: function (jiff, secret, parties_list, threshold, Zp) { + var shares = {}; // Keeps the shares + var i; + + // Each player's random polynomial f must have + // degree threshold - 1, so that threshold many points are needed + // to interpolate/reconstruct. + var t = threshold - 1; + var polynomial = Array(t + 1); // stores the coefficients + + // Each players's random polynomial f must be constructed + // such that f(0) = secret + polynomial[0] = secret; + + // Compute the random polynomial f's coefficients + for (i = 1; i <= t; i++) { + polynomial[i] = jiff.helpers.random(Zp); + } + + // Compute each players share such that share[i] = f(i) + for (i = 0; i < parties_list.length; i++) { + var p_id = parties_list[i]; + shares[p_id] = polynomial[0]; + var power = jiff.helpers.get_party_number(p_id); + + for (var j = 1; j < polynomial.length; j++) { + var tmp = jiff.helpers.mod((polynomial[j] * power), Zp); + shares[p_id] = jiff.helpers.mod((shares[p_id] + tmp), Zp); + power = jiff.helpers.mod(power * jiff.helpers.get_party_number(p_id), Zp); + } + } + + return shares; + }, + /** + * Share given secret to the participating parties. + * @ignore + * @function jiff_share + * @param {module:jiff-client~JIFFClient} jiff - the jiff instance + * @param {number} secret - the secret to share. + * @param {number} [threshold=receivers_list.length] - the min number of parties needed to reconstruct the secret, defaults to all the receivers. + * @param {Array} [receivers_list=all_parties] - array of party ids to share with, by default, this includes all parties. + * @param {Array} [senders_list=all_parties] - array of party ids to receive from, by default, this includes all parties. + * @param {number} [Zp=jiff.Zp] - the mod (if null then the default Zp for the instance is used). + * @param {string|number} [share_id=auto_gen()] - the tag used to tag the messages sent by this share operation, this tag is used + * so that parties distinguish messages belonging to this share operation from other + * share operations between the same parties (when the order of execution is not + * deterministic). An automatic id is generated by increasing a local counter, default + * ids suffice when all parties execute all sharing operations with the same senders + * and receivers in the same order. + * @returns {object} a map where the key is the sender party id + * and the value is the share object that wraps + * what was sent from that party (the internal value maybe deferred). + * if the party that calls this function is not a receiver then the map + * will be empty. + */ + jiff_share: function (jiff, secret, threshold, receivers_list, senders_list, Zp, share_id) { + var i, p_id; + + // defaults + if (Zp == null) { + Zp = jiff.Zp; + } + if (receivers_list == null) { + receivers_list = []; + for (i = 1; i <= jiff.party_count; i++) { + receivers_list.push(i); + } + } else { + jiff.helpers.sort_ids(receivers_list); + } + if (senders_list == null) { + senders_list = []; + for (i = 1; i <= jiff.party_count; i++) { + senders_list.push(i); + } + } else { + jiff.helpers.sort_ids(senders_list); + } + if (threshold == null) { + threshold = receivers_list.length; + } + if (threshold < 0) { + threshold = 2; + } + if (threshold > receivers_list.length) { + threshold = receivers_list.length; + } + + // if party is uninvolved in the share, do nothing + if (receivers_list.indexOf(jiff.id) === -1 && senders_list.indexOf(jiff.id) === -1) { + return {}; + } + + // compute operation id + if (share_id == null) { + share_id = jiff.counters.gen_op_id2('share', receivers_list, senders_list); + } + + // stage sending of shares + if (senders_list.indexOf(jiff.id) > -1) { + // Call hook + secret = jiff.hooks.execute_array_hooks('beforeShare', [jiff, secret, threshold, receivers_list, senders_list, Zp], 1); + + // compute shares + var shares = jiff.hooks.computeShares(jiff, secret, receivers_list, threshold, Zp); + + // Call hook + shares = jiff.hooks.execute_array_hooks('afterComputeShare', [jiff, shares, threshold, receivers_list, senders_list, Zp], 1); + + // send shares + for (i = 0; i < receivers_list.length; i++) { + p_id = receivers_list[i]; + if (p_id === jiff.id) { + continue; + } + + // send encrypted and signed shares_id[p_id] to party p_id + var msg = {party_id: p_id, share: shares[p_id], op_id: share_id}; + msg = jiff.hooks.execute_array_hooks('beforeOperation', [jiff, 'share', msg], 2); + + msg['share'] = jiff.hooks.encryptSign(jiff, msg['share'].toString(10), jiff.keymap[msg['party_id']], jiff.secret_key); + jiff.socket.safe_emit('share', JSON.stringify(msg)); + } + } + + // stage receiving of shares + var result = {}; + if (receivers_list.indexOf(jiff.id) > -1) { + // setup a map of deferred for every received share + if (jiff.deferreds[share_id] == null) { + jiff.deferreds[share_id] = {}; + } + + var _remaining = senders_list.length; + for (i = 0; i < senders_list.length; i++) { + p_id = senders_list[i]; + if (p_id === jiff.id) { // Keep party's own share + var my_share = jiff.hooks.execute_array_hooks('receiveShare', [jiff, p_id, shares[p_id]], 2); + result[p_id] = new jiff.SecretShare(my_share, receivers_list, threshold, Zp); + _remaining--; + continue; + } + + // check if a deferred is set up (maybe the message was previously received) + if (jiff.deferreds[share_id][p_id] == null) { // not ready, setup a deferred + jiff.deferreds[share_id][p_id] = new jiff.helpers.Deferred(); + } + + var promise = jiff.deferreds[share_id][p_id].promise; + // destroy deferred when done + (function (promise, p_id) { // p_id is modified in a for loop, must do this to avoid scoping issues. + promise.then(function () { + delete jiff.deferreds[share_id][p_id]; + _remaining--; + if (_remaining === 0) { + delete jiff.deferreds[share_id]; + } + }); + })(promise, p_id); + + // receive share_i[id] from party p_id + result[p_id] = new jiff.SecretShare(promise, receivers_list, threshold, Zp); + } + } + + return result; + } }; - -/** - * Wraps socket.io regular disconnect with a call to a hook before disconnection - * @method disconnect - * @memberof GuardedSocket - * @instance - */ -var disconnect = function () { - this.jiffClient.hooks.execute_array_hooks('beforeOperation', [this.jiffClient, 'disconnect', {}], -1); - this.old_disconnect.apply(this, arguments); +},{}],43:[function(require,module,exports){ +var genericProtocols = require('./protocols/generic.js'); +var arithmetic = require('./protocols/numbers/arithmetic.js'); +var comparison = require('./protocols/numbers/comparison.js'); +var protocols = require('./protocols/numbers/protocols.js'); +var booleans = require('./protocols/booleans/boolean.js'); +var gmw = require('./protocols/gmw_bit/gmw.js'); +// +// a metaclass that creates SecretShare classes when given a jiff instance +// alternatively, we can think of this as a factory for a secret share prototypes/constructors given a jiff instance +module.exports = function (jiff) { + // Look at jiff-client#SecretShare + function SecretShare(value, holders, threshold, Zp) { + // sort holders + jiff.helpers.sort_ids(holders); + + /** + * Indicates if the secret share's value is ready or still a promise + * @member {boolean} ready + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + this.ready = (value.then == null); + + /** + * The value of the share (or a promise to it) + * @member {number|promise} value + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + this.value = value; + + /** + * Array of party ids who hold shares of the corresponding secret + * @member {Array} holders + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + this.holders = holders; + /** + * The sharing threshold + * @member {number} threshold + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + this.threshold = threshold; + + /** + * The field prime under which the corresponding secret is shared + * @member {number} Zp + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + this.Zp = Zp; + + // when the promise is resolved, acquire the value of the share and set ready to true + if (!this.ready) { + this.value = this.value.then(this.promise_handler.bind(this), this.error.bind(this)); + this.jiff.add_to_barriers(this.value); + } + + // return the share + return jiff.hooks.execute_array_hooks('createSecretShare', [jiff, this], 1); + } + + /** + * The jiff client instance this share belongs to + * @member {module:jiff-client~JIFFClient} jiff + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.jiff = jiff; + + // Basic operations in prototype of SecretShare + /** + * Gets the value of this share + * @method valueOf + * @returns {number} the value (undefined if not ready yet) + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.valueOf = function () { + if (this.ready) { + return this.value; + } else { + return undefined; + } + }; + + /** + * Gets a string representation of this share + * @method toString + * @returns {string} the id and value of the share as a string + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + */ + SecretShare.prototype.toString = function () { + var val = this.ready ? this.value : ''; + return 'share: ' + val + '. Holders: ' + JSON.stringify(this.holders) + '. Threshold: ' + this.threshold + '. Zp: ' + this.Zp.toString() + '.'; + }; + + /** + * Logs an error. Passes the error on to the associated jiff client instance's {@link handlers.error} + * @method error + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {string|error} error - the error to log + */ + SecretShare.prototype.error = function (error) { + this.jiff.handlers.error('SecretShare', error); + }; + + /** + * Logs the value represented by this share to the console + * WARNING: THIS LEAKS INFORMATION AND MUST BE USED ONLY TO DEBUG ON FAKE DATA + * @method logLEAK + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {string} tag - accompanying tag to display in the console + * @param {Array} [parties=[holders[0]] - the parties which will display the log + * @param {string|number|object} [op_id=auto_gen()] - same as {@link module:jiff-client:JIFFClient#open} + * @return {?promise} a promise to the value represented by this share after logging it, null if party is not in parties + */ + SecretShare.prototype.logLEAK = function (tag, parties, op_id) { + if (parties == null) { + parties = [this.holders[0]]; + } + var promise = this.open(parties, tag, op_id); + if (promise != null) { + promise = promise.then(function (result) { + console.log(tag, result.toString()); + return result; + }, this.error); + } + return promise; + }; + + /** + * Handler for when this share's promise (if any) is resolved + * @method promise_handler + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {number} value - the value of the share after it was resolved + */ + SecretShare.prototype.promise_handler = function (value) { + this.value = value; + this.ready = true; + return this.value; + }; + + /** + * Executes callback when both this share and o are ready and returns the result (or a promise to the result) + * @method when_both_ready + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {SecretShare} o - the other share object. + * @param {function()} cb - the callback to execute. + * @returns {value|promise} either the return value of cb() or a promise to it + */ + SecretShare.prototype.when_both_ready = function (o, cb) { + if (this.ready && o.ready) { + return cb(); + } + + if (this.ready) { + return o.value.then(cb, this.error); + } else if (o.ready) { + return this.value.then(cb, this.error); + } else { + return Promise.all([this.value, o.value]).then(cb, this.error); + } + }; + + /** + * Shortcut for opening/revealing the value of this share. Alias for open in jiff-instance + * @see jiff-instance#open + * @method open + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {Array} [parties=all_parties] - an array with party ids (1 to n) of receiving parties + * @param {string|number|object} [op_id=auto_gen()] - same as {@link module:jiff-client:JIFFClient#open} + * @returns {?promise} a (JQuery) promise to the open value of the secret, null if the party is not specified in + * the parties array as a receiver + */ + SecretShare.prototype.open = function (parties, op_id) { + return this.jiff.open(this, parties, op_id); + }; + + /** + * Wrapper around share.value.then. + * In case share is ready (its promise is resolved and cleared) + * The callback is executed immediately. + * Does not support chaining + * @method wThen + * @memberof module:jiff-client~JIFFClient#SecretShare + * @instance + * @param {function} onFulfilled - callback for success, called with this.value as parameter + * @param {function} [onRejected=this.error] - callback for errors + * @return {promise|value} either the result of executing onFulfilled or a promise to it + */ + SecretShare.prototype.wThen = function (onFulfilled, onRejected) { + if (this.ready) { + return onFulfilled(this.value); + } else { + if (onRejected == null) { + onRejected = this.error; + } + return this.value.then(onFulfilled, onRejected); + } + }; + + // Complex protocols in prototype of SecretShare + genericProtocols(SecretShare); + arithmetic(SecretShare); + comparison(SecretShare); + protocols(SecretShare); + booleans(SecretShare); + gmw(SecretShare) + // + + // internal variant of primitives, to use internally by other primitives + var internals = ['cadd', 'csub', 'cmult', 'sadd', 'ssub', 'smult', 'smult_bgw', + 'cxor_bit', 'sxor_bit', 'cor_bit', 'sor_bit', + 'slt', 'slteq', 'sgt', 'sgteq', 'seq', 'sneq', + 'clt', 'clteq', 'cgt', 'cgteq', 'ceq', 'cneq', + 'sdiv', 'cdiv', 'not', 'cpow', 'lt_halfprime', 'if_else']; + for (var i = 0; i < internals.length; i++) { + var key = internals[i]; + SecretShare.prototype['i' + key] = SecretShare.prototype[key]; + } + + return SecretShare; +}; +},{"./protocols/booleans/boolean.js":26,"./protocols/generic.js":27,"./protocols/gmw_bit/gmw.js":29,"./protocols/numbers/arithmetic.js":32,"./protocols/numbers/comparison.js":33,"./protocols/numbers/protocols.js":34}],44:[function(require,module,exports){ +module.exports = { + '+': function (v1, v2) { + return v1 + v2; + }, + '-': function (v1, v2) { + return v1 - v2; + }, + '*': function (v1, v2) { + return v1 * v2; + }, + '/': function (v1, v2) { + return v1 / v2; + }, + '<': function (v1, v2) { + return v1 < v2; + }, + '<=': function (v1, v2) { + return v1 <= v2; + }, + 'floor': function (v) { + return Math.floor(v); + }, + 'ceil': function (v) { + return Math.ceil(v); + }, + 'floor/': function (v1, v2) { + return Math.floor(v1 / v2); + }, + 'pow': function (v1, v2) { + return Math.pow(v1, v2); + }, + 'binary': function (v) { + return v === 1 || v === 0; + }, + 'abs': function (v) { + return Math.abs(v); + }, + '==': function (v1, v2) { + return v1 === v2; + }, + 'even': function (v1) { + return (v1 % 2) === 0; + } }; - -/** - * Safe disconnect: disconnect only after all messages (including free) were acknowledged and - * all pending opens were resolved - * @method safe_disconnect - * @memberof GuardedSocket - * @instance - * @param {boolean} [free=false] - if true, a free message will be issued prior to disconnecting - * @param {function()} [callback] - given callback will be executed after safe disconnection is complete - */ -var safe_disconnect = function (free, callback) { - if (this.is_empty()) { - if (free) { - this.jiffClient.free(); - free = false; - } else { - this.disconnect(); - if (callback != null) { - callback(); - } - return; - } - } - - this.empty_deferred = new this.jiffClient.helpers.Deferred(); - this.empty_deferred.promise.then(this.safe_disconnect.bind(this, free, callback)); +},{}],45:[function(require,module,exports){ +module.exports = function (JIFFClient) { + /** + * Initialize socket listeners and events + * @memberof module:jiff-client.JIFFClient + * @method + */ + JIFFClient.prototype.initSocket = function () { + var jiffClient = this; + + // set on('connect') handler once! + this.socket.on('connect', jiffClient.handlers.connected); + + // Store the id when server sends it back + this.socket.on('initialization', jiffClient.handlers.initialized); + + // Public keys were updated on the server, and it sent us the updates + jiffClient.socket.on('public_keys', function (msg, callback) { + callback(true); + + msg = JSON.parse(msg); + msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'public_keys', msg], 2); + + jiffClient.handlers.store_public_keys(msg.public_keys); + }); + + // Setup receiving matching shares + this.socket.on('share', function (msg, callback) { + callback(true); // send ack to server + + // parse message + var json_msg = JSON.parse(msg); + var sender_id = json_msg['party_id']; + + if (jiffClient.keymap[sender_id] != null) { + jiffClient.handlers.receive_share(json_msg); + } else { + if (jiffClient.messagesWaitingKeys[sender_id] == null) { + jiffClient.messagesWaitingKeys[sender_id] = []; + } + jiffClient.messagesWaitingKeys[sender_id].push({label: 'share', msg: json_msg}); + } + }); + + this.socket.on('OT', function (msg, callback) { + callback(true); // send ack to server + // parse message + var json_msg = JSON.parse(msg); + var sender_id = json_msg['party_id']; + if (jiffClient.keymap[sender_id] != null) { + jiffClient.handlers.ot_receive(json_msg); + } else { + if (jiffClient.messagesWaitingKeys[sender_id] == null) { + jiffClient.messagesWaitingKeys[sender_id] = []; + } + jiffClient.messagesWaitingKeys[sender_id].push({label: 'OT', msg: json_msg}); + } + }); + + + // Setup receiving matching shares + this.socket.on('open', function (msg, callback) { + callback(true); // send ack to server + + // parse message + var json_msg = JSON.parse(msg); + var sender_id = json_msg['party_id']; + + if (jiffClient.keymap[sender_id] != null) { + jiffClient.handlers.receive_open(json_msg); + } else { + if (jiffClient.messagesWaitingKeys[sender_id] == null) { + jiffClient.messagesWaitingKeys[sender_id] = []; + } + jiffClient.messagesWaitingKeys[sender_id].push({label: 'open', msg: json_msg}); + } + }); + + // handle custom messages + this.socket.on('custom', function (msg, callback) { + callback(true); // send ack to server + var json_msg = JSON.parse(msg); + var sender_id = json_msg['party_id']; + var encrypted = json_msg['encrypted']; + + if (jiffClient.keymap[sender_id] != null || encrypted !== true) { + jiffClient.handlers.receive_custom(json_msg); + } else { + // key must not exist yet for sender_id, and encrypted must be true + if (jiffClient.messagesWaitingKeys[sender_id] == null) { + jiffClient.messagesWaitingKeys[sender_id] = []; + } + jiffClient.messagesWaitingKeys[sender_id].push({label: 'custom', msg: json_msg}); + } + }); + + this.socket.on('crypto_provider', function (msg, callback) { + callback(true); // send ack to server + jiffClient.handlers.receive_crypto_provider(JSON.parse(msg)); + }); + + this.socket.on('error', function (msg) { + try { + msg = JSON.parse(msg); + jiffClient.handlers.error(msg['label'], msg['error']); + } catch (error) { + jiffClient.handlers.error('socket.io', msg); + } + }); + + this.socket.on('disconnect', function (reason) { + if (reason !== 'io client disconnect') { + // check that the reason is an error and not a user initiated disconnect + console.log('Disconnected!', jiffClient.id, reason); + } + + jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'disconnect', reason], -1); + }); + }; + + /** + * Executes all callbacks for which the wait condition has been satisfied. + * Remove all executed callbacks so that they would not be executed in the future. + * @memberof module:jiff-client.JIFFClient + * @method + */ + JIFFClient.prototype.execute_wait_callbacks = function () { + var copy_callbacks = this.wait_callbacks; + this.wait_callbacks = []; + for (var i = 0; i < copy_callbacks.length; i++) { + var wait = copy_callbacks[i]; + var parties = wait.parties; + var callback = wait.callback; + var initialization = wait.initialization; + + // Check if the parties to wait for are now known + var parties_satisfied = this.__initialized || !initialization; + for (var j = 0; j < parties.length; j++) { + var party_id = parties[j]; + if (this.keymap == null || this.keymap[party_id] == null) { + parties_satisfied = false; + break; + } + } + + if (parties_satisfied) { + callback(this); + } else { + this.wait_callbacks.push(wait); + } + } + }; + + /** + * Resolves all messages that were pending because their senders primary key was previously unknown. + * These messages are decrypted and verified and handled appropriatly before being removed from the wait queue. + * @memberof module:jiff-client.JIFFClient + * @method + */ + JIFFClient.prototype.resolve_messages_waiting_for_keys = function () { + for (var party_id in this.keymap) { + if (!this.keymap.hasOwnProperty(party_id)) { + continue; + } + + var messageQueue = this.messagesWaitingKeys[party_id]; + if (messageQueue == null) { + continue; + } + for (var i = 0; i < messageQueue.length; i++) { + var msg = messageQueue[i]; + if (msg.label === 'share') { + this.handlers.receive_share(msg.msg); + } else if (msg.label === 'open') { + this.handlers.receive_open(msg.msg); + } else if (msg.label === 'custom') { + this.handlers.receive_custom(msg.msg); + } else { + throw new Error('Error resolving pending message: unknown label ' + msg.label); + } + } + + this.messagesWaitingKeys[party_id] = null; + } + }; }; - -/** - * Checks if the socket mailbox is empty (all communication was done and acknowledged), - * used in safe_disconnect - * @method is_empty - * @memberof GuardedSocket - * @instance - */ -var is_empty = function () { - return this.mailbox.head == null && this.jiffClient.counters.pending_opens === 0; +},{}],46:[function(require,module,exports){ +module.exports = function (jiffClient, __internal_socket) { + __internal_socket.safe_emit = function (label, msg) { + if (label === 'free') { + jiffClient.hooks.execute_array_hooks('afterOperation', [this.jiffClient, 'free', msg], 2); + return; + } + + __internal_socket.emit(label, msg); + }; + + __internal_socket.resend_mailbox = function () {}; + + __internal_socket.disconnect = function () { + jiffClient.hooks.execute_array_hooks('beforeOperation', [jiffClient, 'disconnect', {}], -1); + }; + + __internal_socket.safe_disconnect = function (free, callback) { + if (free) { + jiffClient.free(); + } + jiffClient.socket.disconnect(); + if (callback != null) { + callback(); + } + }; + + return __internal_socket; }; - +},{}],47:[function(require,module,exports){ +var io = require('socket.io-client'); + +var linked_list = require('../../common/linkedlist.js'); +var constants = require('../util/constants.js'); + +var defaultSocketOptions = { + reconnectionDelay: constants.reconnectionDelay, + reconnectionDelayMax: constants.reconnectionDelayMax, + randomizationFactor: constants.randomizationFactor, + autoConnect: false +}; + +/** + * A guarded socket with an attached mailbox. + * + * The socket uses the mailbox to store all outgoing messages, and removes them from the mailbox only when + * the server acknowledges their receipt. The socket resends mailbox upon re-connection. Extends {@link https://socket.io/docs/client-api/#Socket}. + * @see {@link module:jiff-client~JIFFClient#socket} + * @name GuardedSocket + * @alias GuardedSocket + * @constructor + */ + +function guardedSocket(jiffClient) { + jiffClient.options.socketOptions = Object.assign({}, defaultSocketOptions, jiffClient.options.socketOptions); + + // Create plain socket io object which we will wrap in this + var socket = io(jiffClient.hostname, jiffClient.options.socketOptions); + socket.old_disconnect = socket.disconnect; + socket.mailbox = linked_list(); // for outgoing messages + socket.empty_deferred = null; // gets resolved whenever the mailbox is empty + socket.jiffClient = jiffClient; + + // add functionality to socket + socket.safe_emit = safe_emit.bind(socket); + socket.resend_mailbox = resend_mailbox.bind(socket); + socket.disconnect = disconnect.bind(socket); + socket.safe_disconnect = safe_disconnect.bind(socket); + socket.is_empty = is_empty.bind(socket); + + return socket; +} + +/** + * Safe emit: stores message in the mailbox until acknowledgment is received, results in socket.emit(label, msg) call(s) + * @method safe_emit + * @memberof GuardedSocket + * @instance + * @param {string} label - the label given to the message + * @param {string} msg - the message to send + */ +var safe_emit = function (label, msg) { + // add message to mailbox + var mailbox_pointer = this.mailbox.add({ label: label, msg: msg }); + if (this.connected) { + var self = this; + // emit the message, if an acknowledgment is received, remove it from mailbox + this.emit(label, msg, function (status) { + if (status) { + self.mailbox.remove(mailbox_pointer); + if (this.is_empty() && self.empty_deferred != null) { + self.empty_deferred.resolve(); + } + + if (label === 'free') { + this.jiffClient.hooks.execute_array_hooks('afterOperation', [this.jiffClient, 'free', msg], 2); + } + } + }); + } +}; + +/** + * Re-sends all pending messages + * @method resend_mailbox + * @memberof GuardedSocket + * @instance + */ +var resend_mailbox = function () { + // Create a new mailbox, since the current mailbox will be resent and + // will contain new backups. + var old_mailbox = this.mailbox; + this.mailbox = linked_list(); + + // loop over all stored messages and emit them + var current_node = old_mailbox.head; + while (current_node != null) { + var label = current_node.object.label; + var msg = current_node.object.msg; + this.safe_emit(label, msg); + current_node = current_node.next; + } +}; + +/** + * Wraps socket.io regular disconnect with a call to a hook before disconnection + * @method disconnect + * @memberof GuardedSocket + * @instance + */ +var disconnect = function () { + this.jiffClient.hooks.execute_array_hooks('beforeOperation', [this.jiffClient, 'disconnect', {}], -1); + this.old_disconnect.apply(this, arguments); +}; + +/** + * Safe disconnect: disconnect only after all messages (including free) were acknowledged and + * all pending opens were resolved + * @method safe_disconnect + * @memberof GuardedSocket + * @instance + * @param {boolean} [free=false] - if true, a free message will be issued prior to disconnecting + * @param {function()} [callback] - given callback will be executed after safe disconnection is complete + */ +var safe_disconnect = function (free, callback) { + if (this.is_empty()) { + if (free) { + this.jiffClient.free(); + free = false; + } else { + this.disconnect(); + if (callback != null) { + callback(); + } + return; + } + } + + this.empty_deferred = new this.jiffClient.helpers.Deferred(); + this.empty_deferred.promise.then(this.safe_disconnect.bind(this, free, callback)); +}; + +/** + * Checks if the socket mailbox is empty (all communication was done and acknowledged), + * used in safe_disconnect + * @method is_empty + * @memberof GuardedSocket + * @instance + */ +var is_empty = function () { + return this.mailbox.head == null && this.jiffClient.counters.pending_opens === 0; +}; + module.exports = guardedSocket; -},{"../../common/linkedlist.js":49,"../util/constants.js":44,"socket.io-client":231}],44:[function(require,module,exports){ -module.exports = { - /** - * The default mod to be used in a jiff instance if a custom mod was not provided. - */ - gZp: 16777729, - - /** - * Socket connection timeouts - */ - reconnectionDelay: 25000, - reconnectionDelayMax: 27500, - randomizationFactor: 0.1, - - /** - * Maximum numbers of retries on failed initialization. - */ - maxInitializationRetries: 2 +},{"../../common/linkedlist.js":53,"../util/constants.js":48,"socket.io-client":286}],48:[function(require,module,exports){ +module.exports = { + /** + * The default mod to be used in a jiff instance if a custom mod was not provided. + */ + gZp: 16777729, + + /** + * Socket connection timeouts + */ + reconnectionDelay: 25000, + reconnectionDelayMax: 27500, + randomizationFactor: 0.1, + + /** + * Maximum numbers of retries on failed initialization. + */ + maxInitializationRetries: 2 }; -},{}],45:[function(require,module,exports){ -/** - * Encrypts and signs the given message. - * @ignore - * @memberof jiff.utils - * @param {number|string} message - the message to encrypt. - * @param {Uint8Array} encryption_public_key - ascii-armored public key to encrypt with. - * @param {Uint8Array} signing_private_key - the private key of the encrypting party to sign with. - * @returns {object} the signed cipher, includes two properties: 'cipher' and 'nonce'. - */ -exports.encrypt_and_sign = function (jiff, message, encryption_public_key, signing_private_key) { - var nonce = jiff.sodium_.randombytes_buf(jiff.sodium_.crypto_box_NONCEBYTES); - var cipher = jiff.sodium_.crypto_box_easy(message, nonce, encryption_public_key, signing_private_key); - - var result = { nonce: '[' + nonce.toString() + ']', cipher: '[' + cipher.toString() + ']' }; - return result; +},{}],49:[function(require,module,exports){ +/** + * Encrypts and signs the given message. + * @ignore + * @memberof jiff.utils + * @param {number|string} message - the message to encrypt. + * @param {Uint8Array} encryption_public_key - ascii-armored public key to encrypt with. + * @param {Uint8Array} signing_private_key - the private key of the encrypting party to sign with. + * @returns {object} the signed cipher, includes two properties: 'cipher' and 'nonce'. + */ +exports.encrypt_and_sign = function (jiff, message, encryption_public_key, signing_private_key) { + var nonce = jiff.sodium_.randombytes_buf(jiff.sodium_.crypto_box_NONCEBYTES); + var cipher = jiff.sodium_.crypto_box_easy(message, nonce, encryption_public_key, signing_private_key); + + var result = { nonce: '[' + nonce.toString() + ']', cipher: '[' + cipher.toString() + ']' }; + return result; +}; + +/** + * Decrypts and checks the signature of the given cipher text. + * @ignore + * @memberof jiff.utils + * @param {object} cipher_text - the cipher text to decrypt, includes two properties: 'cipher' and 'nonce'. + * @param {Uint8Array} decryption_secret_key - the secret key to decrypt with. + * @param {Uint8Array} signing_public_key - ascii-armored public key to verify against signature. + * @returns {number|string} the decrypted message if the signature was correct, the decrypted message type should + * the type of operation, such that the returned value has the appropriate type and does + * not need any type modifications. + * @throws error if signature or nonce was forged/incorrect. + */ +exports.decrypt_and_sign = function (jiff, cipher_text, decryption_secret_key, signing_public_key) { + var nonce = new Uint8Array(JSON.parse(cipher_text.nonce)); + cipher_text = new Uint8Array(JSON.parse(cipher_text.cipher)); + + try { + return jiff.sodium_.crypto_box_open_easy(cipher_text, nonce, signing_public_key, decryption_secret_key, 'text'); + } catch (_) { + throw new Error('Bad signature or Bad nonce: Cipher: ' + cipher_text + '. DecSKey: ' + decryption_secret_key + '. SignPKey: ' + signing_public_key); + } +}; +},{}],50:[function(require,module,exports){ +var helpers = require('../../common/helpers.js'); + +/** + * Contains helper functions: these may be overriden by extensions to customize behavior + * @see {@link module:jiff-client~JIFFClient#helpers} + * @name helpers + * @alias helpers + * @namespace + */ + +module.exports = function (jiffClient) { + /** + * Polyfill for jQuery Deferred + * From https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred + * @memberof helpers + * @constructor Deferred + */ + jiffClient.helpers.Deferred = function () { + /** + * A method to resolve the associate Promise with the value passed. + * @method resolve + * @memberof helpers.Deferred + * @instance + * @param {*} value - the value to resolve the promise with + */ + this.resolve = null; + + /** + * A method to reject the associated Promise with the value passed. + * If the promise is already settled it does nothing. + * @method reject + * @memberof helpers.Deferred + * @instance + * @param {*} reason - The reason for the rejection of the Promise. + * Generally its an Error object. If however a Promise is passed, then the Promise + * itself will be the reason for rejection no matter the state of the Promise. + */ + this.reject = null; + + /** + * A newly created Promise object. + * Initially in pending state. + * @memberof helpers.Deferred + * @member {Promise} promise + * @instance + */ + this.promise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }.bind(this)); + + Object.freeze(this); + }; + + /** + * Correct Mod instead of javascript's remainder (%). + * @memberof helpers + * @method + * @param {number} x - the number. + * @param {number} y - the mod. + * @return {number} x mod y. + */ + jiffClient.helpers.mod = helpers.mod; + + /** + * Ceil of a number. + * @memberof helpers + * @method + * @param {number} x - the number to ceil. + * @return {number} ceil of x. + */ + jiffClient.helpers.ceil = Math.ceil; + + /** + * Floor of a number + * @memberof helpers + * @method + * @param {number} x - the number to floor. + * @return {number} floor of x. + */ + jiffClient.helpers.floor = Math.floor; + + /** + * Fast Exponentiation Mod + * @memberof helpers + * @method + * @param {number} a - the base number + * @param {number} b - the power + * @param {number} n - the mod + * @return {number} (base^pow) mod m + */ + jiffClient.helpers.pow_mod = function (a, b, n) { + a = jiffClient.helpers.mod(a, n); + var result = 1; + var x = a; + while (b > 0) { + var leastSignificantBit = jiffClient.helpers.mod(b, 2); + b = Math.floor(b / 2); + if (leastSignificantBit === 1) { + result = result * x; + result = jiffClient.helpers.mod(result, n); + } + x = x * x; + x = jiffClient.helpers.mod(x, n); + } + return result; + }; + + /** + * Extended Euclidean for finding inverses. + * @method + * @memberof helpers + * @param {number} a - the number to find inverse for. + * @param {number} b - the mod. + * @return {number[]} [inverse of a mod b, coefficient for a, coefficient for b]. + */ + jiffClient.helpers.extended_gcd = function (a, b) { + if (b === 0) { + return [1, 0, a]; + } + + var temp = jiffClient.helpers.extended_gcd(b, jiffClient.helpers.mod(a, b)); + var x = temp[0]; + var y = temp[1]; + var d = temp[2]; + return [y, x - y * Math.floor(a / b), d]; + }; + + /** + * Compute Log to a given base. + * @method + * @memberof helpers + * @param {number} value - the number to find log for. + * @param {number} [base=2] - the base (2 by default). + * @return {number} log(value) with the given base. + */ + jiffClient.helpers.bLog = function (value, base) { + if (base == null) { + base = 2; + } + return Math.log(value) / Math.log(base); + }; + + /** + * Check that two sorted arrays are equal. + * @method + * @memberof helpers + * @param {Array} arr1 - the first array. + * @param {Array} arr2 - the second array. + * @return {boolean} true if arr1 is equal to arr2, false otherwise. + */ + jiffClient.helpers.array_equals = function (arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + + for (var i = 0; i < arr1.length; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + + return true; + }; + + /** + * Check that two Zps are equal. Used to determine if shares can be computed on or not. + * @method + * @memberof helpers + * @param {SecretShare} s1 - the first share. + * @param {SecretShare} s2 - the second share. + * @return {boolean} true both shares have the same Zp, false otherwise. + */ + jiffClient.helpers.Zp_equals = function (s1, s2) { + return s1.Zp === s2.Zp; + }; + + /** + * Generate a random integer between 0 and max-1 [inclusive]. + * Modify this to change the source of randomness and how it is generated. + * @method + * @memberof helpers + * @param {number} max - the maximum number. + * @return {number} the random number. + */ + jiffClient.helpers.random = helpers.random; + + /** + * Get the party number from the given party_id, the number is used to compute/open shares. + * If party id was a number (regular party), that number is returned, + * If party id refers to the ith server, then party_count + i is returned (i > 0). + * @method + * @memberof helpers + * @param {number|string} party_id - the party id from which to compute the number. + * @return {number} the party number (> 0). + */ + jiffClient.helpers.get_party_number = helpers.get_party_number; + + /** + * Transforms the given number to an array of bits (numbers). + * Lower indices in the returned array corresponding to less significant bits. + * @memberof helpers + * @method + * @param {number} number - the number to transform to binary + * @param {length} [length=ceil(log2(number))] - if provided, then the given array will be padded with zeros to the length. + * @return {number[]} the array of bits. + */ + jiffClient.helpers.number_to_bits = helpers.number_to_bits; + + /** + * Transforms the given array of bits to a number. + * @memberof helpers + * @method + * @param {number[]} bits - the array of bits to compose as a number, starting from least to most significant bits. + * @param {number} [length = bits.length] - if provided, only the first 'length' bits will be used + * @return {number} the array of bits. + */ + jiffClient.helpers.bits_to_number = function (bits, length) { + if (length == null || length > bits.length) { + length = bits.length; + } + return parseInt(bits.slice(0, length).reverse().join(''), 2); + }; + + /** + * Checks if the given number is prime using AKS primality test + * @method + * @memberof helpers + * @param {number} p - the number to check + * @return {boolean} true if p is prime, false otherwise + */ + jiffClient.helpers.is_prime = function (p) { + // AKS Primality Test + + if (p === 2) { + return true; + } else if (p === 3) { + return true; + } else if (p % 2 === 0) { + return false; + } else if (p % 3 === 0) { + return false; + } + + var i = 5; + var n = 2; + while (i * i <= p) { + if (p % i === 0) { + return false; + } + i += n; + n = 6 - n; + } + + return true; + }; + + /** + * sorts an array of ids (in place) according to a consistent ordering + * @method + * @memberof helpers + * @param {array} ids - array of ids containing numbers or "s1" + */ + jiffClient.helpers.sort_ids = function (ids) { + if (ids.__jiff_sorted) { + return; + } + + ids.sort(function (e1, e2) { + if (e1 === e2) { + throw new Error('ids array has duplicated: ' + ids.toString()); + } + if (e1 === 's1') { + return 1; + } + if (e2 === 's1') { + return -1; + } + return e1 - e2; + }); + ids.__jiff_sorted = true; + } +}; +},{"../../common/helpers.js":52}],51:[function(require,module,exports){ +/** + * Contains utility functions (higher order combinators) + * @see {@link module:jiff-client~JIFFClient#utils} + * @name utils + * @alias utils + * @namespace + */ + +module.exports = function (jiffClient) { + /** + * Create an array of secret shares and associated deferred. + * @method + * @memberof utils + * @param {number} count - number of secret shares + * @param {Array} holders - the parties that hold all the corresponding shares (must be sorted) + * @param {number} threshold - the min number of parties needed to reconstruct the secret + * @param {number} Zp - the mod under which this share was created + * @return {object} the secret share object containing the give value + * + */ + jiffClient.utils.many_secret_shares = function (count, holders, threshold, Zp) { + var deferreds = []; + var shares = []; + for (var i = 0; i < count; i++) { + var deferred = new jiffClient.helpers.Deferred(); + shares.push(new jiffClient.SecretShare(deferred.promise, holders, threshold, Zp)); + deferreds.push(deferred); + } + + return {shares: shares, deferreds: deferreds}; + }; + + /** + * Resolve the array of deferreds with the values of the given shares when ready, matched by index + * @method + * @memberof utils + * @param {Deferred[]} deferreds - the deferred to resolve + * @param {SecretShare[]} shares - the shares to resolve with + */ + jiffClient.utils.resolve_many_secrets = function (deferreds, shares) { + for (var i = 0; i < deferreds.length; i++) { + shares[i].wThen(deferreds[i].resolve); + } + }; + + /** + * Combines all the promises of the given share into a single promise that is resolved when + * all shares are resolved + * @method + * @methodof utils + * @param {SecretShare[]} shares - the shares whose promises should be joined + */ + jiffClient.utils.all_promises = function (shares) { + var promises = []; + for (var i = 0; i < shares.length; i++) { + promises.push(shares[i].value); + } + return Promise.all(promises); + }; + + /** + * A high level combinator for iteration of bit arrays + * It executes a round of (func) starting from index start to the length (supports backwards if start > length) excluding length + * Every round is blocked until the previous one finishes and the promise produced by it + * is resolved + * The final value is used to resolve deferred + * @method + * @memberof utils + * @param {!Deferred} deferred - the deferred to resolve with the final output + * @param {!number} start - the index to start from + * @param {!number} length - the index to stop at (excluding it) + * @param {?object} initial - an initial aggregator value + * @param {!function(number, object)} func - the aggregator function to apply to the elements in order, takes the index and the aggregator value so far + * @param {?function(object)} [promisify] - if initial is not null, this is called prior to starting combinator, to turn initial + * into a promise of the actually used initial value(in case it has to be resolved), + * defaults to promisifying a SecretShare with .wThen + * @param {?function(object)} [valufy] - applied to the final result to turn it into a value, which is then used to resolve deferred, + * defaults to getting value of a SecretShare + */ + jiffClient.utils.bit_combinator = function (deferred, start, length, initial, func, promisify, valufy) { + if (promisify == null) { + promisify = function (share) { + return {then: share.wThen.bind(share)}; + } + } + + if (valufy == null) { + valufy = function (share) { + return share.value; + } + } + + var next = start <= length ? 1 : -1; + var __bit_combinator = function (start, val) { + if (start === length) { + // done + deferred.resolve(valufy(val)); + return; + } + + // execute func once + val = func(start, val); + + // when done, do next iteration + promisify(val).then(function () { + __bit_combinator(start + next, val); + }); + }; + + // start combinator + if (initial == null) { + __bit_combinator(start, initial); + } else { + promisify(initial).then(function () { + __bit_combinator(start, initial); + }); + } + } }; +},{}],52:[function(require,module,exports){ +var crypto_; +if (typeof(window) === 'undefined') { + crypto_ = require('crypto'); + crypto_.__randomBytesWrapper = crypto_.randomBytes; +} else { + crypto_ = window.crypto || window.msCrypto; + crypto_.__randomBytesWrapper = function (bytesNeeded) { + var randomBytes = new Uint8Array(bytesNeeded); + crypto_.getRandomValues(randomBytes); + return randomBytes; + }; +} + +// Secure randomness via rejection sampling. +exports.random = function (max) { + // Use rejection sampling to get random value within bounds + // Generate random Uint8 values of 1 byte larger than the max parameter + // Reject if random is larger than quotient * max (remainder would cause biased distribution), then try again + + // Values up to 2^53 should be supported, but log2(2^49) === log2(2^49+1), so we lack the precision to easily + // determine how many bytes are required + if (max > 562949953421312) { + throw new RangeError('Max value should be smaller than or equal to 2^49'); + } + + var bitsNeeded = Math.ceil(Math.log(max)/Math.log(2)); + var bytesNeeded = Math.ceil(bitsNeeded / 8); + var maxValue = Math.pow(256, bytesNeeded); + + // Keep trying until we find a random value within bounds + while (true) { // eslint-disable-line + var randomBytes = crypto_.__randomBytesWrapper(bytesNeeded); + var randomValue = 0; + + for (var i = 0; i < bytesNeeded; i++) { + randomValue = randomValue * 256 + (randomBytes.readUInt8 ? randomBytes.readUInt8(i) : randomBytes[i]); + } + + // randomValue should be smaller than largest multiple of max within maxBytes + if (randomValue < maxValue - maxValue % max) { + return randomValue % max; + } + } +}; + +// actual mode +exports.mod = function (x, y) { + if (x < 0) { + return (x % y) + y; + } + return x % y; +}; + +// get the party number from the given party_id, the number is used to compute/open shares +exports.get_party_number = function (party_id) { + if (typeof(party_id) === 'number') { + return party_id; + } + if (party_id.startsWith('s')) { + return -1 * parseInt(party_id.substring(1), 10); + } + return parseInt(party_id, 10); +}; + +// transform number to bit array +exports.number_to_bits = function (number, length) { + number = number.toString(2); + var bits = []; + for (var i = 0; i < number.length; i++) { + bits[i] = parseInt(number.charAt(number.length - 1 - i)); + } + while (length != null && bits.length < length) { + bits.push(0); + } + return bits; +}; +},{"crypto":141}],53:[function(require,module,exports){ +/** Doubly linked list with add and remove functions and pointers to head and tail**/ +module.exports = function () { + // attributes: list.head and list.tail + // functions: list.add(object) (returns pointer), list.remove(pointer) + // list.head/list.tail/any element contains: + // next: pointer to next, + // previous: pointer to previous, + // object: stored object. + var list = {head: null, tail: null}; + // TODO rename this to pushTail || push + list.add = function (obj) { + var node = { object: obj, next: null, previous: null }; + if (list.head == null) { + list.head = node; + list.tail = node; + } else { + list.tail.next = node; + node.previous = list.tail; + list.tail = node; + } + return node; + }; + + list.pushHead = function (obj) { + list.head = {object: obj, next : list.head, previous : null}; + if (list.head.next != null) { + list.head.next.previous = list.head; + } else { + list.tail = list.head; + } + }; + + list.popHead = function () { + var result = list.head; + if (list.head != null) { + list.head = list.head.next; + if (list.head == null) { + list.tail = null; + } else { + list.head.previous = null; + } + } + return result; + }; + + // merges two linked lists and return a pointer to the head of the merged list + // the head will be the head of list and the tail the tail of l2 + list.extend = function (l2) { + if (list.head == null) { + return l2; + } + if (l2.head == null) { + return list; + } + list.tail.next = l2.head; + l2.head.previous = list.tail; + list.tail = l2.tail; + + return list; + }; + + list.remove = function (ptr) { + var prev = ptr.previous; + var next = ptr.next; + + if (prev == null && list.head !== ptr) { + return; + } else if (next == null && list.tail !== ptr) { + return; + } + + if (prev == null) { // ptr is head (or both head and tail) + list.head = next; + if (list.head != null) { + list.head.previous = null; + } else { + list.tail = null; + } + } else if (next == null) { // ptr is tail (and not head) + list.tail = prev; + prev.next = null; + } else { // ptr is inside + prev.next = next; + next.previous = prev; + } + }; + list.slice = function (ptr) { // remove all elements from head to ptr (including ptr). + if (ptr == null) { + return; + } + + /* CONSERVATIVE: make sure ptr is part of the list then remove */ + var current = list.head; + while (current != null) { + if (current === ptr) { + list.head = ptr.next; + if (list.head == null) { + list.tail = null; + } + + return; + } + current = current.next; + } + + /* MORE AGGRESSIVE VERSION: will be incorrect if ptr is not in the list */ + /* + list.head = ptr.next; + if (list.head == null) { + list.tail = null; + } + */ + }; + /* + list._debug_length = function () { + var l = 0; + var current = list.head; + while (current != null) { + current = current.next; + l++; + } + return l; + }; + */ + return list; +}; -/** - * Decrypts and checks the signature of the given cipher text. - * @ignore - * @memberof jiff.utils - * @param {object} cipher_text - the cipher text to decrypt, includes two properties: 'cipher' and 'nonce'. - * @param {Uint8Array} decryption_secret_key - the secret key to decrypt with. - * @param {Uint8Array} signing_public_key - ascii-armored public key to verify against signature. - * @returns {number|string} the decrypted message if the signature was correct, the decrypted message type should - * the type of operation, such that the returned value has the appropriate type and does - * not need any type modifications. - * @throws error if signature or nonce was forged/incorrect. - */ -exports.decrypt_and_sign = function (jiff, cipher_text, decryption_secret_key, signing_public_key) { - var nonce = new Uint8Array(JSON.parse(cipher_text.nonce)); - cipher_text = new Uint8Array(JSON.parse(cipher_text.cipher)); +},{}],54:[function(require,module,exports){ +/** + * JIFF Client. + * + * Exposes the constructor for the {@link module:jiff-client~JIFFClient} class. + * + * In the browser, this adds `JIFFClient` as a global identifier. + * + * In the browser, this can be accessed via: + *

+ *   <script src="jiff-client.js"></script>
+ *   <script type="text/javascript">
+ *     var jiffClientInstance = new JIFFClient(hostname, computationId, options);
+ *   </script>
+ * 
+ * + * In node.js, this can be accessed via: + *

+ *   const JIFFClient = require('jiffClient');
+ *   const jiffClientInstance = new JIFFClient(hostname, computationId, options);
+ *
+ * 
+ * + * @module jiff-client + * @alias jiff-client + */ + +// browserify bundles this into our code bundle +var sodium = require('libsodium-wrappers'); + +// utils and helpers +var constants = require('./client/util/constants.js'); +var helpers = require('./client/util/helpers.js'); +var utils = require('./client/util/utils.js'); +var linkedList = require('./common/linkedlist.js'); + +// hooks +var Hooks = require('./client/arch/hooks.js'); + +// extensions management +var extensions = require('./client/arch/extensions.js'); + +// op ids and other counters +var counters = require('./client/arch/counters.js'); + +// socket and events +var guardedSocket = require('./client/socket/mailbox.js'); +var internalSocket = require('./client/socket/internal.js'); +var socketEvents = require('./client/socket/events.js'); + +// handlers for communication +var handlers = require('./client/handlers.js'); + +// secret shares +var SecretShareMetaClass = require('./client/share.js'); +var share_helpers = require('./client/shareHelpers.js'); + +// jiff client instance API +var api = require('./client/api.js'); + +// preprocessing +var preprocessingMap = require('./client/preprocessing/map.js'); +var preprocessingAPI = require('./client/preprocessing/api.js'); +var preprocessingDaemon = require('./client/preprocessing/daemon.js'); +// used for gmw bit computation( OT lib) +let IO = require('./client/protocols/gmw_bit/IO.js'); +let OT = require('1-out-of-n')(IO); +/** + * Creates a new jiff client instance. + * @class + * @name JIFFClient + * @param {!string} hostname - server hostname/ip and port. + * @param {!string} computation_id - the id of the computation of this instance. + * @param {?object} [options={}] - javascript object with additional options. + * all parameters are optional, However, private and public key must either be both provided or neither of them provided. +
+ {
+   "party_id": number,
+   "party_count": number,
+   "secret_key": Uint8Array to be used with libsodium-wrappers [(check Library Specs)]{@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html},
+   "public_key": Uint8Array to be used with libsodium-wrappers [(check Library Specs)]{@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html},
+   "public_keys": { 1: "Uint8Array PublicKey", 2: "Uint8Array PublicKey", ... },
+   "Zp": default mod to use (prime number),
+   "autoConnect": true/false,
+   "hooks": { 'check out hooks documentation' },
+   "listeners" : A map from custom tags to listeners (of type function(sender_id, message_string)) that handle custom messages with that tag.
+   "onConnect": function(jiff_instance),
+   "onError": function(label, error): called when errors occured in client code or during handling requests from this client at the server side
+                                      label is a string indicating where the error occured, and error is a string or an exception object.
+   "safemod": boolean (whether or not to check if provided Zp is prime, may be slow for big primes, defaults to false),
+   "crypto_provider": a boolean that flags whether to get beaver triplets and other preprocessing entities from the server (defaults to false),
+   "socketOptions": an object, passed directly to socket.io constructor,
+   "sodium": boolean, if false messages between clients will not be encrypted (useful for debugging),
+   "maxInitializationRetries": how many consecutive times to retry to initialize with the server if initialization fails, defaults to 2,
+   "preprocessingBatchSize": how many base level preprocessing tasks to execute in parallel.
+ }
+ 
+ * + * @example + * var JIFFClient = require('jiffClient'); // only for node.js + * // for the browser + * // build a jiff instance which will connect to a server running on the local machine + * var instance = new JIFFClient('http://localhost:8080', 'computation-1', {party_count: 2}); + */ + + + +function JIFFClient(hostname, computation_id, options) { + var jiffClient = this; + options = Object.assign({}, options); + /** + * The server hostname, ends with a slash, includes port and protocol (http/https). + * @type {!string} + */ + this.hostname = hostname.trim(); + if (!this.hostname.endsWith('/')) { + this.hostname = this.hostname + '/'; + } + + /** + * Stores the computation id. + * @type {!string} + */ + this.computation_id = computation_id; + + /** + * Private. Do not use directly externally; use isReady() instead. + * @type {!boolean} + * @see {@link module:jiff-client~JIFFClient#isReady} + */ + this.__ready = false; + + /** + * Private. Do not use directly externally; use isInitialized() instead. + * @type {!boolean} + * @see {@link module:jiff-client~JIFFClient#isInitialized} + */ + this.__initialized = false; + + /** + * Returns whether this instance is capable of starting the computation. + * In other words, the public keys for all parties and servers are known, + * and this party successfully initialized with the server. + * @returns {!boolean} + */ + this.isReady = function () { + return this.__ready; + }; + + /** + * Returns whether this instance initialized successfully with the server. + * Note that this can be true even when isReady() returns false, in case where some other parties have not + * initialized yet! + * @returns {!boolean} + */ + this.isInitialized = function () { + return this.__initialized; + }; + + /** + * Helper functions [DO NOT MODIFY UNLESS YOU KNOW WHAT YOU ARE DOING]. + * @type {!helpers} + */ + this.helpers = {}; + helpers(this); + + /** + * Shallow copy of the options passed to the constructor. + * @type {!Object} + */ + this.options = options; + + // Parse and verify options + options.maxInitializationRetries = options.maxInitializationRetries || constants.maxInitializationRetries; + if (typeof(options.Zp) === 'number' && options.safemod !== false) { // big numbers are checked by extension + if (!this.helpers.is_prime(options.Zp)) { + throw new Error('Zp = ' + options.Zp + ' is not prime. Please use a prime number for the modulus or set safemod to false.'); + } + } + + /** + * The default Zp for this instance. + * @type {!number} + */ + this.Zp = options.Zp || constants.gZp; + + /** + * The id of this party. + * @type {number} + */ + this.id = options.party_id; + + /** + * Total party count in the computation, parties will take ids between 1 to party_count (inclusive). + * @type {number} + */ + this.party_count = options.party_count; + + /** + * sodium wrappers either imported via require (if in nodejs) or from the bundle (in the browser). + * This will be false if options.sodium is false. + * @see {@link https://www.npmjs.com/package/libsodium-wrappers} + * @type {?sodium} + */ + this.sodium_ = options.sodium !== false ? sodium : false; + + /** + * A map from party id to public key. Where key is the party id (number), and + * value is the public key, which by default follows libsodium's specs (Uint8Array). + * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} + * @type {!object} + */ + this.keymap = Object.assign({}, options.public_keys); + + /** + * The secret key of this party, by default this follows libsodium's specs. + * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} + * @type {?Uint8Array} + */ + this.secret_key = options.secret_key; + + /** + * The public key of this party, by default this follows libsodium's specs. + * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} + * @type {?Uint8Array} + */ + this.public_key = options.public_key; + + /** + * Flags whether to use the server as a fallback for objects that were not pre-processed properly + * @type {!boolean} + */ + this.crypto_provider = (options.crypto_provider === true); + + /** + * Stores messages that are received with a signature prior to acquiring the public keys of the sender. + * { 'party_id': [ { 'label': 'share/open/custom', } ] } + * @type {object} + */ + this.messagesWaitingKeys = {}; + + /** + * A map from tags to listeners (functions that take a sender_id and a string message). + * + * Stores listeners that are attached to this JIFF instance, listeners listen to custom messages sent by other parties. + * @type {!object} + */ + this.listeners = Object.assign({}, options.listeners); + + /** + * Stores custom messages that are received before their listeners are set. Messages are stored in order. + * { 'tag' => [ { "sender_id": , "message": }, ... ] } + * + * Once a listener has been set, the corresponding messages are sent to it in order. + * @type {!object} + */ + this.custom_messages_mailbox = {}; + + /** + * Stores all promises created within some barrier. + * @type {!object} + */ + this.barriers = {}; + + /** + * Stores the parties and callbacks for every .wait_for() registered by the user. + * @type {!Array} + */ + this.wait_callbacks = []; + + /** + * Counts how many times JIFF attempted to initialize with the server + * without success consecutively. + * @type {!number} + * + */ + this.initialization_counter = 0; + + /** + * Utility functions + * @type {!utils} + */ + this.utils = {}; + utils(this); + + /** + * An array containing the names (jiff-client-[name].js) of the extensions that are + * applied to this instance. + * @type {string[]} + */ + this.extensions = ['base']; + + /** + * Internal helpers for operations inside/on a share. Modify existing helpers or add more in your extensions + * to avoid having to re-write and duplicate the code for primitives. + * @type {!object} + */ + this.share_helpers = share_helpers; + + /** + * The constructor function used by JIFF to create a new share. This can be overloaded by extensions to create custom shares. + * Modifying this will modify how shares are generated in the BASE JIFF implementation. + * A share is a value/promise wrapped with a share object. + * A share also has methods for performing operations. + * @constructor + * @param {number|promise} value - the value of the share, or a promise to it. + * @param {Array} holders - the parties that hold all the corresponding shares (must be sorted). + * @param {number} threshold - the min number of parties needed to reconstruct the secret. + * @param {number} Zp - the mod under which this share was created. + * + * @example + * // A share whose value is 10: the secret is still unknown, 10 is only one share + * var share = new jiffClient.SecretShare(10, [1, 2, 3], 3, jiffClient.Zp); + * + * @example + * // A share whose value depends on some promise + * var share = new jiffClient.SecretShare(promise, [1, 2, 3, 4], 4, jiffClient.Zp); + */ + this.SecretShare = SecretShareMetaClass(this); + + /** + * A collection of useful protocols to be used during computation or preprocessing: extensions are encouraged to add useful + * common protocols here, under a sub namespace corresponding to the extension name. + * @type {!protocols} + */ + this.protocols = {}; + + /** + * A collection of useful protocols for manipulating bitwise shared numbers, and transforming them from and to regular numeric shares. + * @member {!bits} bits + * @memberof protocols + */ + this.protocols.bits = {}; + + /** + * Stores pre-computed values (beaver triples, random bits, etc) used to aid/speed up the main processes. + * @type {!object} + */ + this.preprocessing_table = {}; + + /** + * Sets batch size for base level preprocessing tasks + * @type {!Number} + */ + this.preprocessingBatchSize = options.preprocessingBatchSize || 10; + + /** + * maps all primitive operations to the other operations they are dependent on, until leaves are primitives for which preprocessing protocols are defined, + * this map is traversed during preprocessing to guide preprocessing of high level operations. Extensions should modify this map to reflect + * any required changes to preprocessing of modified primitives + * @type {!object} + */ + this.preprocessing_function_map = {}; + + /** + * Store the default preprocessing protocols for each type of preprocessing value + * @type {!object} + */ + this.default_preprocessing_protocols = {}; + + /** + * Stores currently executing preprocessing tasks. + * @type {!linkedlist} + */ + this.currentPreprocessingTasks = linkedList(); + + /** + * Callback to execute when preprocessing is done! + * @type {?function} + */ + this.preprocessingCallback = null; + + /** + * Used for logging/debugging + * @type {!Array} + */ + this.logs = []; + + /** + * A map from open operation id to the corresponding shares received for that open operation + * @type {!object} + */ + this.shares = {}; + + /** + * A map from some message operation id to a deferred resolved when that message is received. + * @type {!object} + */ + this.deferreds = {}; + + /** + * Store sharing and shares counter which keeps track of the count of + * sharing operations (share and open) and the total number of shares + * respectively (used to get a unique id for each share operation and + * share object). + * @type {!object} + */ + this.counters = {}; + + /** + * A prefix attached to all op_ids, can be changed using {@link module:jiff-client~JIFFClient#seed_ids} + * to guarantee uniqueness of auto generate ids in a user-side callback + * or event handler. + * @type {string} + * @see {@link module:jiff-client~JIFFClient#seed_ids} + */ + this.op_id_seed = ''; + + /** + * The hooks for this instance. + * Checkout the hooks documentation + * @type {!hooks} + */ + this.hooks = new Hooks(this); + + /** + * Contains handlers for communication events + * @type {!handlers} + */ + this.handlers = {}; + + /** + * Stores the OT for gmw bit computation. + * @type {Promise} + */ + this.OT=OT; + + // Add user facing API + api(this); + + // Preprocessing + preprocessingMap(this); + preprocessingAPI(this); + preprocessingDaemon(this); + + if (options.__internal_socket == null) { + /** + * Socket wrapper between this instance and the server, based on sockets.io + * @type {!GuardedSocket} + */ + this.socket = guardedSocket(this); + } else { + this.socket = internalSocket(this, options.__internal_socket); + } + + // set up counters for op_ids + counters(this); + + // set up socket event handlers + handlers(this); + this.initSocket(); + + /** + * Connect to the server and starts listening. + */ + this.connect = function () { + // Ask socket to connect, which will automatically trigger a call to 'initialize()' when connection is established! + if (jiffClient.sodium_ === false) { + jiffClient.socket.connect(); + } else { + jiffClient.sodium_.ready.then(function () { + jiffClient.socket.connect(); + }); + } + }; + + // Connect when all is done + if (options.autoConnect !== false) { + this.connect(); + } +} + +// Add extension management to prototype +extensions(JIFFClient); + +// Add socket event handlers to prototype +socketEvents(JIFFClient); + +// export JIFFClient class +module.exports = JIFFClient; - try { - return jiff.sodium_.crypto_box_open_easy(cipher_text, nonce, signing_public_key, decryption_secret_key, 'text'); - } catch (_) { - throw new Error('Bad signature or Bad nonce: Cipher: ' + cipher_text + '. DecSKey: ' + decryption_secret_key + '. SignPKey: ' + signing_public_key); +},{"./client/api.js":1,"./client/arch/counters.js":9,"./client/arch/extensions.js":10,"./client/arch/hooks.js":11,"./client/handlers.js":12,"./client/preprocessing/api.js":17,"./client/preprocessing/daemon.js":18,"./client/preprocessing/map.js":20,"./client/protocols/gmw_bit/IO.js":28,"./client/share.js":43,"./client/shareHelpers.js":44,"./client/socket/events.js":45,"./client/socket/internal.js":46,"./client/socket/mailbox.js":47,"./client/util/constants.js":48,"./client/util/helpers.js":50,"./client/util/utils.js":51,"./common/linkedlist.js":53,"1-out-of-n":55,"libsodium-wrappers":229}],55:[function(require,module,exports){ +module.exports = function (io, sodium) { + if (sodium == null) { + sodium = require('libsodium-wrappers-sumo'); } + + const ot = require('./lib/ot.js')(io, sodium); + + return new Promise(function (resolve) { + sodium.ready.then(function () { + resolve(ot); + }); + }); }; -},{}],46:[function(require,module,exports){ -var helpers = require('../../common/helpers.js'); - -/** - * Contains helper functions: these may be overriden by extensions to customize behavior - * @see {@link module:jiff-client~JIFFClient#helpers} - * @name helpers - * @alias helpers - * @namespace - */ - -module.exports = function (jiffClient) { - /** - * Polyfill for jQuery Deferred - * From https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred - * @memberof helpers - * @constructor Deferred - */ - jiffClient.helpers.Deferred = function () { - /** - * A method to resolve the associate Promise with the value passed. - * @method resolve - * @memberof helpers.Deferred - * @instance - * @param {*} value - the value to resolve the promise with - */ - this.resolve = null; - - /** - * A method to reject the associated Promise with the value passed. - * If the promise is already settled it does nothing. - * @method reject - * @memberof helpers.Deferred - * @instance - * @param {*} reason - The reason for the rejection of the Promise. - * Generally its an Error object. If however a Promise is passed, then the Promise - * itself will be the reason for rejection no matter the state of the Promise. - */ - this.reject = null; - - /** - * A newly created Promise object. - * Initially in pending state. - * @memberof helpers.Deferred - * @member {Promise} promise - * @instance - */ - this.promise = new Promise(function (resolve, reject) { - this.resolve = resolve; - this.reject = reject; - }.bind(this)); - - Object.freeze(this); - }; - - /** - * Correct Mod instead of javascript's remainder (%). - * @memberof helpers - * @method - * @param {number} x - the number. - * @param {number} y - the mod. - * @return {number} x mod y. - */ - jiffClient.helpers.mod = helpers.mod; - - /** - * Ceil of a number. - * @memberof helpers - * @method - * @param {number} x - the number to ceil. - * @return {number} ceil of x. - */ - jiffClient.helpers.ceil = Math.ceil; - - /** - * Floor of a number - * @memberof helpers - * @method - * @param {number} x - the number to floor. - * @return {number} floor of x. - */ - jiffClient.helpers.floor = Math.floor; - - /** - * Fast Exponentiation Mod - * @memberof helpers - * @method - * @param {number} a - the base number - * @param {number} b - the power - * @param {number} n - the mod - * @return {number} (base^pow) mod m - */ - jiffClient.helpers.pow_mod = function (a, b, n) { - a = jiffClient.helpers.mod(a, n); - var result = 1; - var x = a; - while (b > 0) { - var leastSignificantBit = jiffClient.helpers.mod(b, 2); - b = Math.floor(b / 2); - if (leastSignificantBit === 1) { - result = result * x; - result = jiffClient.helpers.mod(result, n); - } - x = x * x; - x = jiffClient.helpers.mod(x, n); - } - return result; - }; - /** - * Extended Euclidean for finding inverses. - * @method - * @memberof helpers - * @param {number} a - the number to find inverse for. - * @param {number} b - the mod. - * @return {number[]} [inverse of a mod b, coefficient for a, coefficient for b]. - */ - jiffClient.helpers.extended_gcd = function (a, b) { - if (b === 0) { - return [1, 0, a]; - } - - var temp = jiffClient.helpers.extended_gcd(b, jiffClient.helpers.mod(a, b)); - var x = temp[0]; - var y = temp[1]; - var d = temp[2]; - return [y, x - y * Math.floor(a / b), d]; - }; - - /** - * Compute Log to a given base. - * @method - * @memberof helpers - * @param {number} value - the number to find log for. - * @param {number} [base=2] - the base (2 by default). - * @return {number} log(value) with the given base. - */ - jiffClient.helpers.bLog = function (value, base) { - if (base == null) { - base = 2; - } - return Math.log(value) / Math.log(base); - }; - - /** - * Check that two sorted arrays are equal. - * @method - * @memberof helpers - * @param {Array} arr1 - the first array. - * @param {Array} arr2 - the second array. - * @return {boolean} true if arr1 is equal to arr2, false otherwise. - */ - jiffClient.helpers.array_equals = function (arr1, arr2) { - if (arr1.length !== arr2.length) { - return false; - } +},{"./lib/ot.js":57,"libsodium-wrappers-sumo":228}],56:[function(require,module,exports){ +module.exports = function (sodium, util) { - for (var i = 0; i < arr1.length; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } + // PRF of length m + const PRF = function (k, I) { + var x = Uint8Array.from(util.to_bits(I, 32)); + return sodium.crypto_aead_chacha20poly1305_encrypt(x, null, null, new Uint8Array(8), k); + }; - return true; + // KDF of length t + const KDF = function () { + return sodium.randombytes_buf(32); }; - /** - * Check that two Zps are equal. Used to determine if shares can be computed on or not. - * @method - * @memberof helpers - * @param {SecretShare} s1 - the first share. - * @param {SecretShare} s2 - the second share. - * @return {boolean} true both shares have the same Zp, false otherwise. - */ - jiffClient.helpers.Zp_equals = function (s1, s2) { - return s1.Zp === s2.Zp; - }; - - /** - * Generate a random integer between 0 and max-1 [inclusive]. - * Modify this to change the source of randomness and how it is generated. - * @method - * @memberof helpers - * @param {number} max - the maximum number. - * @return {number} the random number. - */ - jiffClient.helpers.random = helpers.random; - - /** - * Get the party number from the given party_id, the number is used to compute/open shares. - * If party id was a number (regular party), that number is returned, - * If party id refers to the ith server, then party_count + i is returned (i > 0). - * @method - * @memberof helpers - * @param {number|string} party_id - the party id from which to compute the number. - * @return {number} the party number (> 0). - */ - jiffClient.helpers.get_party_number = helpers.get_party_number; - - /** - * Transforms the given number to an array of bits (numbers). - * Lower indices in the returned array corresponding to less significant bits. - * @memberof helpers - * @method - * @param {number} number - the number to transform to binary - * @param {length} [length=ceil(log2(number))] - if provided, then the given array will be padded with zeros to the length. - * @return {number[]} the array of bits. - */ - jiffClient.helpers.number_to_bits = helpers.number_to_bits; - - /** - * Transforms the given array of bits to a number. - * @memberof helpers - * @method - * @param {number[]} bits - the array of bits to compose as a number, starting from least to most significant bits. - * @param {number} [length = bits.length] - if provided, only the first 'length' bits will be used - * @return {number} the array of bits. - */ - jiffClient.helpers.bits_to_number = function (bits, length) { - if (length == null || length > bits.length) { - length = bits.length; - } - return parseInt(bits.slice(0, length).reverse().join(''), 2); - }; - - /** - * Checks if the given number is prime using AKS primality test - * @method - * @memberof helpers - * @param {number} p - the number to check - * @return {boolean} true if p is prime, false otherwise - */ - jiffClient.helpers.is_prime = function (p) { - // AKS Primality Test - - if (p === 2) { - return true; - } else if (p === 3) { - return true; - } else if (p % 2 === 0) { - return false; - } else if (p % 3 === 0) { - return false; - } + const encrypt_generic = function (plaintext, key) { + return sodium.crypto_aead_chacha20poly1305_encrypt(plaintext, null, null, new Uint8Array(8), key); + }; - var i = 5; - var n = 2; - while (i * i <= p) { - if (p % i === 0) { - return false; - } - i += n; - n = 6 - n; - } + const decrypt_generic = function (ciphertext, key) { + return sodium.crypto_aead_chacha20poly1305_decrypt(null, ciphertext, null, new Uint8Array(8), key); + }; - return true; + return { + PRF: PRF, + KDF: KDF, + encrypt_generic: encrypt_generic, + decrypt_generic: decrypt_generic }; +}; - /** - * sorts an array of ids (in place) according to a consistent ordering - * @method - * @memberof helpers - * @param {array} ids - array of ids containing numbers or "s1" - */ - jiffClient.helpers.sort_ids = function (ids) { - if (ids.__jiff_sorted) { - return; - } +},{}],57:[function(require,module,exports){ +module.exports = function (io, sodium) { + const util = require('./util.js')(sodium); + const crypto = require('./crypto.js')(sodium, util); - ids.sort(function (e1, e2) { - if (e1 === e2) { - throw new Error('ids array has duplicated: ' + ids.toString()); - } - if (e1 === 's1') { - return 1; - } - if (e2 === 's1') { - return -1; - } - return e1 - e2; - }); - ids.__jiff_sorted = true; - } -}; -},{"../../common/helpers.js":48}],47:[function(require,module,exports){ -/** - * Contains utility functions (higher order combinators) - * @see {@link module:jiff-client~JIFFClient#utils} - * @name utils - * @alias utils - * @namespace - */ - -module.exports = function (jiffClient) { - /** - * Create an array of secret shares and associated deferred. - * @method - * @memberof utils - * @param {number} count - number of secret shares - * @param {Array} holders - the parties that hold all the corresponding shares (must be sorted) - * @param {number} threshold - the min number of parties needed to reconstruct the secret - * @param {number} Zp - the mod under which this share was created - * @return {object} the secret share object containing the give value - * - */ - jiffClient.utils.many_secret_shares = function (count, holders, threshold, Zp) { - var deferreds = []; - var shares = []; - for (var i = 0; i < count; i++) { - var deferred = new jiffClient.helpers.Deferred(); - shares.push(new jiffClient.SecretShare(deferred.promise, holders, threshold, Zp)); - deferreds.push(deferred); - } - - return {shares: shares, deferreds: deferreds}; - }; - - /** - * Resolve the array of deferreds with the values of the given shares when ready, matched by index - * @method - * @memberof utils - * @param {Deferred[]} deferreds - the deferred to resolve - * @param {SecretShare[]} shares - the shares to resolve with - */ - jiffClient.utils.resolve_many_secrets = function (deferreds, shares) { - for (var i = 0; i < deferreds.length; i++) { - shares[i].wThen(deferreds[i].resolve); - } - }; - - /** - * Combines all the promises of the given share into a single promise that is resolved when - * all shares are resolved - * @method - * @methodof utils - * @param {SecretShare[]} shares - the shares whose promises should be joined - */ - jiffClient.utils.all_promises = function (shares) { - var promises = []; - for (var i = 0; i < shares.length; i++) { - promises.push(shares[i].value); - } - return Promise.all(promises); - }; - - /** - * A high level combinator for iteration of bit arrays - * It executes a round of (func) starting from index start to the length (supports backwards if start > length) excluding length - * Every round is blocked until the previous one finishes and the promise produced by it - * is resolved - * The final value is used to resolve deferred - * @method - * @memberof utils - * @param {!Deferred} deferred - the deferred to resolve with the final output - * @param {!number} start - the index to start from - * @param {!number} length - the index to stop at (excluding it) - * @param {?object} initial - an initial aggregator value - * @param {!function(number, object)} func - the aggregator function to apply to the elements in order, takes the index and the aggregator value so far - * @param {?function(object)} [promisify] - if initial is not null, this is called prior to starting combinator, to turn initial - * into a promise of the actually used initial value(in case it has to be resolved), - * defaults to promisifying a SecretShare with .wThen - * @param {?function(object)} [valufy] - applied to the final result to turn it into a value, which is then used to resolve deferred, - * defaults to getting value of a SecretShare - */ - jiffClient.utils.bit_combinator = function (deferred, start, length, initial, func, promisify, valufy) { - if (promisify == null) { - promisify = function (share) { - return {then: share.wThen.bind(share)}; - } - } - - if (valufy == null) { - valufy = function (share) { - return share.value; - } - } - - var next = start <= length ? 1 : -1; - var __bit_combinator = function (start, val) { - if (start === length) { - // done - deferred.resolve(valufy(val)); - return; - } + // 1-out-of-2 OT sending + const send_from_2 = function (X1, X2, op_id, session_id) { + op_id = op_id + ':1in2ot'; - // execute func once - val = func(start, val); + var get = io.get.bind(null,op_id, session_id,arguments[4]);// [jiff,jiff1...] arguments[4] means extra parameters + var give = io.give.bind(null,op_id, session_id,arguments[4]); + const a = sodium.crypto_core_ristretto255_scalar_random(); + const A = sodium.crypto_scalarmult_ristretto255_base(a); - // when done, do next iteration - promisify(val).then(function () { - __bit_combinator(start + next, val); - }); - }; + give('A', util.to_str(A)); + get('B').then(function (B_str) { + const B = util.from_str(B_str); - // start combinator - if (initial == null) { - __bit_combinator(start, initial); - } else { - promisify(initial).then(function () { - __bit_combinator(start, initial); - }); - } - } -}; -},{}],48:[function(require,module,exports){ -var crypto_; -if (typeof(window) === 'undefined') { - crypto_ = require('crypto'); - crypto_.__randomBytesWrapper = crypto_.randomBytes; -} else { - crypto_ = window.crypto || window.msCrypto; - crypto_.__randomBytesWrapper = function (bytesNeeded) { - var randomBytes = new Uint8Array(bytesNeeded); - crypto_.getRandomValues(randomBytes); - return randomBytes; - }; -} + var k0 = sodium.crypto_scalarmult_ristretto255(a, B); + var k1 = sodium.crypto_scalarmult_ristretto255(a, sodium.crypto_core_ristretto255_sub(B, A)); -// Secure randomness via rejection sampling. -exports.random = function (max) { - // Use rejection sampling to get random value within bounds - // Generate random Uint8 values of 1 byte larger than the max parameter - // Reject if random is larger than quotient * max (remainder would cause biased distribution), then try again + k0 = sodium.crypto_generichash(32, k0); + k1 = sodium.crypto_generichash(32, k1); - // Values up to 2^53 should be supported, but log2(2^49) === log2(2^49+1), so we lack the precision to easily - // determine how many bytes are required - if (max > 562949953421312) { - throw new RangeError('Max value should be smaller than or equal to 2^49'); - } + const e0 = crypto.encrypt_generic(X1, k0); + const e1 = crypto.encrypt_generic(X2, k1); - var bitsNeeded = Math.ceil(Math.log(max)/Math.log(2)); - var bytesNeeded = Math.ceil(bitsNeeded / 8); - var maxValue = Math.pow(256, bytesNeeded); + give('e', util.to_str([e0, e1])); + }); + }; - // Keep trying until we find a random value within bounds - while (true) { // eslint-disable-line - var randomBytes = crypto_.__randomBytesWrapper(bytesNeeded); - var randomValue = 0; + // 1-out-of-2 OT receiving + const receive_from_2 = function (c, op_id, session_id) { + op_id = op_id + ':1in2ot'; + var get = io.get.bind(null,op_id, session_id,arguments[3]); + var give = io.give.bind(null,op_id, session_id,arguments[3]); + const b = sodium.crypto_core_ristretto255_scalar_random(); + var B = sodium.crypto_scalarmult_ristretto255_base(b); - for (var i = 0; i < bytesNeeded; i++) { - randomValue = randomValue * 256 + (randomBytes.readUInt8 ? randomBytes.readUInt8(i) : randomBytes[i]); - } + return new Promise(function (resolve) { + get('A').then(function (A_str) { + const A = util.from_str(A_str); - // randomValue should be smaller than largest multiple of max within maxBytes - if (randomValue < maxValue - maxValue % max) { - return randomValue % max; - } - } -}; + if (c === 1) { + B = sodium.crypto_core_ristretto255_add(A, B); + } -// actual mode -exports.mod = function (x, y) { - if (x < 0) { - return (x % y) + y; - } - return x % y; -}; + give('B', util.to_str(B)); + get('e').then(function (both_e_str) { + const e12 = util.from_str(both_e_str); + const e = e12[c]; // e_c from [e_1, e_2] -// get the party number from the given party_id, the number is used to compute/open shares -exports.get_party_number = function (party_id) { - if (typeof(party_id) === 'number') { - return party_id; - } - if (party_id.startsWith('s')) { - return -1 * parseInt(party_id.substring(1), 10); - } - return parseInt(party_id, 10); -}; + var k = sodium.crypto_scalarmult_ristretto255(b, A); + k = sodium.crypto_generichash(32, k); -// transform number to bit array -exports.number_to_bits = function (number, length) { - number = number.toString(2); - var bits = []; - for (var i = 0; i < number.length; i++) { - bits[i] = parseInt(number.charAt(number.length - 1 - i)); - } - while (length != null && bits.length < length) { - bits.push(0); - } - return bits; -}; -},{"crypto":113}],49:[function(require,module,exports){ -/** Doubly linked list with add and remove functions and pointers to head and tail**/ -module.exports = function () { - // attributes: list.head and list.tail - // functions: list.add(object) (returns pointer), list.remove(pointer) - // list.head/list.tail/any element contains: - // next: pointer to next, - // previous: pointer to previous, - // object: stored object. - var list = {head: null, tail: null}; - // TODO rename this to pushTail || push - list.add = function (obj) { - var node = { object: obj, next: null, previous: null }; - if (list.head == null) { - list.head = node; - list.tail = node; - } else { - list.tail.next = node; - node.previous = list.tail; - list.tail = node; - } - return node; + var Xc = crypto.decrypt_generic(e, k); + + resolve(Xc); + }); + }); + }); }; - list.pushHead = function (obj) { - list.head = {object: obj, next : list.head, previous : null}; - if (list.head.next != null) { - list.head.next.previous = list.head; - } else { - list.tail = list.head; + // 1-out-of-2 OT sending + const send_from_N = function (X, N, op_id, session_id) { + var I, j; + op_id = op_id + ':1inNot'; + let args= Array.prototype.slice.call(arguments,4); //extra parameters[jiff,jiff1 ... ] + + var give = io.give.bind(null, op_id, session_id,args); + X = util.sanitize(X); // Check padding and fix if not the right type + + if (N == null) { + N = X.length; } - }; - list.popHead = function () { - var result = list.head; - if (list.head != null) { - list.head = list.head.next; - if (list.head == null) { - list.tail = null; - } else { - list.head.previous = null; + const l = Math.ceil(Math.log2(N)); // N = 2^l + + var K = Array(l); + for (j = 0; j < l; j++) { + K[j] = Array(2); + for (var b = 0; b <= 1; b++) { + K[j][b] = crypto.KDF(); // {K_{j}}^{b} } } - return result; - }; - // merges two linked lists and return a pointer to the head of the merged list - // the head will be the head of list and the tail the tail of l2 - list.extend = function (l2) { - if (list.head == null) { - return l2; + var Y = Array(N); + for (I = 0; I < N; I++) { + var i = util.to_bits(I, l); // l bits of I + + Y[I] = X[I]; // new Uint8Array(m); + for (j = 0; j < l; j++) { + const i_j = i[j]; + const K_j = K[j]; + const Kj_ij = K_j[i_j]; // {K_{j}}^{i_j} + Y[I] = util.xor(Y[I], crypto.PRF(Kj_ij, I)); + } } - if (l2.head == null) { - return list; + for (j = 0; j < l; j++) { + const K_j = K[j]; + send_from_2(K_j[0], K_j[1], op_id+j, session_id,args);//[jiff,all extra] } - list.tail.next = l2.head; - l2.head.previous = list.tail; - list.tail = l2.tail; - return list; + for (I = 0; I < N; I++) { + give('I' + String(I), util.to_str(Y[I])); // reveal Y_I + } }; - list.remove = function (ptr) { - var prev = ptr.previous; - var next = ptr.next; - - if (prev == null && list.head !== ptr) { - return; - } else if (next == null && list.tail !== ptr) { - return; - } + // 1-out-of-2 OT receiving + const receive_from_N = function (I, N, op_id, session_id) { + var j; + op_id = op_id + ':1inNot'; + let args= Array.prototype.slice.call(arguments,4); + var get = io.get.bind(null,op_id, session_id,args); + return new Promise(function (resolve) { + const l = Math.ceil(Math.log2(N)); // N = 2^l + const i = util.to_bits(I, l); // l bits of I - if (prev == null) { // ptr is head (or both head and tail) - list.head = next; - if (list.head != null) { - list.head.previous = null; - } else { - list.tail = null; + var K = Array(l); + for (j = 0; j < l; j++) { + const i_j = i[j]; // bit j=i_j of I + K[j] = receive_from_2(i_j, op_id+j, session_id,args); // pick {K_{j}}^{b} which is also {K_{j}}^{i_j} } - } else if (next == null) { // ptr is tail (and not head) - list.tail = prev; - prev.next = null; - } else { // ptr is inside - prev.next = next; - next.previous = prev; - } - }; - list.slice = function (ptr) { // remove all elements from head to ptr (including ptr). - if (ptr == null) { - return; - } - /* CONSERVATIVE: make sure ptr is part of the list then remove */ - var current = list.head; - while (current != null) { - if (current === ptr) { - list.head = ptr.next; - if (list.head == null) { - list.tail = null; + Promise.all(K).then(function (K) { + var Y_I = new Uint8Array(32); + for (var pI = 0; pI < N; pI++) { + const pY_pI = get('I' + String(pI)); + if (pI === I) { + Y_I = pY_pI; + } } - return; - } - current = current.next; - } + Y_I.then(function (Y_I_str) { + const Y_I = util.from_str(Y_I_str); - /* MORE AGGRESSIVE VERSION: will be incorrect if ptr is not in the list */ - /* - list.head = ptr.next; - if (list.head == null) { - list.tail = null; - } - */ + var X_I = Y_I; // new Uint8Array(m); + for (j = 0; j < l; j++) { + const Kj_ij = K[j]; // {K_{j}}^{i_j} + X_I = util.xor(X_I, crypto.PRF(Kj_ij, I)); + } + + // Done + resolve(X_I); + }); + }); + }); }; - /* - list._debug_length = function () { - var l = 0; - var current = list.head; - while (current != null) { - current = current.next; - l++; - } - return l; + + return { + send: send_from_N, + receive: receive_from_N, + single_send: send_from_2, + single_receive: receive_from_2 }; - */ - return list; }; -},{}],50:[function(require,module,exports){ -/** - * JIFF Client. - * - * Exposes the constructor for the {@link module:jiff-client~JIFFClient} class. - * - * In the browser, this adds `JIFFClient` as a global identifier. - * - * In the browser, this can be accessed via: - *

- *   <script src="jiff-client.js"></script>
- *   <script type="text/javascript">
- *     var jiffClientInstance = new JIFFClient(hostname, computationId, options);
- *   </script>
- * 
- * - * In node.js, this can be accessed via: - *

- *   const JIFFClient = require('jiffClient');
- *   const jiffClientInstance = new JIFFClient(hostname, computationId, options);
- *
- * 
- * - * @module jiff-client - * @alias jiff-client - */ - -// browserify bundles this into our code bundle -var sodium = require('libsodium-wrappers'); - -// utils and helpers -var constants = require('./client/util/constants.js'); -var helpers = require('./client/util/helpers.js'); -var utils = require('./client/util/utils.js'); -var linkedList = require('./common/linkedlist.js'); - -// hooks -var Hooks = require('./client/arch/hooks.js'); - -// extensions management -var extensions = require('./client/arch/extensions.js'); - -// op ids and other counters -var counters = require('./client/arch/counters.js'); - -// socket and events -var guardedSocket = require('./client/socket/mailbox.js'); -var internalSocket = require('./client/socket/internal.js'); -var socketEvents = require('./client/socket/events.js'); - -// handlers for communication -var handlers = require('./client/handlers.js'); - -// secret shares -var SecretShareMetaClass = require('./client/share.js'); -var share_helpers = require('./client/shareHelpers.js'); - -// jiff client instance API -var api = require('./client/api.js'); - -// preprocessing -var preprocessingMap = require('./client/preprocessing/map.js'); -var preprocessingAPI = require('./client/preprocessing/api.js'); -var preprocessingDaemon = require('./client/preprocessing/daemon.js'); - -/** - * Creates a new jiff client instance. - * @class - * @name JIFFClient - * @param {!string} hostname - server hostname/ip and port. - * @param {!string} computation_id - the id of the computation of this instance. - * @param {?object} [options={}] - javascript object with additional options. - * all parameters are optional, However, private and public key must either be both provided or neither of them provided. -
- {
-   "party_id": number,
-   "party_count": number,
-   "secret_key": Uint8Array to be used with libsodium-wrappers [(check Library Specs)]{@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html},
-   "public_key": Uint8Array to be used with libsodium-wrappers [(check Library Specs)]{@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html},
-   "public_keys": { 1: "Uint8Array PublicKey", 2: "Uint8Array PublicKey", ... },
-   "Zp": default mod to use (prime number),
-   "autoConnect": true/false,
-   "hooks": { 'check out hooks documentation' },
-   "listeners" : A map from custom tags to listeners (of type function(sender_id, message_string)) that handle custom messages with that tag.
-   "onConnect": function(jiff_instance),
-   "onError": function(label, error): called when errors occured in client code or during handling requests from this client at the server side
-                                      label is a string indicating where the error occured, and error is a string or an exception object.
-   "safemod": boolean (whether or not to check if provided Zp is prime, may be slow for big primes, defaults to false),
-   "crypto_provider": a boolean that flags whether to get beaver triplets and other preprocessing entities from the server (defaults to false),
-   "socketOptions": an object, passed directly to socket.io constructor,
-   "maxInitializationRetries": how many consecutive times to retry to initialize with the server if initialization fails, defaults to 2,
-   "preprocessingBatchSize": how many base level preprocessing tasks to execute in parallel.
- }
- 
- * - * @example - * var JIFFClient = require('jiffClient'); // only for node.js - * // for the browser - * // build a jiff instance which will connect to a server running on the local machine - * var instance = new JIFFClient('http://localhost:8080', 'computation-1', {party_count: 2}); - */ -function JIFFClient(hostname, computation_id, options) { - var jiffClient = this; - options = Object.assign({}, options); - - /** - * The server hostname, ends with a slash, includes port and protocol (http/https). - * @type {!string} - */ - this.hostname = hostname.trim(); - if (!this.hostname.endsWith('/')) { - this.hostname = this.hostname + '/'; - } - - /** - * Stores the computation id. - * @type {!string} - */ - this.computation_id = computation_id; - - /** - * Private. Do not use directly externally; use isReady() instead. - * @type {!boolean} - * @see {@link module:jiff-client~JIFFClient#isReady} - */ - this.__ready = false; - - /** - * Private. Do not use directly externally; use isInitialized() instead. - * @type {!boolean} - * @see {@link module:jiff-client~JIFFClient#isInitialized} - */ - this.__initialized = false; - - /** - * Returns whether this instance is capable of starting the computation. - * In other words, the public keys for all parties and servers are known, - * and this party successfully initialized with the server. - * @returns {!boolean} - */ - this.isReady = function () { - return this.__ready; - }; - - /** - * Returns whether this instance initialized successfully with the server. - * Note that this can be true even when isReady() returns false, in case where some other parties have not - * initialized yet! - * @returns {!boolean} - */ - this.isInitialized = function () { - return this.__initialized; - }; - - /** - * Helper functions [DO NOT MODIFY UNLESS YOU KNOW WHAT YOU ARE DOING]. - * @type {!helpers} - */ - this.helpers = {}; - helpers(this); - - /** - * Shallow copy of the options passed to the constructor. - * @type {!Object} - */ - this.options = options; +},{"./crypto.js":56,"./util.js":58}],58:[function(require,module,exports){ +module.exports = function (sodium) { + // Bit decomposition + const to_bits = function (I, l) { + var i = I.toString(2).split('').map(Number); + i = i.reverse(); // little endian for correctness, but actually doesn't matter for the use in OT + var il = i.concat(Array(l - i.length).fill(0)); + return il; + }; - // Parse and verify options - options.maxInitializationRetries = options.maxInitializationRetries || constants.maxInitializationRetries; - if (typeof(options.Zp) === 'number' && options.safemod !== false) { // big numbers are checked by extension - if (!this.helpers.is_prime(options.Zp)) { - throw new Error('Zp = ' + options.Zp + ' is not prime. Please use a prime number for the modulus or set safemod to false.'); - } - } - - /** - * The default Zp for this instance. - * @type {!number} - */ - this.Zp = options.Zp || constants.gZp; - - /** - * The id of this party. - * @type {number} - */ - this.id = options.party_id; - - /** - * Total party count in the computation, parties will take ids between 1 to party_count (inclusive). - * @type {number} - */ - this.party_count = options.party_count; - - /** - * sodium wrappers either imported via require (if in nodejs) or from the bundle (in the browser). - * This will be undefined if options.sodium is false. - * @see {@link https://www.npmjs.com/package/libsodium-wrappers} - * @type {?sodium} - */ - this.sodium_ = options.sodium !== false ? sodium : null; - - /** - * A map from party id to public key. Where key is the party id (number), and - * value is the public key, which by default follows libsodium's specs (Uint8Array). - * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} - * @type {!object} - */ - this.keymap = Object.assign({}, options.public_keys); - - /** - * The secret key of this party, by default this follows libsodium's specs. - * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} - * @type {?Uint8Array} - */ - this.secret_key = options.secret_key; - - /** - * The public key of this party, by default this follows libsodium's specs. - * @see {@link https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html} - * @type {?Uint8Array} - */ - this.public_key = options.public_key; - - /** - * Flags whether to use the server as a fallback for objects that were not pre-processed properly - * @type {!boolean} - */ - this.crypto_provider = (options.crypto_provider === true); - - /** - * Stores messages that are received with a signature prior to acquiring the public keys of the sender. - * { 'party_id': [ { 'label': 'share/open/custom', } ] } - * @type {object} - */ - this.messagesWaitingKeys = {}; - - /** - * A map from tags to listeners (functions that take a sender_id and a string message). - * - * Stores listeners that are attached to this JIFF instance, listeners listen to custom messages sent by other parties. - * @type {!object} - */ - this.listeners = Object.assign({}, options.listeners); - - /** - * Stores custom messages that are received before their listeners are set. Messages are stored in order. - * { 'tag' => [ { "sender_id": , "message": }, ... ] } - * - * Once a listener has been set, the corresponding messages are sent to it in order. - * @type {!object} - */ - this.custom_messages_mailbox = {}; - - /** - * Stores all promises created within some barrier. - * @type {!object} - */ - this.barriers = {}; - - /** - * Stores the parties and callbacks for every .wait_for() registered by the user. - * @type {!Array} - */ - this.wait_callbacks = []; - - /** - * Counts how many times JIFF attempted to initialize with the server - * without success consecutively. - * @type {!number} - * - */ - this.initialization_counter = 0; - - /** - * Utility functions - * @type {!utils} - */ - this.utils = {}; - utils(this); - - /** - * An array containing the names (jiff-client-[name].js) of the extensions that are - * applied to this instance. - * @type {string[]} - */ - this.extensions = ['base']; - - /** - * Internal helpers for operations inside/on a share. Modify existing helpers or add more in your extensions - * to avoid having to re-write and duplicate the code for primitives. - * @type {!object} - */ - this.share_helpers = share_helpers; - - /** - * The constructor function used by JIFF to create a new share. This can be overloaded by extensions to create custom shares. - * Modifying this will modify how shares are generated in the BASE JIFF implementation. - * A share is a value/promise wrapped with a share object. - * A share also has methods for performing operations. - * @constructor - * @param {number|promise} value - the value of the share, or a promise to it. - * @param {Array} holders - the parties that hold all the corresponding shares (must be sorted). - * @param {number} threshold - the min number of parties needed to reconstruct the secret. - * @param {number} Zp - the mod under which this share was created. - * - * @example - * // A share whose value is 10: the secret is still unknown, 10 is only one share - * var share = new jiffClient.SecretShare(10, [1, 2, 3], 3, jiffClient.Zp); - * - * @example - * // A share whose value depends on some promise - * var share = new jiffClient.SecretShare(promise, [1, 2, 3, 4], 4, jiffClient.Zp); - */ - this.SecretShare = SecretShareMetaClass(this); - - /** - * A collection of useful protocols to be used during computation or preprocessing: extensions are encouraged to add useful - * common protocols here, under a sub namespace corresponding to the extension name. - * @type {!protocols} - */ - this.protocols = {}; - - /** - * A collection of useful protocols for manipulating bitwise shared numbers, and transforming them from and to regular numeric shares. - * @member {!bits} bits - * @memberof protocols - */ - this.protocols.bits = {}; - - /** - * Stores pre-computed values (beaver triples, random bits, etc) used to aid/speed up the main processes. - * @type {!object} - */ - this.preprocessing_table = {}; - - /** - * Sets batch size for base level preprocessing tasks - * @type {!Number} - */ - this.preprocessingBatchSize = options.preprocessingBatchSize || 10; - - /** - * maps all primitive operations to the other operations they are dependent on, until leaves are primitives for which preprocessing protocols are defined, - * this map is traversed during preprocessing to guide preprocessing of high level operations. Extensions should modify this map to reflect - * any required changes to preprocessing of modified primitives - * @type {!object} - */ - this.preprocessing_function_map = {}; - - /** - * Store the default preprocessing protocols for each type of preprocessing value - * @type {!object} - */ - this.default_preprocessing_protocols = {}; - - /** - * Stores currently executing preprocessing tasks. - * @type {!linkedlist} - */ - this.currentPreprocessingTasks = linkedList(); - - /** - * Callback to execute when preprocessing is done! - * @type {?function} - */ - this.preprocessingCallback = null; - - /** - * Used for logging/debugging - * @type {!Array} - */ - this.logs = []; - - /** - * A map from open operation id to the corresponding shares received for that open operation - * @type {!object} - */ - this.shares = {}; - - /** - * A map from some message operation id to a deferred resolved when that message is received. - * @type {!object} - */ - this.deferreds = {}; - - /** - * Store sharing and shares counter which keeps track of the count of - * sharing operations (share and open) and the total number of shares - * respectively (used to get a unique id for each share operation and - * share object). - * @type {!object} - */ - this.counters = {}; - - /** - * A prefix attached to all op_ids, can be changed using {@link module:jiff-client~JIFFClient#seed_ids} - * to guarantee uniqueness of auto generate ids in a user-side callback - * or event handler. - * @type {string} - * @see {@link module:jiff-client~JIFFClient#seed_ids} - */ - this.op_id_seed = ''; - - /** - * The hooks for this instance. - * Checkout the hooks documentation - * @type {!hooks} - */ - this.hooks = new Hooks(this); - - /** - * Contains handlers for communication events - * @type {!handlers} - */ - this.handlers = {}; - - // Add user facing API - api(this); - - // Preprocessing - preprocessingMap(this); - preprocessingAPI(this); - preprocessingDaemon(this); - - if (options.__internal_socket == null) { - /** - * Socket wrapper between this instance and the server, based on sockets.io - * @type {!GuardedSocket} - */ - this.socket = guardedSocket(this); - } else { - this.socket = internalSocket(this, options.__internal_socket); - } + // Bitwise XOR + const xorBytes = function (x, y) { + // if (x.length !== y.length) { + // throw new Error('Cannot XOR mismatched size byte arrays, ' + x.length + ' and ' + y.length + '.') + // } + + const bytes = new Uint8Array(x.length); - // set up counters for op_ids - counters(this); + for (var i = 0; i < bytes.length; i++) { + bytes[i] = x[i] ^ y[i]; + } - // set up socket event handlers - handlers(this); - this.initSocket(); + return bytes; + }; - /** - * Connect to the server and starts listening. - */ - this.connect = function () { - // Ask socket to connect, which will automatically trigger a call to 'initialize()' when connection is established! - if (jiffClient.sodium_ === false) { - jiffClient.socket.connect(); + // Message serialization helpers + const del = ', '; + const to_Uint8 = sodium.from_base64; + const from_Uint8 = sodium.to_base64; // Tip: Use sodium.to_hex for debug. + const to_str = function (x) { + if (Array.isArray(x)) { + return x.map(to_str).join(del); } else { - jiffClient.sodium_.ready.then(function () { - jiffClient.socket.connect(); - }); + return from_Uint8(x); + } + }; + const from_str = function (str) { + + if (str.indexOf(del) > 1) { + json_array = '["' + str.split(del).join('","') + '"]'; + return JSON.parse(json_array).map(from_str); + } else { + return to_Uint8(str); } }; - // Connect when all is done - if (options.autoConnect !== false) { - this.connect(); + // Convert an array of numbers into an array of Uint8Arrays + const sanitize = function (X, l) { + if (Array.isArray(X) && X.length > 0 && typeof(X[0]) === 'number') { + if (l == null) { + const max = function (x, y) { return x > y ? x : y; }; + const x_max = X.reduce(max, 0); + l = Math.ceil(Math.log2(x_max+1)/8); // the minimum bytes required + } + for (var i = 0; i < X.length; i++) { + var n = X[i]; + X[i] = new Uint8Array(l); + for (var j = 0; j < l; j++) { + X[i][j] = n % 256; + n = Math.floor(n/256); + } + } + } + return X; } -} -// Add extension management to prototype -extensions(JIFFClient); - -// Add socket event handlers to prototype -socketEvents(JIFFClient); - -// export JIFFClient class -module.exports = JIFFClient; + return { + to_bits: to_bits, + xor: xorBytes, + to_str: to_str, + from_str: from_str, + sanitize: sanitize + }; +} -},{"./client/api.js":1,"./client/arch/counters.js":9,"./client/arch/extensions.js":10,"./client/arch/hooks.js":11,"./client/handlers.js":12,"./client/preprocessing/api.js":17,"./client/preprocessing/daemon.js":18,"./client/preprocessing/map.js":20,"./client/share.js":39,"./client/shareHelpers.js":40,"./client/socket/events.js":41,"./client/socket/internal.js":42,"./client/socket/mailbox.js":43,"./client/util/constants.js":44,"./client/util/helpers.js":46,"./client/util/utils.js":47,"./common/linkedlist.js":49,"libsodium-wrappers":178}],51:[function(require,module,exports){ +},{}],59:[function(require,module,exports){ module.exports = after function after(count, callback, err_cb) { @@ -8363,7 +9337,7 @@ function after(count, callback, err_cb) { function noop() {} -},{}],52:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * An abstraction for slicing an arraybuffer even when * ArrayBuffer.prototype.slice is not supported @@ -8394,7 +9368,7 @@ module.exports = function(arraybuffer, start, end) { return result.buffer; }; -},{}],53:[function(require,module,exports){ +},{}],61:[function(require,module,exports){ var asn1 = exports; asn1.bignum = require('bn.js'); @@ -8405,7 +9379,7 @@ asn1.constants = require('./asn1/constants'); asn1.decoders = require('./asn1/decoders'); asn1.encoders = require('./asn1/encoders'); -},{"./asn1/api":54,"./asn1/base":56,"./asn1/constants":60,"./asn1/decoders":62,"./asn1/encoders":65,"bn.js":71}],54:[function(require,module,exports){ +},{"./asn1/api":62,"./asn1/base":64,"./asn1/constants":68,"./asn1/decoders":70,"./asn1/encoders":73,"bn.js":75}],62:[function(require,module,exports){ var asn1 = require('../asn1'); var inherits = require('inherits'); @@ -8468,7 +9442,7 @@ Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) { return this._getEncoder(enc).encode(data, reporter); }; -},{"../asn1":53,"inherits":175,"vm":250}],55:[function(require,module,exports){ +},{"../asn1":61,"inherits":224,"vm":304}],63:[function(require,module,exports){ var inherits = require('inherits'); var Reporter = require('../base').Reporter; var Buffer = require('buffer').Buffer; @@ -8586,7 +9560,7 @@ EncoderBuffer.prototype.join = function join(out, offset) { return out; }; -},{"../base":56,"buffer":102,"inherits":175}],56:[function(require,module,exports){ +},{"../base":64,"buffer":129,"inherits":224}],64:[function(require,module,exports){ var base = exports; base.Reporter = require('./reporter').Reporter; @@ -8594,7 +9568,7 @@ base.DecoderBuffer = require('./buffer').DecoderBuffer; base.EncoderBuffer = require('./buffer').EncoderBuffer; base.Node = require('./node'); -},{"./buffer":55,"./node":57,"./reporter":58}],57:[function(require,module,exports){ +},{"./buffer":63,"./node":65,"./reporter":66}],65:[function(require,module,exports){ var Reporter = require('../base').Reporter; var EncoderBuffer = require('../base').EncoderBuffer; var DecoderBuffer = require('../base').DecoderBuffer; @@ -9230,7 +10204,7 @@ Node.prototype._isPrintstr = function isPrintstr(str) { return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str); }; -},{"../base":56,"minimalistic-assert":182}],58:[function(require,module,exports){ +},{"../base":64,"minimalistic-assert":234}],66:[function(require,module,exports){ var inherits = require('inherits'); function Reporter(options) { @@ -9353,7 +10327,7 @@ ReporterError.prototype.rethrow = function rethrow(msg) { return this; }; -},{"inherits":175}],59:[function(require,module,exports){ +},{"inherits":224}],67:[function(require,module,exports){ var constants = require('../constants'); exports.tagClass = { @@ -9397,7 +10371,7 @@ exports.tag = { }; exports.tagByName = constants._reverse(exports.tag); -},{"../constants":60}],60:[function(require,module,exports){ +},{"../constants":68}],68:[function(require,module,exports){ var constants = exports; // Helper @@ -9418,7 +10392,7 @@ constants._reverse = function reverse(map) { constants.der = require('./der'); -},{"./der":59}],61:[function(require,module,exports){ +},{"./der":67}],69:[function(require,module,exports){ var inherits = require('inherits'); var asn1 = require('../../asn1'); @@ -9744,13 +10718,13 @@ function derDecodeLen(buf, primitive, fail) { return len; } -},{"../../asn1":53,"inherits":175}],62:[function(require,module,exports){ +},{"../../asn1":61,"inherits":224}],70:[function(require,module,exports){ var decoders = exports; decoders.der = require('./der'); decoders.pem = require('./pem'); -},{"./der":61,"./pem":63}],63:[function(require,module,exports){ +},{"./der":69,"./pem":71}],71:[function(require,module,exports){ var inherits = require('inherits'); var Buffer = require('buffer').Buffer; @@ -9801,7 +10775,7 @@ PEMDecoder.prototype.decode = function decode(data, options) { return DERDecoder.prototype.decode.call(this, input, options); }; -},{"./der":61,"buffer":102,"inherits":175}],64:[function(require,module,exports){ +},{"./der":69,"buffer":129,"inherits":224}],72:[function(require,module,exports){ var inherits = require('inherits'); var Buffer = require('buffer').Buffer; @@ -10098,13 +11072,13 @@ function encodeTag(tag, primitive, cls, reporter) { return res; } -},{"../../asn1":53,"buffer":102,"inherits":175}],65:[function(require,module,exports){ +},{"../../asn1":61,"buffer":129,"inherits":224}],73:[function(require,module,exports){ var encoders = exports; encoders.der = require('./der'); encoders.pem = require('./pem'); -},{"./der":64,"./pem":66}],66:[function(require,module,exports){ +},{"./der":72,"./pem":74}],74:[function(require,module,exports){ var inherits = require('inherits'); var DEREncoder = require('./der'); @@ -10127,419 +11101,7 @@ PEMEncoder.prototype.encode = function encode(data, options) { return out.join('\n'); }; -},{"./der":64,"inherits":175}],67:[function(require,module,exports){ - -/** - * Expose `Backoff`. - */ - -module.exports = Backoff; - -/** - * Initialize backoff timer with `opts`. - * - * - `min` initial timeout in milliseconds [100] - * - `max` max timeout [10000] - * - `jitter` [0] - * - `factor` [2] - * - * @param {Object} opts - * @api public - */ - -function Backoff(opts) { - opts = opts || {}; - this.ms = opts.min || 100; - this.max = opts.max || 10000; - this.factor = opts.factor || 2; - this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; - this.attempts = 0; -} - -/** - * Return the backoff duration. - * - * @return {Number} - * @api public - */ - -Backoff.prototype.duration = function(){ - var ms = this.ms * Math.pow(this.factor, this.attempts++); - if (this.jitter) { - var rand = Math.random(); - var deviation = Math.floor(rand * this.jitter * ms); - ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; - } - return Math.min(ms, this.max) | 0; -}; - -/** - * Reset the number of attempts. - * - * @api public - */ - -Backoff.prototype.reset = function(){ - this.attempts = 0; -}; - -/** - * Set the minimum duration - * - * @api public - */ - -Backoff.prototype.setMin = function(min){ - this.ms = min; -}; - -/** - * Set the maximum duration - * - * @api public - */ - -Backoff.prototype.setMax = function(max){ - this.max = max; -}; - -/** - * Set the jitter - * - * @api public - */ - -Backoff.prototype.setJitter = function(jitter){ - this.jitter = jitter; -}; - - -},{}],68:[function(require,module,exports){ -/* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ -(function(){ - "use strict"; - - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - // Use a lookup table to find the index. - var lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - - exports.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - exports.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i+1)]; - encoded3 = lookup[base64.charCodeAt(i+2)]; - encoded4 = lookup[base64.charCodeAt(i+3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; -})(); - -},{}],69:[function(require,module,exports){ -'use strict' - -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray - -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} - -// Support decoding URL-safe base64 strings, as Node.js does. -// See: https://en.wikipedia.org/wiki/Base64#URL_applications -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 - -function getLens (b64) { - var len = b64.length - - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len - - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) - - return [validLen, placeHoldersLen] -} - -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - - var curByte = 0 - - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen - - var i - for (i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } - - return parts.join('') -} - -},{}],70:[function(require,module,exports){ -/** - * Create a blob builder even when vendor prefixes exist - */ - -var BlobBuilder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : - typeof WebKitBlobBuilder !== 'undefined' ? WebKitBlobBuilder : - typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : - typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : - false; - -/** - * Check if Blob constructor is supported - */ - -var blobSupported = (function() { - try { - var a = new Blob(['hi']); - return a.size === 2; - } catch(e) { - return false; - } -})(); - -/** - * Check if Blob constructor supports ArrayBufferViews - * Fails in Safari 6, so we need to map to ArrayBuffers there. - */ - -var blobSupportsArrayBufferView = blobSupported && (function() { - try { - var b = new Blob([new Uint8Array([1,2])]); - return b.size === 2; - } catch(e) { - return false; - } -})(); - -/** - * Check if BlobBuilder is supported - */ - -var blobBuilderSupported = BlobBuilder - && BlobBuilder.prototype.append - && BlobBuilder.prototype.getBlob; - -/** - * Helper function that maps ArrayBufferViews to ArrayBuffers - * Used by BlobBuilder constructor and old browsers that didn't - * support it in the Blob constructor. - */ - -function mapArrayBufferViews(ary) { - return ary.map(function(chunk) { - if (chunk.buffer instanceof ArrayBuffer) { - var buf = chunk.buffer; - - // if this is a subarray, make a copy so we only - // include the subarray region from the underlying buffer - if (chunk.byteLength !== buf.byteLength) { - var copy = new Uint8Array(chunk.byteLength); - copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); - buf = copy.buffer; - } - - return buf; - } - - return chunk; - }); -} - -function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - mapArrayBufferViews(ary).forEach(function(part) { - bb.append(part); - }); - - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); -}; - -function BlobConstructor(ary, options) { - return new Blob(mapArrayBufferViews(ary), options || {}); -}; - -if (typeof Blob !== 'undefined') { - BlobBuilderConstructor.prototype = Blob.prototype; - BlobConstructor.prototype = Blob.prototype; -} - -module.exports = (function() { - if (blobSupported) { - return blobSupportsArrayBufferView ? Blob : BlobConstructor; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } -})(); - -},{}],71:[function(require,module,exports){ +},{"./der":72,"inherits":224}],75:[function(require,module,exports){ (function (module, exports) { 'use strict'; @@ -13514,7 +14076,13 @@ module.exports = (function() { } else if (cmp > 0) { r.isub(this.p); } else { - r.strip(); + if (r.strip !== undefined) { + // r is BN v4 instance + r.strip(); + } else { + // r is BN v5 instance + r._strip(); + } } return r; @@ -13968,8507 +14536,15652 @@ module.exports = (function() { }; })(typeof module === 'undefined' || module, this); -},{"buffer":73}],72:[function(require,module,exports){ -var r; - -module.exports = function rand(len) { - if (!r) - r = new Rand(null); - - return r.generate(len); -}; +},{"buffer":82}],76:[function(require,module,exports){ -function Rand(rand) { - this.rand = rand; -} -module.exports.Rand = Rand; +/** + * Expose `Backoff`. + */ -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; +module.exports = Backoff; -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); +/** + * Initialize backoff timer with `opts`. + * + * - `min` initial timeout in milliseconds [100] + * - `max` max timeout [10000] + * - `jitter` [0] + * - `factor` [2] + * + * @param {Object} opts + * @api public + */ - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; +function Backoff(opts) { + opts = opts || {}; + this.ms = opts.min || 100; + this.max = opts.max || 10000; + this.factor = opts.factor || 2; + this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; + this.attempts = 0; +} -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; +/** + * Return the backoff duration. + * + * @return {Number} + * @api public + */ - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; +Backoff.prototype.duration = function(){ + var ms = this.ms * Math.pow(this.factor, this.attempts++); + if (this.jitter) { + var rand = Math.random(); + var deviation = Math.floor(rand * this.jitter * ms); + ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto = require('crypto'); - if (typeof crypto.randomBytes !== 'function') - throw new Error('Not supported'); + return Math.min(ms, this.max) | 0; +}; - Rand.prototype._rand = function _rand(n) { - return crypto.randomBytes(n); - }; - } catch (e) { - } -} +/** + * Reset the number of attempts. + * + * @api public + */ -},{"crypto":73}],73:[function(require,module,exports){ +Backoff.prototype.reset = function(){ + this.attempts = 0; +}; -},{}],74:[function(require,module,exports){ -// based on the aes implimentation in triple sec -// https://github.com/keybase/triplesec -// which is in turn based on the one from crypto-js -// https://code.google.com/p/crypto-js/ +/** + * Set the minimum duration + * + * @api public + */ -var Buffer = require('safe-buffer').Buffer +Backoff.prototype.setMin = function(min){ + this.ms = min; +}; -function asUInt32Array (buf) { - if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) +/** + * Set the maximum duration + * + * @api public + */ - var len = (buf.length / 4) | 0 - var out = new Array(len) +Backoff.prototype.setMax = function(max){ + this.max = max; +}; - for (var i = 0; i < len; i++) { - out[i] = buf.readUInt32BE(i * 4) - } +/** + * Set the jitter + * + * @api public + */ - return out -} +Backoff.prototype.setJitter = function(jitter){ + this.jitter = jitter; +}; -function scrubVec (v) { - for (var i = 0; i < v.length; v++) { - v[i] = 0 - } -} -function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) { - var SUB_MIX0 = SUB_MIX[0] - var SUB_MIX1 = SUB_MIX[1] - var SUB_MIX2 = SUB_MIX[2] - var SUB_MIX3 = SUB_MIX[3] +},{}],77:[function(require,module,exports){ +/* + * base64-arraybuffer + * https://github.com/niklasvh/base64-arraybuffer + * + * Copyright (c) 2012 Niklas von Hertzen + * Licensed under the MIT license. + */ +(function(){ + "use strict"; - var s0 = M[0] ^ keySchedule[0] - var s1 = M[1] ^ keySchedule[1] - var s2 = M[2] ^ keySchedule[2] - var s3 = M[3] ^ keySchedule[3] - var t0, t1, t2, t3 - var ksRow = 4 + var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - for (var round = 1; round < nRounds; round++) { - t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++] - t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++] - t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++] - t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++] - s0 = t0 - s1 = t1 - s2 = t2 - s3 = t3 + // Use a lookup table to find the index. + var lookup = new Uint8Array(256); + for (var i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; } - t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] - t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] - t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] - t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] - t0 = t0 >>> 0 - t1 = t1 >>> 0 - t2 = t2 >>> 0 - t3 = t3 >>> 0 + exports.encode = function(arraybuffer) { + var bytes = new Uint8Array(arraybuffer), + i, len = bytes.length, base64 = ""; - return [t0, t1, t2, t3] -} + for (i = 0; i < len; i+=3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } -// AES constants -var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] -var G = (function () { - // Compute double table - var d = new Array(256) - for (var j = 0; j < 256; j++) { - if (j < 128) { - d[j] = j << 1 - } else { - d[j] = (j << 1) ^ 0x11b + if ((len % 3) === 2) { + base64 = base64.substring(0, base64.length - 1) + "="; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + "=="; } - } - var SBOX = [] - var INV_SBOX = [] - var SUB_MIX = [[], [], [], []] - var INV_SUB_MIX = [[], [], [], []] + return base64; + }; - // Walk GF(2^8) - var x = 0 - var xi = 0 - for (var i = 0; i < 256; ++i) { - // Compute sbox - var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) - sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63 - SBOX[x] = sx - INV_SBOX[sx] = x + exports.decode = function(base64) { + var bufferLength = base64.length * 0.75, + len = base64.length, i, p = 0, + encoded1, encoded2, encoded3, encoded4; - // Compute multiplication - var x2 = d[x] - var x4 = d[x2] - var x8 = d[x4] + if (base64[base64.length - 1] === "=") { + bufferLength--; + if (base64[base64.length - 2] === "=") { + bufferLength--; + } + } - // Compute sub bytes, mix columns tables - var t = (d[sx] * 0x101) ^ (sx * 0x1010100) - SUB_MIX[0][x] = (t << 24) | (t >>> 8) - SUB_MIX[1][x] = (t << 16) | (t >>> 16) - SUB_MIX[2][x] = (t << 8) | (t >>> 24) - SUB_MIX[3][x] = t + var arraybuffer = new ArrayBuffer(bufferLength), + bytes = new Uint8Array(arraybuffer); - // Compute inv sub bytes, inv mix columns tables - t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100) - INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) - INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) - INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) - INV_SUB_MIX[3][sx] = t + for (i = 0; i < len; i+=4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i+1)]; + encoded3 = lookup[base64.charCodeAt(i+2)]; + encoded4 = lookup[base64.charCodeAt(i+3)]; - if (x === 0) { - x = xi = 1 - } else { - x = x2 ^ d[d[d[x8 ^ x2]]] - xi ^= d[d[xi]] + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); } - } - return { - SBOX: SBOX, - INV_SBOX: INV_SBOX, - SUB_MIX: SUB_MIX, - INV_SUB_MIX: INV_SUB_MIX - } -})() + return arraybuffer; + }; +})(); -function AES (key) { - this._key = asUInt32Array(key) - this._reset() -} +},{}],78:[function(require,module,exports){ +'use strict' -AES.blockSize = 4 * 4 -AES.keySize = 256 / 8 -AES.prototype.blockSize = AES.blockSize -AES.prototype.keySize = AES.keySize -AES.prototype._reset = function () { - var keyWords = this._key - var keySize = keyWords.length - var nRounds = keySize + 6 - var ksRows = (nRounds + 1) * 4 +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray - var keySchedule = [] - for (var k = 0; k < keySize; k++) { - keySchedule[k] = keyWords[k] - } +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - for (k = keySize; k < ksRows; k++) { - var t = keySchedule[k - 1] +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} - if (k % keySize === 0) { - t = (t << 8) | (t >>> 24) - t = - (G.SBOX[t >>> 24] << 24) | - (G.SBOX[(t >>> 16) & 0xff] << 16) | - (G.SBOX[(t >>> 8) & 0xff] << 8) | - (G.SBOX[t & 0xff]) +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 - t ^= RCON[(k / keySize) | 0] << 24 - } else if (keySize > 6 && k % keySize === 4) { - t = - (G.SBOX[t >>> 24] << 24) | - (G.SBOX[(t >>> 16) & 0xff] << 16) | - (G.SBOX[(t >>> 8) & 0xff] << 8) | - (G.SBOX[t & 0xff]) - } +function getLens (b64) { + var len = b64.length - keySchedule[k] = keySchedule[k - keySize] ^ t + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') } - var invKeySchedule = [] - for (var ik = 0; ik < ksRows; ik++) { - var ksR = ksRows - ik - var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)] + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len - if (ik < 4 || ksR <= 4) { - invKeySchedule[ik] = tt - } else { - invKeySchedule[ik] = - G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^ - G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^ - G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^ - G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]] - } - } + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) - this._nRounds = nRounds - this._keySchedule = keySchedule - this._invKeySchedule = invKeySchedule + return [validLen, placeHoldersLen] } -AES.prototype.encryptBlockRaw = function (M) { - M = asUInt32Array(M) - return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds) +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } -AES.prototype.encryptBlock = function (M) { - var out = this.encryptBlockRaw(M) - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0], 0) - buf.writeUInt32BE(out[1], 4) - buf.writeUInt32BE(out[2], 8) - buf.writeUInt32BE(out[3], 12) - return buf +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } -AES.prototype.decryptBlock = function (M) { - M = asUInt32Array(M) - - // swap - var m1 = M[1] - M[1] = M[3] - M[3] = m1 +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] - var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds) - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0], 0) - buf.writeUInt32BE(out[3], 4) - buf.writeUInt32BE(out[2], 8) - buf.writeUInt32BE(out[1], 12) - return buf -} + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) -AES.prototype.scrub = function () { - scrubVec(this._keySchedule) - scrubVec(this._invKeySchedule) - scrubVec(this._key) -} + var curByte = 0 -module.exports.AES = AES + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen -},{"safe-buffer":222}],75:[function(require,module,exports){ -var aes = require('./aes') -var Buffer = require('safe-buffer').Buffer -var Transform = require('cipher-base') -var inherits = require('inherits') -var GHASH = require('./ghash') -var xor = require('buffer-xor') -var incr32 = require('./incr32') + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } -function xorTest (a, b) { - var out = 0 - if (a.length !== b.length) out++ + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } - var len = Math.min(a.length, b.length) - for (var i = 0; i < len; ++i) { - out += (a[i] ^ b[i]) + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF } - return out + return arr } -function calcIv (self, iv, ck) { - if (iv.length === 12) { - self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) - return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])]) - } - var ghash = new GHASH(ck) - var len = iv.length - var toPad = len % 16 - ghash.update(iv) - if (toPad) { - toPad = 16 - toPad - ghash.update(Buffer.alloc(toPad, 0)) +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) } - ghash.update(Buffer.alloc(8, 0)) - var ivBits = len * 8 - var tail = Buffer.alloc(8) - tail.writeUIntBE(ivBits, 0, 8) - ghash.update(tail) - self._finID = ghash.state - var out = Buffer.from(self._finID) - incr32(out) - return out + return output.join('') } -function StreamCipher (mode, key, iv, decrypt) { - Transform.call(this) - var h = Buffer.alloc(4, 0) +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 - this._cipher = new aes.AES(key) - var ck = this._cipher.encryptBlock(h) - this._ghash = new GHASH(ck) - iv = calcIv(this, iv, ck) + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } - this._prev = Buffer.from(iv) - this._cache = Buffer.allocUnsafe(0) - this._secCache = Buffer.allocUnsafe(0) - this._decrypt = decrypt - this._alen = 0 - this._len = 0 - this._mode = mode + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } - this._authTag = null - this._called = false + return parts.join('') } -inherits(StreamCipher, Transform) +},{}],79:[function(require,module,exports){ +/** + * Create a blob builder even when vendor prefixes exist + */ + +var BlobBuilder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : + typeof WebKitBlobBuilder !== 'undefined' ? WebKitBlobBuilder : + typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : + typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : + false; + +/** + * Check if Blob constructor is supported + */ + +var blobSupported = (function() { + try { + var a = new Blob(['hi']); + return a.size === 2; + } catch(e) { + return false; + } +})(); + +/** + * Check if Blob constructor supports ArrayBufferViews + * Fails in Safari 6, so we need to map to ArrayBuffers there. + */ + +var blobSupportsArrayBufferView = blobSupported && (function() { + try { + var b = new Blob([new Uint8Array([1,2])]); + return b.size === 2; + } catch(e) { + return false; + } +})(); + +/** + * Check if BlobBuilder is supported + */ + +var blobBuilderSupported = BlobBuilder + && BlobBuilder.prototype.append + && BlobBuilder.prototype.getBlob; + +/** + * Helper function that maps ArrayBufferViews to ArrayBuffers + * Used by BlobBuilder constructor and old browsers that didn't + * support it in the Blob constructor. + */ + +function mapArrayBufferViews(ary) { + return ary.map(function(chunk) { + if (chunk.buffer instanceof ArrayBuffer) { + var buf = chunk.buffer; + + // if this is a subarray, make a copy so we only + // include the subarray region from the underlying buffer + if (chunk.byteLength !== buf.byteLength) { + var copy = new Uint8Array(chunk.byteLength); + copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); + buf = copy.buffer; + } + + return buf; + } + + return chunk; + }); +} + +function BlobBuilderConstructor(ary, options) { + options = options || {}; + + var bb = new BlobBuilder(); + mapArrayBufferViews(ary).forEach(function(part) { + bb.append(part); + }); + + return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); +}; + +function BlobConstructor(ary, options) { + return new Blob(mapArrayBufferViews(ary), options || {}); +}; + +if (typeof Blob !== 'undefined') { + BlobBuilderConstructor.prototype = Blob.prototype; + BlobConstructor.prototype = Blob.prototype; +} + +module.exports = (function() { + if (blobSupported) { + return blobSupportsArrayBufferView ? Blob : BlobConstructor; + } else if (blobBuilderSupported) { + return BlobBuilderConstructor; + } else { + return undefined; + } +})(); -StreamCipher.prototype._update = function (chunk) { - if (!this._called && this._alen) { - var rump = 16 - (this._alen % 16) - if (rump < 16) { - rump = Buffer.alloc(rump, 0) - this._ghash.update(rump) - } - } +},{}],80:[function(require,module,exports){ +(function (module, exports) { + 'use strict'; - this._called = true - var out = this._mode.encrypt(this, chunk) - if (this._decrypt) { - this._ghash.update(chunk) - } else { - this._ghash.update(out) + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); } - this._len += chunk.length - return out -} -StreamCipher.prototype._final = function () { - if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } - var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) - if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') + // BN - this._authTag = tag - this._cipher.scrub() -} + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } -StreamCipher.prototype.getAuthTag = function getAuthTag () { - if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') + this.negative = 0; + this.words = null; + this.length = 0; - return this._authTag -} + // Reduction context + this.red = null; -StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { - if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } - this._authTag = tag -} + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } -StreamCipher.prototype.setAAD = function setAAD (buf) { - if (this._called) throw new Error('Attempting to set AAD in unsupported state') + BN.BN = BN; + BN.wordSize = 26; - this._ghash.update(buf) - this._alen += buf.length -} + var Buffer; + try { + Buffer = require('buffer').Buffer; + } catch (e) { + } -module.exports = StreamCipher + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } -},{"./aes":74,"./ghash":79,"./incr32":80,"buffer-xor":101,"cipher-base":103,"inherits":175,"safe-buffer":222}],76:[function(require,module,exports){ -var ciphers = require('./encrypter') -var deciphers = require('./decrypter') -var modes = require('./modes/list.json') + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; -function getCiphers () { - return Object.keys(modes) -} + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; -exports.createCipher = exports.Cipher = ciphers.createCipher -exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv -exports.createDecipher = exports.Decipher = deciphers.createDecipher -exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv -exports.listCiphers = exports.getCiphers = getCiphers + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; -},{"./decrypter":77,"./encrypter":78,"./modes/list.json":88}],77:[function(require,module,exports){ -var AuthCipher = require('./authCipher') -var Buffer = require('safe-buffer').Buffer -var MODES = require('./modes') -var StreamCipher = require('./streamCipher') -var Transform = require('cipher-base') -var aes = require('./aes') -var ebtk = require('evp_bytestokey') -var inherits = require('inherits') + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } -function Decipher (mode, key, iv) { - Transform.call(this) + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } - this._cache = new Splitter() - this._last = void 0 - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._mode = mode - this._autopadding = true -} + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); -inherits(Decipher, Transform) + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } -Decipher.prototype._update = function (data) { - this._cache.add(data) - var chunk - var thing - var out = [] - while ((chunk = this._cache.get(this._autopadding))) { - thing = this._mode.decrypt(this, chunk) - out.push(thing) - } - return Buffer.concat(out) -} + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } -Decipher.prototype._final = function () { - var chunk = this._cache.flush() - if (this._autopadding) { - return unpad(this._mode.decrypt(this, chunk)) - } else if (chunk) { - throw new Error('data not multiple of block length') - } -} + if (number[0] === '-') { + this.negative = 1; + } -Decipher.prototype.setAutoPadding = function (setTo) { - this._autopadding = !!setTo - return this -} + this._strip(); -function Splitter () { - this.cache = Buffer.allocUnsafe(0) -} + if (endian !== 'le') return; -Splitter.prototype.add = function (data) { - this.cache = Buffer.concat([this.cache, data]) -} + this._initArray(this.toArray(), base, endian); + }; -Splitter.prototype.get = function (autoPadding) { - var out - if (autoPadding) { - if (this.cache.length > 16) { - out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; } - } else { - if (this.cache.length >= 16) { - out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out + if (number < 0x4000000) { + this.words = [number & 0x3ffffff]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; } - } - return null -} + if (endian !== 'le') return; -Splitter.prototype.flush = function () { - if (this.cache.length) return this.cache -} + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; -function unpad (last) { - var padded = last[15] - if (padded < 1 || padded > 16) { - throw new Error('unable to decrypt data') - } - var i = -1 - while (++i < padded) { - if (last[(i + (16 - padded))] !== padded) { - throw new Error('unable to decrypt data') + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [0]; + this.length = 1; + return this; } - } - if (padded === 16) return - return last.slice(0, 16 - padded) -} + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } -function createDecipheriv (suite, password, iv) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this._strip(); + }; - if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + var z = 0; + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; - if (typeof password === 'string') password = Buffer.from(password) - if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) + r <<= 4; - if (config.type === 'stream') { - return new StreamCipher(config.module, password, iv, true) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv, true) - } + var b; - return new Decipher(config.module, password, iv) -} + // 'a' - 'f' + if (c >= 49 && c <= 54) { + b = c - 49 + 0xa; -function createDecipher (suite, password) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + b = c - 17 + 0xa; - var keys = ebtk(password, false, config.key, config.iv) - return createDecipheriv(suite, keys.key, keys.iv) -} + // '0' - '9' + } else { + b = c; + } -exports.createDecipher = createDecipher -exports.createDecipheriv = createDecipheriv + r |= b; + z |= b; + } -},{"./aes":74,"./authCipher":75,"./modes":87,"./streamCipher":90,"cipher-base":103,"evp_bytestokey":156,"inherits":175,"safe-buffer":222}],78:[function(require,module,exports){ -var MODES = require('./modes') -var AuthCipher = require('./authCipher') -var Buffer = require('safe-buffer').Buffer -var StreamCipher = require('./streamCipher') -var Transform = require('cipher-base') -var aes = require('./aes') -var ebtk = require('evp_bytestokey') -var inherits = require('inherits') + assert(!(z & 0xf0), 'Invalid character in ' + str); + return r; + } -function Cipher (mode, key, iv) { - Transform.call(this) + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } - this._cache = new Splitter() - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._mode = mode - this._autopadding = true -} + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this._strip(); + }; -inherits(Cipher, Transform) + function parseBase (str, start, end, mul) { + var r = 0; + var b = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; -Cipher.prototype._update = function (data) { - this._cache.add(data) - var chunk - var thing - var out = [] + r *= mul; - while ((chunk = this._cache.get())) { - thing = this._mode.encrypt(this, chunk) - out.push(thing) - } + // 'a' + if (c >= 49) { + b = c - 49 + 0xa; - return Buffer.concat(out) -} + // 'A' + } else if (c >= 17) { + b = c - 17 + 0xa; -var PADDING = Buffer.alloc(16, 0x10) + // '0' - '9' + } else { + b = c; + } + assert(c >= 0 && b < mul, 'Invalid character'); + r += b; + } + return r; + } -Cipher.prototype._final = function () { - var chunk = this._cache.flush() - if (this._autopadding) { - chunk = this._mode.encrypt(this, chunk) - this._cipher.scrub() - return chunk - } - - if (!chunk.equals(PADDING)) { - this._cipher.scrub() - throw new Error('data not multiple of block length') - } -} - -Cipher.prototype.setAutoPadding = function (setTo) { - this._autopadding = !!setTo - return this -} - -function Splitter () { - this.cache = Buffer.allocUnsafe(0) -} + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [0]; + this.length = 1; -Splitter.prototype.add = function (data) { - this.cache = Buffer.concat([this.cache, data]) -} + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; -Splitter.prototype.get = function () { - if (this.cache.length > 15) { - var out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out - } - return null -} + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; -Splitter.prototype.flush = function () { - var len = 16 - this.cache.length - var padBuff = Buffer.allocUnsafe(len) + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); - var i = -1 - while (++i < len) { - padBuff.writeUInt8(len, i) - } + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } - return Buffer.concat([this.cache, padBuff]) -} + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); -function createCipheriv (suite, password, iv) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + for (i = 0; i < mod; i++) { + pow *= base; + } - if (typeof password === 'string') password = Buffer.from(password) - if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; - if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; - if (config.type === 'stream') { - return new StreamCipher(config.module, password, iv) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv) + function move (dest, src) { + dest.words = src.words; + dest.length = src.length; + dest.negative = src.negative; + dest.red = src.red; } - return new Cipher(config.module, password, iv) -} - -function createCipher (suite, password) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') - - var keys = ebtk(password, false, config.key, config.iv) - return createCipheriv(suite, keys.key, keys.iv) -} - -exports.createCipheriv = createCipheriv -exports.createCipher = createCipher - -},{"./aes":74,"./authCipher":75,"./modes":87,"./streamCipher":90,"cipher-base":103,"evp_bytestokey":156,"inherits":175,"safe-buffer":222}],79:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var ZEROES = Buffer.alloc(16, 0) - -function toArray (buf) { - return [ - buf.readUInt32BE(0), - buf.readUInt32BE(4), - buf.readUInt32BE(8), - buf.readUInt32BE(12) - ] -} - -function fromArray (out) { - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0] >>> 0, 0) - buf.writeUInt32BE(out[1] >>> 0, 4) - buf.writeUInt32BE(out[2] >>> 0, 8) - buf.writeUInt32BE(out[3] >>> 0, 12) - return buf -} - -function GHASH (key) { - this.h = key - this.state = Buffer.alloc(16, 0) - this.cache = Buffer.allocUnsafe(0) -} + BN.prototype._move = function _move (dest) { + move(dest, this); + }; -// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html -// by Juho Vähä-Herttua -GHASH.prototype.ghash = function (block) { - var i = -1 - while (++i < block.length) { - this.state[i] ^= block[i] - } - this._multiply() -} + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; -GHASH.prototype._multiply = function () { - var Vi = toArray(this.h) - var Zi = [0, 0, 0, 0] - var j, xi, lsbVi - var i = -1 - while (++i < 128) { - xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0 - if (xi) { - // Z_i+1 = Z_i ^ V_i - Zi[0] ^= Vi[0] - Zi[1] ^= Vi[1] - Zi[2] ^= Vi[2] - Zi[3] ^= Vi[3] + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; } + return this; + }; - // Store the value of LSB(V_i) - lsbVi = (Vi[3] & 1) !== 0 - - // V_i+1 = V_i >> 1 - for (j = 3; j > 0; j--) { - Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31) + // Remove leading `0` from `this` + BN.prototype._strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; } - Vi[0] = Vi[0] >>> 1 + return this._normSign(); + }; - // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R - if (lsbVi) { - Vi[0] = Vi[0] ^ (0xe1 << 24) + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; } - } - this.state = fromArray(Zi) -} + return this; + }; -GHASH.prototype.update = function (buf) { - this.cache = Buffer.concat([this.cache, buf]) - var chunk - while (this.cache.length >= 16) { - chunk = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - this.ghash(chunk) + // Check Symbol.for because not everywhere where Symbol defined + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility + if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') { + BN.prototype[Symbol.for('nodejs.util.inspect.custom')] = inspect; + } else { + BN.prototype.inspect = inspect; } -} -GHASH.prototype.final = function (abl, bl) { - if (this.cache.length) { - this.ghash(Buffer.concat([this.cache, ZEROES], 16)) + function inspect () { + return (this.red ? ''; } - this.ghash(fromArray([0, abl, 0, bl])) - return this.state -} + /* -module.exports = GHASH + var zeros = []; + var groupSizes = []; + var groupBases = []; -},{"safe-buffer":222}],80:[function(require,module,exports){ -function incr32 (iv) { - var len = iv.length - var item - while (len--) { - item = iv.readUInt8(len) - if (item === 255) { - iv.writeUInt8(0, len) - } else { - item++ - iv.writeUInt8(item, len) - break + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; } -} -module.exports = incr32 -},{}],81:[function(require,module,exports){ -var xor = require('buffer-xor') + */ -exports.encrypt = function (self, block) { - var data = xor(block, self._prev) + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; - self._prev = self._cipher.encryptBlock(data) - return self._prev -} + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; -exports.decrypt = function (self, block) { - var pad = self._prev + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; - self._prev = block - var out = self._cipher.decryptBlock(block) + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; - return xor(out, pad) -} + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } -},{"buffer-xor":101}],82:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var xor = require('buffer-xor') + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modrn(groupBase).toString(base); + c = c.idivn(groupBase); -function encryptStart (self, data, decrypt) { - var len = data.length - var out = xor(data, self._cache) - self._cache = self._cache.slice(len) - self._prev = Buffer.concat([self._prev, decrypt ? data : out]) - return out -} + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } -exports.encrypt = function (self, data, decrypt) { - var out = Buffer.allocUnsafe(0) - var len + assert(false, 'Base should be between 2 and 36'); + }; - while (data.length) { - if (self._cache.length === 0) { - self._cache = self._cipher.encryptBlock(self._prev) - self._prev = Buffer.allocUnsafe(0) + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); } + return (this.negative !== 0) ? -ret : ret; + }; - if (self._cache.length <= data.length) { - len = self._cache.length - out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)]) - data = data.slice(len) - } else { - out = Buffer.concat([out, encryptStart(self, data, decrypt)]) - break - } - } + BN.prototype.toJSON = function toJSON () { + return this.toString(16, 2); + }; - return out -} + if (Buffer) { + BN.prototype.toBuffer = function toBuffer (endian, length) { + return this.toArrayLike(Buffer, endian, length); + }; + } -},{"buffer-xor":101,"safe-buffer":222}],83:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; -function encryptByte (self, byteParam, decrypt) { - var pad - var i = -1 - var len = 8 - var out = 0 - var bit, value - while (++i < len) { - pad = self._cipher.encryptBlock(self._prev) - bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0 - value = pad[0] ^ bit - out += ((value & 0x80) >> (i % 8)) - self._prev = shiftIn(self._prev, decrypt ? bit : value) - } - return out -} + var allocate = function allocate (ArrayType, size) { + if (ArrayType.allocUnsafe) { + return ArrayType.allocUnsafe(size); + } + return new ArrayType(size); + }; -function shiftIn (buffer, value) { - var len = buffer.length - var i = -1 - var out = Buffer.allocUnsafe(buffer.length) - buffer = Buffer.concat([buffer, Buffer.from([value])]) + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + this._strip(); - while (++i < len) { - out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) - } + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); - return out -} + var res = allocate(ArrayType, reqLength); + var postfix = endian === 'le' ? 'LE' : 'BE'; + this['_toArrayLike' + postfix](res, byteLength); + return res; + }; -exports.encrypt = function (self, chunk, decrypt) { - var len = chunk.length - var out = Buffer.allocUnsafe(len) - var i = -1 + BN.prototype._toArrayLikeLE = function _toArrayLikeLE (res, byteLength) { + var position = 0; + var carry = 0; - while (++i < len) { - out[i] = encryptByte(self, chunk[i], decrypt) - } + for (var i = 0, shift = 0; i < this.length; i++) { + var word = (this.words[i] << shift) | carry; - return out -} + res[position++] = word & 0xff; + if (position < res.length) { + res[position++] = (word >> 8) & 0xff; + } + if (position < res.length) { + res[position++] = (word >> 16) & 0xff; + } -},{"safe-buffer":222}],84:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer + if (shift === 6) { + if (position < res.length) { + res[position++] = (word >> 24) & 0xff; + } + carry = 0; + shift = 0; + } else { + carry = word >>> 24; + shift += 2; + } + } -function encryptByte (self, byteParam, decrypt) { - var pad = self._cipher.encryptBlock(self._prev) - var out = pad[0] ^ byteParam + if (position < res.length) { + res[position++] = carry; - self._prev = Buffer.concat([ - self._prev.slice(1), - Buffer.from([decrypt ? byteParam : out]) - ]) + while (position < res.length) { + res[position++] = 0; + } + } + }; - return out -} + BN.prototype._toArrayLikeBE = function _toArrayLikeBE (res, byteLength) { + var position = res.length - 1; + var carry = 0; -exports.encrypt = function (self, chunk, decrypt) { - var len = chunk.length - var out = Buffer.allocUnsafe(len) - var i = -1 + for (var i = 0, shift = 0; i < this.length; i++) { + var word = (this.words[i] << shift) | carry; - while (++i < len) { - out[i] = encryptByte(self, chunk[i], decrypt) - } + res[position--] = word & 0xff; + if (position >= 0) { + res[position--] = (word >> 8) & 0xff; + } + if (position >= 0) { + res[position--] = (word >> 16) & 0xff; + } - return out -} + if (shift === 6) { + if (position >= 0) { + res[position--] = (word >> 24) & 0xff; + } + carry = 0; + shift = 0; + } else { + carry = word >>> 24; + shift += 2; + } + } -},{"safe-buffer":222}],85:[function(require,module,exports){ -var xor = require('buffer-xor') -var Buffer = require('safe-buffer').Buffer -var incr32 = require('../incr32') + if (position >= 0) { + res[position--] = carry; -function getBlock (self) { - var out = self._cipher.encryptBlockRaw(self._prev) - incr32(self._prev) - return out -} + while (position >= 0) { + res[position--] = 0; + } + } + }; -var blockSize = 16 -exports.encrypt = function (self, chunk) { - var chunkNum = Math.ceil(chunk.length / blockSize) - var start = self._cache.length - self._cache = Buffer.concat([ - self._cache, - Buffer.allocUnsafe(chunkNum * blockSize) - ]) - for (var i = 0; i < chunkNum; i++) { - var out = getBlock(self) - var offset = start + i * blockSize - self._cache.writeUInt32BE(out[0], offset + 0) - self._cache.writeUInt32BE(out[1], offset + 4) - self._cache.writeUInt32BE(out[2], offset + 8) - self._cache.writeUInt32BE(out[3], offset + 12) + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; } - var pad = self._cache.slice(0, chunk.length) - self._cache = self._cache.slice(chunk.length) - return xor(chunk, pad) -} -},{"../incr32":80,"buffer-xor":101,"safe-buffer":222}],86:[function(require,module,exports){ -exports.encrypt = function (self, block) { - return self._cipher.encryptBlock(block) -} + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; -exports.decrypt = function (self, block) { - return self._cipher.decryptBlock(block) -} + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; -},{}],87:[function(require,module,exports){ -var modeModules = { - ECB: require('./ecb'), - CBC: require('./cbc'), - CFB: require('./cfb'), - CFB8: require('./cfb8'), - CFB1: require('./cfb1'), - OFB: require('./ofb'), - CTR: require('./ctr'), - GCM: require('./ctr') -} + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; -var modes = require('./list.json') + function toBitArray (num) { + var w = new Array(num.bitLength()); -for (var key in modes) { - modes[key].module = modeModules[modes[key].mode] -} + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; -module.exports = modes + w[bit] = (num.words[off] >>> wbit) & 0x01; + } -},{"./cbc":81,"./cfb":82,"./cfb1":83,"./cfb8":84,"./ctr":85,"./ecb":86,"./list.json":88,"./ofb":89}],88:[function(require,module,exports){ -module.exports={ - "aes-128-ecb": { - "cipher": "AES", - "key": 128, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-192-ecb": { - "cipher": "AES", - "key": 192, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-256-ecb": { - "cipher": "AES", - "key": 256, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-128-cbc": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-192-cbc": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-256-cbc": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes128": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes192": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes256": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-128-cfb": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-192-cfb": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-256-cfb": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-128-cfb8": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-192-cfb8": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-256-cfb8": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-128-cfb1": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-192-cfb1": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-256-cfb1": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-128-ofb": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-192-ofb": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-256-ofb": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-128-ctr": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-192-ctr": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-256-ctr": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-128-gcm": { - "cipher": "AES", - "key": 128, - "iv": 12, - "mode": "GCM", - "type": "auth" - }, - "aes-192-gcm": { - "cipher": "AES", - "key": 192, - "iv": 12, - "mode": "GCM", - "type": "auth" - }, - "aes-256-gcm": { - "cipher": "AES", - "key": 256, - "iv": 12, - "mode": "GCM", - "type": "auth" + return w; } -} -},{}],89:[function(require,module,exports){ -(function (Buffer){ -var xor = require('buffer-xor') + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; -function getBlock (self) { - self._prev = self._cipher.encryptBlock(self._prev) - return self._prev -} + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; -exports.encrypt = function (self, chunk) { - while (self._cache.length < chunk.length) { - self._cache = Buffer.concat([self._cache, getBlock(self)]) - } + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; - var pad = self._cache.slice(0, chunk.length) - self._cache = self._cache.slice(chunk.length) - return xor(chunk, pad) -} + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; -}).call(this,require("buffer").Buffer) + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; -},{"buffer":102,"buffer-xor":101}],90:[function(require,module,exports){ -var aes = require('./aes') -var Buffer = require('safe-buffer').Buffer -var Transform = require('cipher-base') -var inherits = require('inherits') + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; -function StreamCipher (mode, key, iv, decrypt) { - Transform.call(this) + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._cache = Buffer.allocUnsafe(0) - this._secCache = Buffer.allocUnsafe(0) - this._decrypt = decrypt - this._mode = mode -} + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } -inherits(StreamCipher, Transform) + return this; + }; -StreamCipher.prototype._update = function (chunk) { - return this._mode.encrypt(this, chunk, this._decrypt) -} + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } -StreamCipher.prototype._final = function () { - this._cipher.scrub() -} + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } -module.exports = StreamCipher + return this._strip(); + }; -},{"./aes":74,"cipher-base":103,"inherits":175,"safe-buffer":222}],91:[function(require,module,exports){ -var DES = require('browserify-des') -var aes = require('browserify-aes/browser') -var aesModes = require('browserify-aes/modes') -var desModes = require('browserify-des/modes') -var ebtk = require('evp_bytestokey') + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; -function createCipher (suite, password) { - suite = suite.toLowerCase() + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; - var keyLen, ivLen - if (aesModes[suite]) { - keyLen = aesModes[suite].key - ivLen = aesModes[suite].iv - } else if (desModes[suite]) { - keyLen = desModes[suite].key * 8 - ivLen = desModes[suite].iv - } else { - throw new TypeError('invalid suite type') - } + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; - var keys = ebtk(password, false, keyLen, ivLen) - return createCipheriv(suite, keys.key, keys.iv) -} + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } -function createDecipher (suite, password) { - suite = suite.toLowerCase() + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } - var keyLen, ivLen - if (aesModes[suite]) { - keyLen = aesModes[suite].key - ivLen = aesModes[suite].iv - } else if (desModes[suite]) { - keyLen = desModes[suite].key * 8 - ivLen = desModes[suite].iv - } else { - throw new TypeError('invalid suite type') - } + this.length = b.length; - var keys = ebtk(password, false, keyLen, ivLen) - return createDecipheriv(suite, keys.key, keys.iv) -} + return this._strip(); + }; -function createCipheriv (suite, key, iv) { - suite = suite.toLowerCase() - if (aesModes[suite]) return aes.createCipheriv(suite, key, iv) - if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite }) + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; - throw new TypeError('invalid suite type') -} + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; -function createDecipheriv (suite, key, iv) { - suite = suite.toLowerCase() - if (aesModes[suite]) return aes.createDecipheriv(suite, key, iv) - if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite, decrypt: true }) + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; - throw new TypeError('invalid suite type') -} + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } -function getCiphers () { - return Object.keys(desModes).concat(aes.getCiphers()) -} + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } -exports.createCipher = exports.Cipher = createCipher -exports.createCipheriv = exports.Cipheriv = createCipheriv -exports.createDecipher = exports.Decipher = createDecipher -exports.createDecipheriv = exports.Decipheriv = createDecipheriv -exports.listCiphers = exports.getCiphers = getCiphers + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } -},{"browserify-aes/browser":76,"browserify-aes/modes":87,"browserify-des":92,"browserify-des/modes":93,"evp_bytestokey":156}],92:[function(require,module,exports){ -var CipherBase = require('cipher-base') -var des = require('des.js') -var inherits = require('inherits') -var Buffer = require('safe-buffer').Buffer + this.length = a.length; -var modes = { - 'des-ede3-cbc': des.CBC.instantiate(des.EDE), - 'des-ede3': des.EDE, - 'des-ede-cbc': des.CBC.instantiate(des.EDE), - 'des-ede': des.EDE, - 'des-cbc': des.CBC.instantiate(des.DES), - 'des-ecb': des.DES -} -modes.des = modes['des-cbc'] -modes.des3 = modes['des-ede3-cbc'] -module.exports = DES -inherits(DES, CipherBase) -function DES (opts) { - CipherBase.call(this) - var modeName = opts.mode.toLowerCase() - var mode = modes[modeName] - var type - if (opts.decrypt) { - type = 'decrypt' - } else { - type = 'encrypt' - } - var key = opts.key - if (!Buffer.isBuffer(key)) { - key = Buffer.from(key) - } - if (modeName === 'des-ede' || modeName === 'des-ede-cbc') { - key = Buffer.concat([key, key.slice(0, 8)]) - } - var iv = opts.iv - if (!Buffer.isBuffer(iv)) { - iv = Buffer.from(iv) - } - this._des = mode.create({ - key: key, - iv: iv, - type: type - }) -} -DES.prototype._update = function (data) { - return Buffer.from(this._des.update(data)) -} -DES.prototype._final = function () { - return Buffer.from(this._des.final()) -} - -},{"cipher-base":103,"des.js":114,"inherits":175,"safe-buffer":222}],93:[function(require,module,exports){ -exports['des-ecb'] = { - key: 8, - iv: 0 -} -exports['des-cbc'] = exports.des = { - key: 8, - iv: 8 -} -exports['des-ede3-cbc'] = exports.des3 = { - key: 24, - iv: 8 -} -exports['des-ede3'] = { - key: 24, - iv: 0 -} -exports['des-ede-cbc'] = { - key: 16, - iv: 8 -} -exports['des-ede'] = { - key: 16, - iv: 0 -} + return this._strip(); + }; -},{}],94:[function(require,module,exports){ -(function (Buffer){ -var bn = require('bn.js'); -var randomBytes = require('randombytes'); -module.exports = crt; -function blind(priv) { - var r = getr(priv); - var blinder = r.toRed(bn.mont(priv.modulus)) - .redPow(new bn(priv.publicExponent)).fromRed(); - return { - blinder: blinder, - unblinder:r.invm(priv.modulus) + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); }; -} -function crt(msg, priv) { - var blinds = blind(priv); - var len = priv.modulus.byteLength(); - var mod = bn.mont(priv.modulus); - var blinded = new bn(msg).mul(blinds.blinder).umod(priv.modulus); - var c1 = blinded.toRed(bn.mont(priv.prime1)); - var c2 = blinded.toRed(bn.mont(priv.prime2)); - var qinv = priv.coefficient; - var p = priv.prime1; - var q = priv.prime2; - var m1 = c1.redPow(priv.exponent1); - var m2 = c2.redPow(priv.exponent2); - m1 = m1.fromRed(); - m2 = m2.fromRed(); - var h = m1.isub(m2).imul(qinv).umod(p); - h.imul(q); - m2.iadd(h); - return new Buffer(m2.imul(blinds.unblinder).umod(priv.modulus).toArray(false, len)); -} -crt.getr = getr; -function getr(priv) { - var len = priv.modulus.byteLength(); - var r = new bn(randomBytes(len)); - while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) { - r = new bn(randomBytes(len)); - } - return r; -} -}).call(this,require("buffer").Buffer) + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; -},{"bn.js":71,"buffer":102,"randombytes":205}],95:[function(require,module,exports){ -module.exports = require('./browser/algorithms.json') + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; -},{"./browser/algorithms.json":96}],96:[function(require,module,exports){ -module.exports={ - "sha224WithRSAEncryption": { - "sign": "rsa", - "hash": "sha224", - "id": "302d300d06096086480165030402040500041c" - }, - "RSA-SHA224": { - "sign": "ecdsa/rsa", - "hash": "sha224", - "id": "302d300d06096086480165030402040500041c" - }, - "sha256WithRSAEncryption": { - "sign": "rsa", - "hash": "sha256", - "id": "3031300d060960864801650304020105000420" - }, - "RSA-SHA256": { - "sign": "ecdsa/rsa", - "hash": "sha256", - "id": "3031300d060960864801650304020105000420" - }, - "sha384WithRSAEncryption": { - "sign": "rsa", - "hash": "sha384", - "id": "3041300d060960864801650304020205000430" - }, - "RSA-SHA384": { - "sign": "ecdsa/rsa", - "hash": "sha384", - "id": "3041300d060960864801650304020205000430" - }, - "sha512WithRSAEncryption": { - "sign": "rsa", - "hash": "sha512", - "id": "3051300d060960864801650304020305000440" - }, - "RSA-SHA512": { - "sign": "ecdsa/rsa", - "hash": "sha512", - "id": "3051300d060960864801650304020305000440" - }, - "RSA-SHA1": { - "sign": "rsa", - "hash": "sha1", - "id": "3021300906052b0e03021a05000414" - }, - "ecdsa-with-SHA1": { - "sign": "ecdsa", - "hash": "sha1", - "id": "" - }, - "sha256": { - "sign": "ecdsa", - "hash": "sha256", - "id": "" - }, - "sha224": { - "sign": "ecdsa", - "hash": "sha224", - "id": "" - }, - "sha384": { - "sign": "ecdsa", - "hash": "sha384", - "id": "" - }, - "sha512": { - "sign": "ecdsa", - "hash": "sha512", - "id": "" - }, - "DSA-SHA": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA-SHA1": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA-WITH-SHA224": { - "sign": "dsa", - "hash": "sha224", - "id": "" - }, - "DSA-SHA224": { - "sign": "dsa", - "hash": "sha224", - "id": "" - }, - "DSA-WITH-SHA256": { - "sign": "dsa", - "hash": "sha256", - "id": "" - }, - "DSA-SHA256": { - "sign": "dsa", - "hash": "sha256", - "id": "" - }, - "DSA-WITH-SHA384": { - "sign": "dsa", - "hash": "sha384", - "id": "" - }, - "DSA-SHA384": { - "sign": "dsa", - "hash": "sha384", - "id": "" - }, - "DSA-WITH-SHA512": { - "sign": "dsa", - "hash": "sha512", - "id": "" - }, - "DSA-SHA512": { - "sign": "dsa", - "hash": "sha512", - "id": "" - }, - "DSA-RIPEMD160": { - "sign": "dsa", - "hash": "rmd160", - "id": "" - }, - "ripemd160WithRSA": { - "sign": "rsa", - "hash": "rmd160", - "id": "3021300906052b2403020105000414" - }, - "RSA-RIPEMD160": { - "sign": "rsa", - "hash": "rmd160", - "id": "3021300906052b2403020105000414" - }, - "md5WithRSAEncryption": { - "sign": "rsa", - "hash": "md5", - "id": "3020300c06082a864886f70d020505000410" - }, - "RSA-MD5": { - "sign": "rsa", - "hash": "md5", - "id": "3020300c06082a864886f70d020505000410" - } -} + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); -},{}],97:[function(require,module,exports){ -module.exports={ - "1.3.132.0.10": "secp256k1", - "1.3.132.0.33": "p224", - "1.2.840.10045.3.1.1": "p192", - "1.2.840.10045.3.1.7": "p256", - "1.3.132.0.34": "p384", - "1.3.132.0.35": "p521" -} + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; -},{}],98:[function(require,module,exports){ -(function (Buffer){ -var createHash = require('create-hash') -var stream = require('stream') -var inherits = require('inherits') -var sign = require('./sign') -var verify = require('./verify') + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); -var algorithms = require('./algorithms.json') -Object.keys(algorithms).forEach(function (key) { - algorithms[key].id = new Buffer(algorithms[key].id, 'hex') - algorithms[key.toLowerCase()] = algorithms[key] -}) + if (bitsLeft > 0) { + bytesNeeded--; + } -function Sign (algorithm) { - stream.Writable.call(this) + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } - var data = algorithms[algorithm] - if (!data) throw new Error('Unknown message digest') + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } - this._hashType = data.hash - this._hash = createHash(data.hash) - this._tag = data.id - this._signType = data.sign -} -inherits(Sign, stream.Writable) + // And remove leading zeroes + return this._strip(); + }; -Sign.prototype._write = function _write (data, _, done) { - this._hash.update(data) - done() -} + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; -Sign.prototype.update = function update (data, enc) { - if (typeof data === 'string') data = new Buffer(data, enc) + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); - this._hash.update(data) - return this -} + var off = (bit / 26) | 0; + var wbit = bit % 26; -Sign.prototype.sign = function signMethod (key, enc) { - this.end() - var hash = this._hash.digest() - var sig = sign(hash, key, this._hashType, this._signType, this._tag) + this._expand(off + 1); - return enc ? sig.toString(enc) : sig -} + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } -function Verify (algorithm) { - stream.Writable.call(this) + return this._strip(); + }; - var data = algorithms[algorithm] - if (!data) throw new Error('Unknown message digest') + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; - this._hash = createHash(data.hash) - this._tag = data.id - this._signType = data.sign -} -inherits(Verify, stream.Writable) + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); -Verify.prototype._write = function _write (data, _, done) { - this._hash.update(data) - done() -} + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } -Verify.prototype.update = function update (data, enc) { - if (typeof data === 'string') data = new Buffer(data, enc) + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } - this._hash.update(data) - return this -} + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } -Verify.prototype.verify = function verifyMethod (key, sig, enc) { - if (typeof sig === 'string') sig = new Buffer(sig, enc) + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } - this.end() - var hash = this._hash.digest() - return verify(sig, hash, key, this._signType, this._tag) -} + return this; + }; -function createSign (algorithm) { - return new Sign(algorithm) -} + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } -function createVerify (algorithm) { - return new Verify(algorithm) -} + if (this.length > num.length) return this.clone().iadd(num); -module.exports = { - Sign: createSign, - Verify: createVerify, - createSign: createSign, - createVerify: createVerify -} + return num.clone().iadd(this); + }; -}).call(this,require("buffer").Buffer) + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); -},{"./algorithms.json":96,"./sign":99,"./verify":100,"buffer":102,"create-hash":109,"inherits":175,"stream":245}],99:[function(require,module,exports){ -(function (Buffer){ -// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js -var createHmac = require('create-hmac') -var crt = require('browserify-rsa') -var EC = require('elliptic').ec -var BN = require('bn.js') -var parseKeys = require('parse-asn1') -var curves = require('./curves.json') + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } -function sign (hash, key, hashType, signType, tag) { - var priv = parseKeys(key) - if (priv.curve) { - // rsa keys can be interpreted as ecdsa ones in openssl - if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') - return ecSign(hash, priv) - } else if (priv.type === 'dsa') { - if (signType !== 'dsa') throw new Error('wrong private key type') - return dsaSign(hash, priv, hashType) - } else { - if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') - } - hash = Buffer.concat([tag, hash]) - var len = priv.modulus.byteLength() - var pad = [ 0, 1 ] - while (hash.length + pad.length + 1 < len) pad.push(0xff) - pad.push(0x00) - var i = -1 - while (++i < hash.length) pad.push(hash[i]) + // At this point both numbers are positive + var cmp = this.cmp(num); - var out = crt(pad, priv) - return out -} + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } -function ecSign (hash, priv) { - var curveId = curves[priv.curve.join('.')] - if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.')) + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } - var curve = new EC(curveId) - var key = curve.keyFromPrivate(priv.privateKey) - var out = key.sign(hash) + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } - return new Buffer(out.toDER()) -} - -function dsaSign (hash, priv, algo) { - var x = priv.params.priv_key - var p = priv.params.p - var q = priv.params.q - var g = priv.params.g - var r = new BN(0) - var k - var H = bits2int(hash, q).mod(q) - var s = false - var kv = getKey(x, q, hash, algo) - while (s === false) { - k = makeKey(q, kv, algo) - r = makeR(g, k, p, q) - s = k.invm(q).imul(H.add(x.mul(r))).mod(q) - if (s.cmpn(0) === 0) { - s = false - r = new BN(0) + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } } - } - return toDER(r, s) -} - -function toDER (r, s) { - r = r.toArray() - s = s.toArray() - - // Pad values - if (r[0] & 0x80) r = [ 0 ].concat(r) - if (s[0] & 0x80) s = [ 0 ].concat(s) - - var total = r.length + s.length + 4 - var res = [ 0x30, total, 0x02, r.length ] - res = res.concat(r, [ 0x02, s.length ], s) - return new Buffer(res) -} - -function getKey (x, q, hash, algo) { - x = new Buffer(x.toArray()) - if (x.length < q.byteLength()) { - var zeros = new Buffer(q.byteLength() - x.length) - zeros.fill(0) - x = Buffer.concat([ zeros, x ]) - } - var hlen = hash.length - var hbits = bits2octets(hash, q) - var v = new Buffer(hlen) - v.fill(1) - var k = new Buffer(hlen) - k.fill(0) - k = createHmac(algo, k).update(v).update(new Buffer([ 0 ])).update(x).update(hbits).digest() - v = createHmac(algo, k).update(v).digest() - k = createHmac(algo, k).update(v).update(new Buffer([ 1 ])).update(x).update(hbits).digest() - v = createHmac(algo, k).update(v).digest() - return { k: k, v: v } -} - -function bits2int (obits, q) { - var bits = new BN(obits) - var shift = (obits.length << 3) - q.bitLength() - if (shift > 0) bits.ishrn(shift) - return bits -} - -function bits2octets (bits, q) { - bits = bits2int(bits, q) - bits = bits.mod(q) - var out = new Buffer(bits.toArray()) - if (out.length < q.byteLength()) { - var zeros = new Buffer(q.byteLength() - out.length) - zeros.fill(0) - out = Buffer.concat([ zeros, out ]) - } - return out -} -function makeKey (q, kv, algo) { - var t - var k - - do { - t = new Buffer(0) + this.length = Math.max(this.length, i); - while (t.length * 8 < q.bitLength()) { - kv.v = createHmac(algo, kv.k).update(kv.v).digest() - t = Buffer.concat([ t, kv.v ]) + if (a !== this) { + this.negative = 1; } - k = bits2int(t, q) - kv.k = createHmac(algo, kv.k).update(kv.v).update(new Buffer([ 0 ])).digest() - kv.v = createHmac(algo, kv.k).update(kv.v).digest() - } while (k.cmp(q) !== -1) - - return k -} - -function makeR (g, k, p, q) { - return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q) -} - -module.exports = sign -module.exports.getKey = getKey -module.exports.makeKey = makeKey - -}).call(this,require("buffer").Buffer) - -},{"./curves.json":97,"bn.js":71,"browserify-rsa":94,"buffer":102,"create-hmac":111,"elliptic":124,"parse-asn1":188}],100:[function(require,module,exports){ -(function (Buffer){ -// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js -var BN = require('bn.js') -var EC = require('elliptic').ec -var parseKeys = require('parse-asn1') -var curves = require('./curves.json') - -function verify (sig, hash, key, signType, tag) { - var pub = parseKeys(key) - if (pub.type === 'ec') { - // rsa keys can be interpreted as ecdsa ones in openssl - if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') - return ecVerify(sig, hash, pub) - } else if (pub.type === 'dsa') { - if (signType !== 'dsa') throw new Error('wrong public key type') - return dsaVerify(sig, hash, pub) - } else { - if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') - } - hash = Buffer.concat([tag, hash]) - var len = pub.modulus.byteLength() - var pad = [ 1 ] - var padNum = 0 - while (hash.length + pad.length + 2 < len) { - pad.push(0xff) - padNum++ - } - pad.push(0x00) - var i = -1 - while (++i < hash.length) { - pad.push(hash[i]) - } - pad = new Buffer(pad) - var red = BN.mont(pub.modulus) - sig = new BN(sig).toRed(red) - - sig = sig.redPow(new BN(pub.publicExponent)) - sig = new Buffer(sig.fromRed().toArray()) - var out = padNum < 8 ? 1 : 0 - len = Math.min(sig.length, pad.length) - if (sig.length !== pad.length) out = 1 - - i = -1 - while (++i < len) out |= sig[i] ^ pad[i] - return out === 0 -} - -function ecVerify (sig, hash, pub) { - var curveId = curves[pub.data.algorithm.curve.join('.')] - if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.')) - - var curve = new EC(curveId) - var pubkey = pub.data.subjectPrivateKey.data - - return curve.verify(hash, sig, pubkey) -} - -function dsaVerify (sig, hash, pub) { - var p = pub.data.p - var q = pub.data.q - var g = pub.data.g - var y = pub.data.pub_key - var unpacked = parseKeys.signature.decode(sig, 'der') - var s = unpacked.s - var r = unpacked.r - checkValue(s, q) - checkValue(r, q) - var montp = BN.mont(p) - var w = s.invm(q) - var v = g.toRed(montp) - .redPow(new BN(hash).mul(w).mod(q)) - .fromRed() - .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed()) - .mod(p) - .mod(q) - return v.cmp(r) === 0 -} - -function checkValue (b, q) { - if (b.cmpn(0) <= 0) throw new Error('invalid sig') - if (b.cmp(q) >= q) throw new Error('invalid sig') -} - -module.exports = verify - -}).call(this,require("buffer").Buffer) - -},{"./curves.json":97,"bn.js":71,"buffer":102,"elliptic":124,"parse-asn1":188}],101:[function(require,module,exports){ -(function (Buffer){ -module.exports = function xor (a, b) { - var length = Math.min(a.length, b.length) - var buffer = new Buffer(length) - - for (var i = 0; i < length; ++i) { - buffer[i] = a[i] ^ b[i] - } - - return buffer -} - -}).call(this,require("buffer").Buffer) - -},{"buffer":102}],102:[function(require,module,exports){ -(function (Buffer){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ - -'use strict' - -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var customInspectSymbol = - (typeof Symbol === 'function' && typeof Symbol.for === 'function') - ? Symbol.for('nodejs.util.inspect.custom') - : null - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 - -var K_MAX_LENGTH = 0x7fffffff -exports.kMaxLength = K_MAX_LENGTH - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Print warning and recommend using `buffer` v4.x which has an Object - * implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * We report that the browser does not support typed arrays if the are not subclassable - * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` - * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support - * for __proto__ and has a buggy typed array implementation. - */ -Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() - -if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && - typeof console.error === 'function') { - console.error( - 'This browser lacks typed array (Uint8Array) support which is required by ' + - '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' - ) -} - -function typedArraySupport () { - // Can typed array instances can be augmented? - try { - var arr = new Uint8Array(1) - var proto = { foo: function () { return 42 } } - Object.setPrototypeOf(proto, Uint8Array.prototype) - Object.setPrototypeOf(arr, proto) - return arr.foo() === 42 - } catch (e) { - return false - } -} + return this._strip(); + }; -Object.defineProperty(Buffer.prototype, 'parent', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.buffer - } -}) + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; -Object.defineProperty(Buffer.prototype, 'offset', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.byteOffset - } -}) + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; -function createBuffer (length) { - if (length > K_MAX_LENGTH) { - throw new RangeError('The value "' + length + '" is invalid for option "size"') - } - // Return an augmented `Uint8Array` instance - var buf = new Uint8Array(length) - Object.setPrototypeOf(buf, Buffer.prototype) - return buf -} + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; -function Buffer (arg, encodingOrOffset, length) { - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new TypeError( - 'The "string" argument must be of type string. Received type number' - ) + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; } - return allocUnsafe(arg) - } - return from(arg, encodingOrOffset, length) -} - -// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 -if (typeof Symbol !== 'undefined' && Symbol.species != null && - Buffer[Symbol.species] === Buffer) { - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true, - enumerable: false, - writable: false - }) -} - -Buffer.poolSize = 8192 // not used by this implementation - -function from (value, encodingOrOffset, length) { - if (typeof value === 'string') { - return fromString(value, encodingOrOffset) - } - - if (ArrayBuffer.isView(value)) { - return fromArrayLike(value) - } - - if (value == null) { - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) - } - - if (isInstance(value, ArrayBuffer) || - (value && isInstance(value.buffer, ArrayBuffer))) { - return fromArrayBuffer(value, encodingOrOffset, length) - } - - if (typeof value === 'number') { - throw new TypeError( - 'The "value" argument must not be of type number. Received type number' - ) - } - - var valueOf = value.valueOf && value.valueOf() - if (valueOf != null && valueOf !== value) { - return Buffer.from(valueOf, encodingOrOffset, length) - } - - var b = fromObject(value) - if (b) return b - - if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && - typeof value[Symbol.toPrimitive] === 'function') { - return Buffer.from( - value[Symbol.toPrimitive]('string'), encodingOrOffset, length - ) - } - - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) -} - -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(value, encodingOrOffset, length) -} - -// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: -// https://github.com/feross/buffer/pull/148 -Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype) -Object.setPrototypeOf(Buffer, Uint8Array) - -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be of type number') - } else if (size < 0) { - throw new RangeError('The value "' + size + '" is invalid for option "size"') - } -} -function alloc (size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(size).fill(fill, encoding) - : createBuffer(size).fill(fill) + return out._strip(); } - return createBuffer(size) -} - -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(size, fill, encoding) -} -function allocUnsafe (size) { - assertSize(size) - return createBuffer(size < 0 ? 0 : checked(size) | 0) -} + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(size) -} - -function fromString (string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; } - var length = byteLength(string, encoding) | 0 - var buf = createBuffer(length) + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; - var actual = buf.write(string, encoding) + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - buf = buf.slice(0, actual) - } + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; - return buf -} + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } -function fromArrayLike (array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - var buf = createBuffer(length) - for (var i = 0; i < length; i += 1) { - buf[i] = array[i] & 255 + return out._strip(); } - return buf -} -function fromArrayBuffer (array, byteOffset, length) { - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('"offset" is outside of buffer bounds') + function jumboMulTo (self, num, out) { + // Temporary disable, see https://github.com/indutny/bn.js/issues/211 + // var fftm = new FFTM(); + // return fftm.mulp(self, num, out); + return bigMulTo(self, num, out); } - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('"length" is outside of buffer bounds') - } + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } - var buf - if (byteOffset === undefined && length === undefined) { - buf = new Uint8Array(array) - } else if (length === undefined) { - buf = new Uint8Array(array, byteOffset) - } else { - buf = new Uint8Array(array, byteOffset, length) + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; } - // Return an augmented `Uint8Array` instance - Object.setPrototypeOf(buf, Buffer.prototype) + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } - return buf -} + return t; + }; -function fromObject (obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - var buf = createBuffer(len) + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; - if (buf.length === 0) { - return buf + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; } - obj.copy(buf, 0, 0, len) - return buf - } + return rb; + }; - if (obj.length !== undefined) { - if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { - return createBuffer(0) + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; } - return fromArrayLike(obj) - } - - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data) - } -} + }; -function checked (length) { - // Note: cannot use `length < K_MAX_LENGTH` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= K_MAX_LENGTH) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') - } - return length | 0 -} + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; -Buffer.isBuffer = function isBuffer (b) { - return b != null && b._isBuffer === true && - b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false -} + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); -Buffer.compare = function compare (a, b) { - if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) - if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError( - 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' - ) - } + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; - if (a === b) return 0 + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; - var x = a.length - var y = b.length + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } + var rx = rtwdf_ * ro - itwdf_ * io; - if (x < y) return -1 - if (y < x) return 1 - return 0 -} + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} + rtws[p + j] = re + ro; + itws[p + j] = ie + io; -Buffer.concat = function concat (list, length) { - if (!Array.isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; - if (list.length === 0) { - return Buffer.alloc(0) - } + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } } - } + }; - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (isInstance(buf, Uint8Array)) { - buf = Buffer.from(buf) + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; } - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} + }; -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - throw new TypeError( - 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + - 'Received type ' + typeof string - ) - } + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; - var len = string.length - var mustMatch = (arguments.length > 2 && arguments[2] === true) - if (!mustMatch && len === 0) return 0 + ws[i] = w & 0x3ffffff; - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) { - return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 - } - encoding = ('' + encoding).toLowerCase() - loweredCase = true + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } } - } -} -Buffer.byteLength = byteLength -function slowToString (encoding, start, end) { - var loweredCase = false + return ws; + }; - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } - if (end === undefined || end > this.length) { - end = this.length - } + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } - if (end <= 0) { - return '' - } + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } - if (end <= start) { - return '' - } + return ph; + }; - if (!encoding) encoding = 'utf8' + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) + var rbt = this.makeRBT(N); - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) + var _ = this.stub(N); - case 'ascii': - return asciiSlice(this, start, end) + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); - case 'base64': - return base64Slice(this, start, end) + var rmws = out.words; + rmws.length = N; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; } - } -} -// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) -// to detect a Buffer instance. It's not possible to use `instanceof Buffer` -// reliably in a browserify context because there could be multiple different -// copies of the 'buffer' package in use. This method works even for Buffer -// instances that were created from another copy of the `buffer` package. -// See: https://github.com/feross/buffer/issues/154 -Buffer.prototype._isBuffer = true + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out._strip(); + }; -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; -Buffer.prototype.toString = function toString () { - var length = this.length - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} + BN.prototype.imuln = function imuln (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -Buffer.prototype.toLocaleString = Buffer.prototype.toString + assert(typeof num === 'number'); + assert(num < 0x4000000); -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() - if (this.length > max) str += ' ... ' - return '' -} -if (customInspectSymbol) { - Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect -} + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (isInstance(target, Uint8Array)) { - target = Buffer.from(target, target.offset, target.byteLength) - } - if (!Buffer.isBuffer(target)) { - throw new TypeError( - 'The "target" argument must be one of type Buffer or Uint8Array. ' + - 'Received type ' + (typeof target) - ) - } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } + return isNegNum ? this.ineg() : this; + }; - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; - if (this === target) return 0 + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break + res = res.mul(q); + } } - } - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 + return res; + }; - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (numberIsNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } + if (r !== 0) { + var carry = 0; - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + if (carry) { + this.words[i] = carry; + this.length++; } } - return arrayIndexOf(buffer, [val], byteOffset, encoding, dir) - } - - throw new TypeError('val must be string, number or Buffer') -} -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 + for (i = 0; i < s; i++) { + this.words[i] = 0; } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 + + this.length += s; } - } - function read (buf, i) { - if (indexSize === 1) { - return buf[i] + return this._strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; } else { - return buf.readUInt16BE(i * indexSize) + h = 0; } - } - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; } + maskedWords.length = s; } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } + + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; } - if (found) return i + } else { + this.words[0] = 0; + this.length = 1; } - } - return -1 -} + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} + return this._strip(); + }; -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; - var strLen = string.length + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (numberIsNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} + // Check bit and return + var w = this.words[s]; -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset >>> 0 - if (isFinite(length)) { - length = length >>> 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) - } + return !!(w & q); + }; - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } + assert(this.negative === 0, 'imaskn works only with positive numbers'); - if (!encoding) encoding = 'utf8' + if (this.length <= s) { + return this; + } - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } - case 'ascii': - return asciiWrite(this, string, offset, length) + return this._strip(); + }; - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) <= num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; } - } -} - -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} + // Add without checks + return this._iaddn(num); + }; -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint + return this; + }; - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; } - res.push(codePoint) - i += bytesPerSequence - } + this.words[0] -= num; - return decodeCodePointsArray(res) -} + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 + return this._strip(); + }; -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() - } + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) - } - return res -} + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) + BN.prototype.iabs = function iabs () { + this.negative = 0; - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} + return this; + }; -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) - } - return ret -} + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; -function hexSlice (buf, start, end) { - var len = buf.length + this._expand(len); - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } - var out = '' - for (var i = start; i < end; ++i) { - out += hexSliceLookupTable[buf[i]] - } - return out -} + if (carry === 0) return this._strip(); -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) - } - return res -} + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end + return this._strip(); + }; - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len - } + var a = this.clone(); + var b = num; - if (end < start) end = start + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } - var newBuf = this.subarray(start, end) - // Return an augmented `Uint8Array` instance - Object.setPrototypeOf(newBuf, Buffer.prototype) + // Initialize quotient + var m = a.length - b.length; + var q; - return newBuf -} + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); - return val -} + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q._strip(); + } + a._strip(); -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } + return { + div: q || null, + mod: a + }; + }; - return val -} + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} + if (mode !== 'mod') { + div = res.div.neg(); + } -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} + return { + div: div, + mod: mod + }; + } -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} + if (mode !== 'mod') { + div = res.div.neg(); + } -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + return { + div: div, + mod: res.mod + }; + } - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); - if (val >= mul) val -= Math.pow(2, 8 * byteLength) + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } - return val -} + return { + div: res.div, + mod: mod + }; + } -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + // Both numbers are positive at this point - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul - } - mul *= 0x80 + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } - if (val >= mul) val -= Math.pow(2, 8 * byteLength) + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } - return val -} + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modrn(num.words[0])) + }; + } -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} + return { + div: this.divn(num.words[0]), + mod: new BN(this.modrn(num.words[0])) + }; + } -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} + return this._wordDiv(num, mode); + }; -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} + // Round down + if (cmp < 0 || (r2 === 1 && cmp === 0)) return dm.div; -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} + BN.prototype.modrn = function modrn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } + return isNegNum ? -acc : acc; + }; - return offset + byteLength -} + // WARNING: DEPRECATED + BN.prototype.modn = function modn (num) { + return this.modrn(num); + }; -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - this[offset] = (value & 0xff) - return offset + 1 -} + // In-place division by number + BN.prototype.idivn = function idivn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} + assert(num <= 0x3ffffff); -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - return offset + 4 -} + this._strip(); + return isNegNum ? this.ineg() : this; + }; -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } + var x = this; + var y = p.clone(); - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - return offset + byteLength -} + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } + var g = 0; - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - return offset + byteLength -} + var yp = y.clone(); + var xp = x.clone(); -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} + A.iushrn(1); + B.iushrn(1); + } + } -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - return offset + 4 -} + C.iushrn(1); + D.iushrn(1); + } + } -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; -function writeFloat (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} + var a = this; + var b = p.clone(); -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } -function writeDouble (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} + var x1 = new BN(1); + var x2 = new BN(0); -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} + var delta = b.clone(); -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start + x1.iushrn(1); + } + } - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('Index out of range') - if (end < 0) throw new RangeError('sourceEnd out of bounds') + x2.iushrn(1); + } + } - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } - var len = end - start + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } - if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { - // Use built-in when available, missing from IE11 - this.copyWithin(targetStart, start, end) - } else if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (var i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] + if (res.cmpn(0) < 0) { + res.iadd(p); } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, end), - targetStart - ) - } - return len -} + return res; + }; -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length - } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); } - if (val.length === 1) { - var code = val.charCodeAt(0) - if ((encoding === 'utf8' && code < 128) || - encoding === 'latin1') { - // Fast path: If `val` fits into a single byte, use that numeric value. - val = code + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); } - } - } else if (typeof val === 'number') { - val = val & 255 - } else if (typeof val === 'boolean') { - val = Number(val) - } - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } - if (end <= start) { - return this - } + a.isub(b); + } while (true); - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 + return b.iushln(shift); + }; - if (!val) val = 0 + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : Buffer.from(val, encoding) - var len = bytes.length - if (len === 0) { - throw new TypeError('The value "' + val + - '" is invalid for argument "value"') + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; } - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] + if (carry !== 0) { + this.words[i] = carry; + this.length++; } - } + return this; + }; - return this -} + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; -// HELPER FUNCTIONS -// ================ + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; -var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; -function base64clean (str) { - // Node takes equal signs as end of the Base64 encoding - str = str.split('=')[0] - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = str.trim().replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} + this._strip(); -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) + assert(num <= 0x3ffffff, 'Number is too big'); - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; - // valid lead - leadSurrogate = codePoint + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; - continue - } + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; } + return res; + }; - leadSurrogate = null + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; - return bytes -} + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; - return byteArray -} + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] - } - return i -} + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; -// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass -// the `instanceof` check but they should be treated as of that type. -// See: https://github.com/feross/buffer/issues/166 -function isInstance (obj, type) { - return obj instanceof type || - (obj != null && obj.constructor != null && obj.constructor.name != null && - obj.constructor.name === type.name) -} -function numberIsNaN (obj) { - // For IE11 support - return obj !== obj // eslint-disable-line no-self-compare -} + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; -// Create lookup table for `toString('hex')` -// See: https://github.com/feross/buffer/issues/219 -var hexSliceLookupTable = (function () { - var alphabet = '0123456789abcdef' - var table = new Array(256) - for (var i = 0; i < 16; ++i) { - var i16 = i * 16 - for (var j = 0; j < 16; ++j) { - table[i16 + j] = alphabet[i] + alphabet[j] - } - } - return table -})() + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; -}).call(this,require("buffer").Buffer) + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; -},{"base64-js":69,"buffer":102,"ieee754":173}],103:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var Transform = require('stream').Transform -var StringDecoder = require('string_decoder').StringDecoder -var inherits = require('inherits') + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; -function CipherBase (hashMode) { - Transform.call(this) - this.hashMode = typeof hashMode === 'string' - if (this.hashMode) { - this[hashMode] = this._finalOrDigest - } else { - this.final = this._finalOrDigest - } - if (this._final) { - this.__final = this._final - this._final = null - } - this._decoder = null - this._encoding = null -} -inherits(CipherBase, Transform) + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; -CipherBase.prototype.update = function (data, inputEnc, outputEnc) { - if (typeof data === 'string') { - data = Buffer.from(data, inputEnc) - } + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; - var outData = this._update(data) - if (this.hashMode) return this + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; - if (outputEnc) { - outData = this._toString(outData, outputEnc) - } + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; - return outData -} + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; -CipherBase.prototype.setAutoPadding = function () {} -CipherBase.prototype.getAuthTag = function () { - throw new Error('trying to get auth tag in unsupported state') -} + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; -CipherBase.prototype.setAuthTag = function () { - throw new Error('trying to set auth tag in unsupported state') -} + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; -CipherBase.prototype.setAAD = function () { - throw new Error('trying to set aad in unsupported state') -} + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; -CipherBase.prototype._transform = function (data, _, next) { - var err - try { - if (this.hashMode) { - this._update(data) + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); } else { - this.push(this._update(data)) + if (r.strip !== undefined) { + // r is a BN v4 instance + r.strip(); + } else { + // r is a BN v5 instance + r._strip(); + } } - } catch (e) { - err = e - } finally { - next(err) - } -} -CipherBase.prototype._flush = function (done) { - var err - try { - this.push(this.__final()) - } catch (e) { - err = e - } - done(err) -} -CipherBase.prototype._finalOrDigest = function (outputEnc) { - var outData = this.__final() || Buffer.alloc(0) - if (outputEnc) { - outData = this._toString(outData, outputEnc, true) - } - return outData -} + return r; + }; -CipherBase.prototype._toString = function (value, enc, fin) { - if (!this._decoder) { - this._decoder = new StringDecoder(enc) - this._encoding = enc - } + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; - if (this._encoding !== enc) throw new Error('can\'t switch encodings') + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; - var out = this._decoder.write(value) - if (fin) { - out += this._decoder.end() + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); } + inherits(K256, MPrime); - return out -} + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; -module.exports = CipherBase + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; -},{"inherits":175,"safe-buffer":222,"stream":245,"string_decoder":246}],104:[function(require,module,exports){ -/** - * Slice reference. - */ + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } -var slice = [].slice; + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; -/** - * Bind `obj` to `fn`. - * - * @param {Object} obj - * @param {Function|String} fn or string - * @return {Function} - * @api public - */ + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; -module.exports = function(obj, fn){ - if ('string' == typeof fn) fn = obj[fn]; - if ('function' != typeof fn) throw new Error('bind() requires a function'); - var args = slice.call(arguments, 2); - return function(){ - return fn.apply(obj, args.concat(slice.call(arguments))); + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); } -}; + inherits(P224, MPrime); -},{}],105:[function(require,module,exports){ - -/** - * Expose `Emitter`. - */ - -if (typeof module !== 'undefined') { - module.exports = Emitter; -} - -/** - * Initialize a new `Emitter`. - * - * @api public - */ - -function Emitter(obj) { - if (obj) return mixin(obj); -}; - -/** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - -function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; -} - -/** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.on = -Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks['$' + event] = this._callbacks['$' + event] || []) - .push(fn); - return this; -}; - -/** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.once = function(event, fn){ - function on() { - this.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; -}; - -/** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.off = -Emitter.prototype.removeListener = -Emitter.prototype.removeAllListeners = -Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks['$' + event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks['$' + event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; -}; - -/** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - -Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks['$' + event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; -}; - -/** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - -Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks['$' + event] || []; -}; - -/** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - -Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; -}; + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); -},{}],106:[function(require,module,exports){ + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); -module.exports = function(a, b){ - var fn = function(){}; - fn.prototype = b.prototype; - a.prototype = new fn; - a.prototype.constructor = a; -}; -},{}],107:[function(require,module,exports){ -(function (Buffer){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); - } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; + return prime; + }; -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; + move(a, a.umod(this.m)._forceRed(this)); + return a; + }; -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; + return this.m.sub(a)._forceRed(this); + }; -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; + Red.prototype.add = function add (a, b) { + this._verify2(a, b); -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; -exports.isBuffer = Buffer.isBuffer; + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); -function objectToString(o) { - return Object.prototype.toString.call(o); -} + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; -}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); -},{"../../is-buffer/index.js":176}],108:[function(require,module,exports){ -(function (Buffer){ -var elliptic = require('elliptic') -var BN = require('bn.js') + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; -module.exports = function createECDH (curve) { - return new ECDH(curve) -} + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; -var aliases = { - secp256k1: { - name: 'secp256k1', - byteLength: 32 - }, - secp224r1: { - name: 'p224', - byteLength: 28 - }, - prime256v1: { - name: 'p256', - byteLength: 32 - }, - prime192v1: { - name: 'p192', - byteLength: 24 - }, - ed25519: { - name: 'ed25519', - byteLength: 32 - }, - secp384r1: { - name: 'p384', - byteLength: 48 - }, - secp521r1: { - name: 'p521', - byteLength: 66 - } -} + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; -aliases.p224 = aliases.secp224r1 -aliases.p256 = aliases.secp256r1 = aliases.prime256v1 -aliases.p192 = aliases.secp192r1 = aliases.prime192v1 -aliases.p384 = aliases.secp384r1 -aliases.p521 = aliases.secp521r1 + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; -function ECDH (curve) { - this.curveType = aliases[curve] - if (!this.curveType) { - this.curveType = { - name: curve - } - } - this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap - this.keys = void 0 -} + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; -ECDH.prototype.generateKeys = function (enc, format) { - this.keys = this.curve.genKeyPair() - return this.getPublicKey(enc, format) -} + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; -ECDH.prototype.computeSecret = function (other, inenc, enc) { - inenc = inenc || 'utf8' - if (!Buffer.isBuffer(other)) { - other = new Buffer(other, inenc) - } - var otherPub = this.curve.keyFromPublic(other).getPublic() - var out = otherPub.mul(this.keys.getPrivate()).getX() - return formatReturnValue(out, enc, this.curveType.byteLength) -} + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); -ECDH.prototype.getPublicKey = function (enc, format) { - var key = this.keys.getPublic(format === 'compressed', true) - if (format === 'hybrid') { - if (key[key.length - 1] % 2) { - key[0] = 7 - } else { - key[0] = 6 + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); } - } - return formatReturnValue(key, enc) -} -ECDH.prototype.getPrivateKey = function (enc) { - return formatReturnValue(this.keys.getPrivate(), enc) -} + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); -ECDH.prototype.setPublicKey = function (pub, enc) { - enc = enc || 'utf8' - if (!Buffer.isBuffer(pub)) { - pub = new Buffer(pub, enc) - } - this.keys._importPublic(pub) - return this -} + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); -ECDH.prototype.setPrivateKey = function (priv, enc) { - enc = enc || 'utf8' - if (!Buffer.isBuffer(priv)) { - priv = new Buffer(priv, enc) - } + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); - var _priv = new BN(priv) - _priv = _priv.toString(16) - this.keys = this.curve.genKeyPair() - this.keys._importPrivate(_priv) - return this -} + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } -function formatReturnValue (bn, enc, len) { - if (!Array.isArray(bn)) { - bn = bn.toArray() - } - var buf = new Buffer(bn) - if (len && buf.length < len) { - var zeros = new Buffer(len - buf.length) - zeros.fill(0) - buf = Buffer.concat([zeros, buf]) - } - if (!enc) { - return buf - } else { - return buf.toString(enc) - } -} - -}).call(this,require("buffer").Buffer) - -},{"bn.js":71,"buffer":102,"elliptic":124}],109:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var MD5 = require('md5.js') -var RIPEMD160 = require('ripemd160') -var sha = require('sha.js') -var Base = require('cipher-base') - -function Hash (hash) { - Base.call(this, 'digest') + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); - this._hash = hash -} + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } -inherits(Hash, Base) + return r; + }; -Hash.prototype._update = function (data) { - this._hash.update(data) -} + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; -Hash.prototype._final = function () { - return this._hash.digest() -} + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); -module.exports = function createHash (alg) { - alg = alg.toLowerCase() - if (alg === 'md5') return new MD5() - if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160() + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } - return new Hash(sha(alg)) -} + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } -},{"cipher-base":103,"inherits":175,"md5.js":180,"ripemd160":221,"sha.js":224}],110:[function(require,module,exports){ -var MD5 = require('md5.js') + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } -module.exports = function (buffer) { - return new MD5().update(buffer).digest() -} + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } -},{"md5.js":180}],111:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var Legacy = require('./legacy') -var Base = require('cipher-base') -var Buffer = require('safe-buffer').Buffer -var md5 = require('create-hash/md5') -var RIPEMD160 = require('ripemd160') + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; -var sha = require('sha.js') + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } -var ZEROS = Buffer.alloc(128) + return res; + }; -function Hmac (alg, key) { - Base.call(this, 'digest') - if (typeof key === 'string') { - key = Buffer.from(key) - } + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); - var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 + return r === num ? r.clone() : r; + }; - this._alg = alg - this._key = key - if (key.length > blocksize) { - var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) - key = hash.update(key).digest() - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; - var ipad = this._ipad = Buffer.allocUnsafe(blocksize) - var opad = this._opad = Buffer.allocUnsafe(blocksize) + // + // Montgomery method engine + // - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C - } - this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) - this._hash.update(ipad) -} + BN.mont = function mont (num) { + return new Mont(num); + }; -inherits(Hmac, Base) + function Mont (m) { + Red.call(this, m); -Hmac.prototype._update = function (data) { - this._hash.update(data) -} + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } -Hmac.prototype._final = function () { - var h = this._hash.digest() - var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg) - return hash.update(this._opad).update(h).digest() -} + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); -module.exports = function createHmac (alg, key) { - alg = alg.toLowerCase() - if (alg === 'rmd160' || alg === 'ripemd160') { - return new Hmac('rmd160', key) - } - if (alg === 'md5') { - return new Legacy(md5, key) + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); } - return new Hmac(alg, key) -} - -},{"./legacy":112,"cipher-base":103,"create-hash/md5":110,"inherits":175,"ripemd160":221,"safe-buffer":222,"sha.js":224}],112:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var Buffer = require('safe-buffer').Buffer + inherits(Mont, Red); -var Base = require('cipher-base') + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; -var ZEROS = Buffer.alloc(128) -var blocksize = 64 + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; -function Hmac (alg, key) { - Base.call(this, 'digest') - if (typeof key === 'string') { - key = Buffer.from(key) - } + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } - this._alg = alg - this._key = key + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; - if (key.length > blocksize) { - key = alg(key) - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } - var ipad = this._ipad = Buffer.allocUnsafe(blocksize) - var opad = this._opad = Buffer.allocUnsafe(blocksize) + return res._forceRed(this); + }; - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C - } + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - this._hash = [ipad] -} + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } -inherits(Hmac, Base) + return res._forceRed(this); + }; -Hmac.prototype._update = function (data) { - this._hash.push(data) -} + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); -Hmac.prototype._final = function () { - var h = this._alg(Buffer.concat(this._hash)) - return this._alg(Buffer.concat([this._opad, h])) -} -module.exports = Hmac +},{"buffer":82}],81:[function(require,module,exports){ +var r; -},{"cipher-base":103,"inherits":175,"safe-buffer":222}],113:[function(require,module,exports){ -'use strict' +module.exports = function rand(len) { + if (!r) + r = new Rand(null); -exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes') -exports.createHash = exports.Hash = require('create-hash') -exports.createHmac = exports.Hmac = require('create-hmac') + return r.generate(len); +}; -var algos = require('browserify-sign/algos') -var algoKeys = Object.keys(algos) -var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys) -exports.getHashes = function () { - return hashes +function Rand(rand) { + this.rand = rand; } +module.exports.Rand = Rand; -var p = require('pbkdf2') -exports.pbkdf2 = p.pbkdf2 -exports.pbkdf2Sync = p.pbkdf2Sync - -var aes = require('browserify-cipher') +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; -exports.Cipher = aes.Cipher -exports.createCipher = aes.createCipher -exports.Cipheriv = aes.Cipheriv -exports.createCipheriv = aes.createCipheriv -exports.Decipher = aes.Decipher -exports.createDecipher = aes.createDecipher -exports.Decipheriv = aes.Decipheriv -exports.createDecipheriv = aes.createDecipheriv -exports.getCiphers = aes.getCiphers -exports.listCiphers = aes.listCiphers +// Emulate crypto API using randy +Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); -var dh = require('diffie-hellman') + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; +}; -exports.DiffieHellmanGroup = dh.DiffieHellmanGroup -exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup -exports.getDiffieHellman = dh.getDiffieHellman -exports.createDiffieHellman = dh.createDiffieHellman -exports.DiffieHellman = dh.DiffieHellman +if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; -var sign = require('browserify-sign') + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } +} else { + // Node.js or Web worker with no crypto support + try { + var crypto = require('crypto'); + if (typeof crypto.randomBytes !== 'function') + throw new Error('Not supported'); -exports.createSign = sign.createSign -exports.Sign = sign.Sign -exports.createVerify = sign.createVerify -exports.Verify = sign.Verify + Rand.prototype._rand = function _rand(n) { + return crypto.randomBytes(n); + }; + } catch (e) { + } +} -exports.createECDH = require('create-ecdh') +},{"crypto":82}],82:[function(require,module,exports){ -var publicEncrypt = require('public-encrypt') +},{}],83:[function(require,module,exports){ +// based on the aes implimentation in triple sec +// https://github.com/keybase/triplesec +// which is in turn based on the one from crypto-js +// https://code.google.com/p/crypto-js/ -exports.publicEncrypt = publicEncrypt.publicEncrypt -exports.privateEncrypt = publicEncrypt.privateEncrypt -exports.publicDecrypt = publicEncrypt.publicDecrypt -exports.privateDecrypt = publicEncrypt.privateDecrypt +var Buffer = require('safe-buffer').Buffer -// the least I can do is make error messages for the rest of the node.js/crypto api. -// ;[ -// 'createCredentials' -// ].forEach(function (name) { -// exports[name] = function () { -// throw new Error([ -// 'sorry, ' + name + ' is not implemented yet', -// 'we accept pull requests', -// 'https://github.com/crypto-browserify/crypto-browserify' -// ].join('\n')) -// } -// }) +function asUInt32Array (buf) { + if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) -var rf = require('randomfill') + var len = (buf.length / 4) | 0 + var out = new Array(len) -exports.randomFill = rf.randomFill -exports.randomFillSync = rf.randomFillSync + for (var i = 0; i < len; i++) { + out[i] = buf.readUInt32BE(i * 4) + } -exports.createCredentials = function () { - throw new Error([ - 'sorry, createCredentials is not implemented yet', - 'we accept pull requests', - 'https://github.com/crypto-browserify/crypto-browserify' - ].join('\n')) + return out } -exports.constants = { - 'DH_CHECK_P_NOT_SAFE_PRIME': 2, - 'DH_CHECK_P_NOT_PRIME': 1, - 'DH_UNABLE_TO_CHECK_GENERATOR': 4, - 'DH_NOT_SUITABLE_GENERATOR': 8, - 'NPN_ENABLED': 1, - 'ALPN_ENABLED': 1, - 'RSA_PKCS1_PADDING': 1, - 'RSA_SSLV23_PADDING': 2, - 'RSA_NO_PADDING': 3, - 'RSA_PKCS1_OAEP_PADDING': 4, - 'RSA_X931_PADDING': 5, - 'RSA_PKCS1_PSS_PADDING': 6, - 'POINT_CONVERSION_COMPRESSED': 2, - 'POINT_CONVERSION_UNCOMPRESSED': 4, - 'POINT_CONVERSION_HYBRID': 6 +function scrubVec (v) { + for (var i = 0; i < v.length; v++) { + v[i] = 0 + } } -},{"browserify-cipher":91,"browserify-sign":98,"browserify-sign/algos":95,"create-ecdh":108,"create-hash":109,"create-hmac":111,"diffie-hellman":120,"pbkdf2":192,"public-encrypt":199,"randombytes":205,"randomfill":206}],114:[function(require,module,exports){ -'use strict'; - -exports.utils = require('./des/utils'); -exports.Cipher = require('./des/cipher'); -exports.DES = require('./des/des'); -exports.CBC = require('./des/cbc'); -exports.EDE = require('./des/ede'); - -},{"./des/cbc":115,"./des/cipher":116,"./des/des":117,"./des/ede":118,"./des/utils":119}],115:[function(require,module,exports){ -'use strict'; +function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) { + var SUB_MIX0 = SUB_MIX[0] + var SUB_MIX1 = SUB_MIX[1] + var SUB_MIX2 = SUB_MIX[2] + var SUB_MIX3 = SUB_MIX[3] -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); + var s0 = M[0] ^ keySchedule[0] + var s1 = M[1] ^ keySchedule[1] + var s2 = M[2] ^ keySchedule[2] + var s3 = M[3] ^ keySchedule[3] + var t0, t1, t2, t3 + var ksRow = 4 -var proto = {}; + for (var round = 1; round < nRounds; round++) { + t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++] + t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++] + t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++] + t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++] + s0 = t0 + s1 = t1 + s2 = t2 + s3 = t3 + } -function CBCState(iv) { - assert.equal(iv.length, 8, 'Invalid IV length'); + t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] + t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] + t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] + t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] + t0 = t0 >>> 0 + t1 = t1 >>> 0 + t2 = t2 >>> 0 + t3 = t3 >>> 0 - this.iv = new Array(8); - for (var i = 0; i < this.iv.length; i++) - this.iv[i] = iv[i]; + return [t0, t1, t2, t3] } -function instantiate(Base) { - function CBC(options) { - Base.call(this, options); - this._cbcInit(); +// AES constants +var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] +var G = (function () { + // Compute double table + var d = new Array(256) + for (var j = 0; j < 256; j++) { + if (j < 128) { + d[j] = j << 1 + } else { + d[j] = (j << 1) ^ 0x11b + } } - inherits(CBC, Base); - var keys = Object.keys(proto); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - CBC.prototype[key] = proto[key]; - } + var SBOX = [] + var INV_SBOX = [] + var SUB_MIX = [[], [], [], []] + var INV_SUB_MIX = [[], [], [], []] - CBC.create = function create(options) { - return new CBC(options); - }; + // Walk GF(2^8) + var x = 0 + var xi = 0 + for (var i = 0; i < 256; ++i) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63 + SBOX[x] = sx + INV_SBOX[sx] = x - return CBC; -} + // Compute multiplication + var x2 = d[x] + var x4 = d[x2] + var x8 = d[x4] -exports.instantiate = instantiate; - -proto._cbcInit = function _cbcInit() { - var state = new CBCState(this.options.iv); - this._cbcState = state; -}; + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100) + SUB_MIX[0][x] = (t << 24) | (t >>> 8) + SUB_MIX[1][x] = (t << 16) | (t >>> 16) + SUB_MIX[2][x] = (t << 8) | (t >>> 24) + SUB_MIX[3][x] = t -proto._update = function _update(inp, inOff, out, outOff) { - var state = this._cbcState; - var superProto = this.constructor.super_.prototype; + // Compute inv sub bytes, inv mix columns tables + t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100) + INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) + INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) + INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) + INV_SUB_MIX[3][sx] = t - var iv = state.iv; - if (this.type === 'encrypt') { - for (var i = 0; i < this.blockSize; i++) - iv[i] ^= inp[inOff + i]; + if (x === 0) { + x = xi = 1 + } else { + x = x2 ^ d[d[d[x8 ^ x2]]] + xi ^= d[d[xi]] + } + } - superProto._update.call(this, iv, 0, out, outOff); + return { + SBOX: SBOX, + INV_SBOX: INV_SBOX, + SUB_MIX: SUB_MIX, + INV_SUB_MIX: INV_SUB_MIX + } +})() - for (var i = 0; i < this.blockSize; i++) - iv[i] = out[outOff + i]; - } else { - superProto._update.call(this, inp, inOff, out, outOff); +function AES (key) { + this._key = asUInt32Array(key) + this._reset() +} - for (var i = 0; i < this.blockSize; i++) - out[outOff + i] ^= iv[i]; +AES.blockSize = 4 * 4 +AES.keySize = 256 / 8 +AES.prototype.blockSize = AES.blockSize +AES.prototype.keySize = AES.keySize +AES.prototype._reset = function () { + var keyWords = this._key + var keySize = keyWords.length + var nRounds = keySize + 6 + var ksRows = (nRounds + 1) * 4 - for (var i = 0; i < this.blockSize; i++) - iv[i] = inp[inOff + i]; + var keySchedule = [] + for (var k = 0; k < keySize; k++) { + keySchedule[k] = keyWords[k] } -}; -},{"inherits":175,"minimalistic-assert":182}],116:[function(require,module,exports){ -'use strict'; + for (k = keySize; k < ksRows; k++) { + var t = keySchedule[k - 1] -var assert = require('minimalistic-assert'); + if (k % keySize === 0) { + t = (t << 8) | (t >>> 24) + t = + (G.SBOX[t >>> 24] << 24) | + (G.SBOX[(t >>> 16) & 0xff] << 16) | + (G.SBOX[(t >>> 8) & 0xff] << 8) | + (G.SBOX[t & 0xff]) -function Cipher(options) { - this.options = options; + t ^= RCON[(k / keySize) | 0] << 24 + } else if (keySize > 6 && k % keySize === 4) { + t = + (G.SBOX[t >>> 24] << 24) | + (G.SBOX[(t >>> 16) & 0xff] << 16) | + (G.SBOX[(t >>> 8) & 0xff] << 8) | + (G.SBOX[t & 0xff]) + } - this.type = this.options.type; - this.blockSize = 8; - this._init(); + keySchedule[k] = keySchedule[k - keySize] ^ t + } - this.buffer = new Array(this.blockSize); - this.bufferOff = 0; + var invKeySchedule = [] + for (var ik = 0; ik < ksRows; ik++) { + var ksR = ksRows - ik + var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)] + + if (ik < 4 || ksR <= 4) { + invKeySchedule[ik] = tt + } else { + invKeySchedule[ik] = + G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^ + G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^ + G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^ + G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]] + } + } + + this._nRounds = nRounds + this._keySchedule = keySchedule + this._invKeySchedule = invKeySchedule } -module.exports = Cipher; -Cipher.prototype._init = function _init() { - // Might be overrided -}; +AES.prototype.encryptBlockRaw = function (M) { + M = asUInt32Array(M) + return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds) +} -Cipher.prototype.update = function update(data) { - if (data.length === 0) - return []; +AES.prototype.encryptBlock = function (M) { + var out = this.encryptBlockRaw(M) + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0], 0) + buf.writeUInt32BE(out[1], 4) + buf.writeUInt32BE(out[2], 8) + buf.writeUInt32BE(out[3], 12) + return buf +} - if (this.type === 'decrypt') - return this._updateDecrypt(data); - else - return this._updateEncrypt(data); -}; +AES.prototype.decryptBlock = function (M) { + M = asUInt32Array(M) -Cipher.prototype._buffer = function _buffer(data, off) { - // Append data to buffer - var min = Math.min(this.buffer.length - this.bufferOff, data.length - off); - for (var i = 0; i < min; i++) - this.buffer[this.bufferOff + i] = data[off + i]; - this.bufferOff += min; + // swap + var m1 = M[1] + M[1] = M[3] + M[3] = m1 - // Shift next - return min; -}; + var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds) + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0], 0) + buf.writeUInt32BE(out[3], 4) + buf.writeUInt32BE(out[2], 8) + buf.writeUInt32BE(out[1], 12) + return buf +} -Cipher.prototype._flushBuffer = function _flushBuffer(out, off) { - this._update(this.buffer, 0, out, off); - this.bufferOff = 0; - return this.blockSize; -}; +AES.prototype.scrub = function () { + scrubVec(this._keySchedule) + scrubVec(this._invKeySchedule) + scrubVec(this._key) +} -Cipher.prototype._updateEncrypt = function _updateEncrypt(data) { - var inputOff = 0; - var outputOff = 0; +module.exports.AES = AES - var count = ((this.bufferOff + data.length) / this.blockSize) | 0; - var out = new Array(count * this.blockSize); +},{"safe-buffer":277}],84:[function(require,module,exports){ +var aes = require('./aes') +var Buffer = require('safe-buffer').Buffer +var Transform = require('cipher-base') +var inherits = require('inherits') +var GHASH = require('./ghash') +var xor = require('buffer-xor') +var incr32 = require('./incr32') - if (this.bufferOff !== 0) { - inputOff += this._buffer(data, inputOff); +function xorTest (a, b) { + var out = 0 + if (a.length !== b.length) out++ - if (this.bufferOff === this.buffer.length) - outputOff += this._flushBuffer(out, outputOff); + var len = Math.min(a.length, b.length) + for (var i = 0; i < len; ++i) { + out += (a[i] ^ b[i]) } - // Write blocks - var max = data.length - ((data.length - inputOff) % this.blockSize); - for (; inputOff < max; inputOff += this.blockSize) { - this._update(data, inputOff, out, outputOff); - outputOff += this.blockSize; + return out +} + +function calcIv (self, iv, ck) { + if (iv.length === 12) { + self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) + return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])]) + } + var ghash = new GHASH(ck) + var len = iv.length + var toPad = len % 16 + ghash.update(iv) + if (toPad) { + toPad = 16 - toPad + ghash.update(Buffer.alloc(toPad, 0)) } + ghash.update(Buffer.alloc(8, 0)) + var ivBits = len * 8 + var tail = Buffer.alloc(8) + tail.writeUIntBE(ivBits, 0, 8) + ghash.update(tail) + self._finID = ghash.state + var out = Buffer.from(self._finID) + incr32(out) + return out +} +function StreamCipher (mode, key, iv, decrypt) { + Transform.call(this) - // Queue rest - for (; inputOff < data.length; inputOff++, this.bufferOff++) - this.buffer[this.bufferOff] = data[inputOff]; + var h = Buffer.alloc(4, 0) - return out; -}; + this._cipher = new aes.AES(key) + var ck = this._cipher.encryptBlock(h) + this._ghash = new GHASH(ck) + iv = calcIv(this, iv, ck) -Cipher.prototype._updateDecrypt = function _updateDecrypt(data) { - var inputOff = 0; - var outputOff = 0; + this._prev = Buffer.from(iv) + this._cache = Buffer.allocUnsafe(0) + this._secCache = Buffer.allocUnsafe(0) + this._decrypt = decrypt + this._alen = 0 + this._len = 0 + this._mode = mode - var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1; - var out = new Array(count * this.blockSize); + this._authTag = null + this._called = false +} - // TODO(indutny): optimize it, this is far from optimal - for (; count > 0; count--) { - inputOff += this._buffer(data, inputOff); - outputOff += this._flushBuffer(out, outputOff); +inherits(StreamCipher, Transform) + +StreamCipher.prototype._update = function (chunk) { + if (!this._called && this._alen) { + var rump = 16 - (this._alen % 16) + if (rump < 16) { + rump = Buffer.alloc(rump, 0) + this._ghash.update(rump) + } } - // Buffer rest of the input - inputOff += this._buffer(data, inputOff); + this._called = true + var out = this._mode.encrypt(this, chunk) + if (this._decrypt) { + this._ghash.update(chunk) + } else { + this._ghash.update(out) + } + this._len += chunk.length + return out +} - return out; -}; +StreamCipher.prototype._final = function () { + if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') -Cipher.prototype.final = function final(buffer) { - var first; - if (buffer) - first = this.update(buffer); + var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) + if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') - var last; - if (this.type === 'encrypt') - last = this._finalEncrypt(); - else - last = this._finalDecrypt(); + this._authTag = tag + this._cipher.scrub() +} - if (first) - return first.concat(last); - else - return last; -}; +StreamCipher.prototype.getAuthTag = function getAuthTag () { + if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') -Cipher.prototype._pad = function _pad(buffer, off) { - if (off === 0) - return false; + return this._authTag +} - while (off < buffer.length) - buffer[off++] = 0; +StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { + if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') - return true; -}; + this._authTag = tag +} -Cipher.prototype._finalEncrypt = function _finalEncrypt() { - if (!this._pad(this.buffer, this.bufferOff)) - return []; +StreamCipher.prototype.setAAD = function setAAD (buf) { + if (this._called) throw new Error('Attempting to set AAD in unsupported state') - var out = new Array(this.blockSize); - this._update(this.buffer, 0, out, 0); - return out; -}; + this._ghash.update(buf) + this._alen += buf.length +} -Cipher.prototype._unpad = function _unpad(buffer) { - return buffer; -}; +module.exports = StreamCipher -Cipher.prototype._finalDecrypt = function _finalDecrypt() { - assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt'); - var out = new Array(this.blockSize); - this._flushBuffer(out, 0); +},{"./aes":83,"./ghash":88,"./incr32":89,"buffer-xor":128,"cipher-base":130,"inherits":224,"safe-buffer":277}],85:[function(require,module,exports){ +var ciphers = require('./encrypter') +var deciphers = require('./decrypter') +var modes = require('./modes/list.json') - return this._unpad(out); -}; +function getCiphers () { + return Object.keys(modes) +} -},{"minimalistic-assert":182}],117:[function(require,module,exports){ -'use strict'; +exports.createCipher = exports.Cipher = ciphers.createCipher +exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv +exports.createDecipher = exports.Decipher = deciphers.createDecipher +exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv +exports.listCiphers = exports.getCiphers = getCiphers -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); +},{"./decrypter":86,"./encrypter":87,"./modes/list.json":97}],86:[function(require,module,exports){ +var AuthCipher = require('./authCipher') +var Buffer = require('safe-buffer').Buffer +var MODES = require('./modes') +var StreamCipher = require('./streamCipher') +var Transform = require('cipher-base') +var aes = require('./aes') +var ebtk = require('evp_bytestokey') +var inherits = require('inherits') -var utils = require('./utils'); -var Cipher = require('./cipher'); +function Decipher (mode, key, iv) { + Transform.call(this) -function DESState() { - this.tmp = new Array(2); - this.keys = null; + this._cache = new Splitter() + this._last = void 0 + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._mode = mode + this._autopadding = true } -function DES(options) { - Cipher.call(this, options); +inherits(Decipher, Transform) - var state = new DESState(); - this._desState = state; +Decipher.prototype._update = function (data) { + this._cache.add(data) + var chunk + var thing + var out = [] + while ((chunk = this._cache.get(this._autopadding))) { + thing = this._mode.decrypt(this, chunk) + out.push(thing) + } + return Buffer.concat(out) +} - this.deriveKeys(state, options.key); +Decipher.prototype._final = function () { + var chunk = this._cache.flush() + if (this._autopadding) { + return unpad(this._mode.decrypt(this, chunk)) + } else if (chunk) { + throw new Error('data not multiple of block length') + } } -inherits(DES, Cipher); -module.exports = DES; -DES.create = function create(options) { - return new DES(options); -}; +Decipher.prototype.setAutoPadding = function (setTo) { + this._autopadding = !!setTo + return this +} -var shiftTable = [ - 1, 1, 2, 2, 2, 2, 2, 2, - 1, 2, 2, 2, 2, 2, 2, 1 -]; +function Splitter () { + this.cache = Buffer.allocUnsafe(0) +} -DES.prototype.deriveKeys = function deriveKeys(state, key) { - state.keys = new Array(16 * 2); +Splitter.prototype.add = function (data) { + this.cache = Buffer.concat([this.cache, data]) +} - assert.equal(key.length, this.blockSize, 'Invalid key length'); +Splitter.prototype.get = function (autoPadding) { + var out + if (autoPadding) { + if (this.cache.length > 16) { + out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out + } + } else { + if (this.cache.length >= 16) { + out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out + } + } - var kL = utils.readUInt32BE(key, 0); - var kR = utils.readUInt32BE(key, 4); + return null +} - utils.pc1(kL, kR, state.tmp, 0); - kL = state.tmp[0]; - kR = state.tmp[1]; - for (var i = 0; i < state.keys.length; i += 2) { - var shift = shiftTable[i >>> 1]; - kL = utils.r28shl(kL, shift); - kR = utils.r28shl(kR, shift); - utils.pc2(kL, kR, state.keys, i); +Splitter.prototype.flush = function () { + if (this.cache.length) return this.cache +} + +function unpad (last) { + var padded = last[15] + if (padded < 1 || padded > 16) { + throw new Error('unable to decrypt data') } -}; + var i = -1 + while (++i < padded) { + if (last[(i + (16 - padded))] !== padded) { + throw new Error('unable to decrypt data') + } + } + if (padded === 16) return -DES.prototype._update = function _update(inp, inOff, out, outOff) { - var state = this._desState; + return last.slice(0, 16 - padded) +} - var l = utils.readUInt32BE(inp, inOff); - var r = utils.readUInt32BE(inp, inOff + 4); +function createDecipheriv (suite, password, iv) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - // Initial Permutation - utils.ip(l, r, state.tmp, 0); - l = state.tmp[0]; - r = state.tmp[1]; + if (typeof iv === 'string') iv = Buffer.from(iv) + if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) - if (this.type === 'encrypt') - this._encrypt(state, l, r, state.tmp, 0); - else - this._decrypt(state, l, r, state.tmp, 0); + if (typeof password === 'string') password = Buffer.from(password) + if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) - l = state.tmp[0]; - r = state.tmp[1]; + if (config.type === 'stream') { + return new StreamCipher(config.module, password, iv, true) + } else if (config.type === 'auth') { + return new AuthCipher(config.module, password, iv, true) + } - utils.writeUInt32BE(out, l, outOff); - utils.writeUInt32BE(out, r, outOff + 4); -}; + return new Decipher(config.module, password, iv) +} -DES.prototype._pad = function _pad(buffer, off) { - var value = buffer.length - off; - for (var i = off; i < buffer.length; i++) - buffer[i] = value; +function createDecipher (suite, password) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - return true; -}; + var keys = ebtk(password, false, config.key, config.iv) + return createDecipheriv(suite, keys.key, keys.iv) +} -DES.prototype._unpad = function _unpad(buffer) { - var pad = buffer[buffer.length - 1]; - for (var i = buffer.length - pad; i < buffer.length; i++) - assert.equal(buffer[i], pad); +exports.createDecipher = createDecipher +exports.createDecipheriv = createDecipheriv - return buffer.slice(0, buffer.length - pad); -}; +},{"./aes":83,"./authCipher":84,"./modes":96,"./streamCipher":99,"cipher-base":130,"evp_bytestokey":188,"inherits":224,"safe-buffer":277}],87:[function(require,module,exports){ +var MODES = require('./modes') +var AuthCipher = require('./authCipher') +var Buffer = require('safe-buffer').Buffer +var StreamCipher = require('./streamCipher') +var Transform = require('cipher-base') +var aes = require('./aes') +var ebtk = require('evp_bytestokey') +var inherits = require('inherits') -DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) { - var l = lStart; - var r = rStart; +function Cipher (mode, key, iv) { + Transform.call(this) - // Apply f() x16 times - for (var i = 0; i < state.keys.length; i += 2) { - var keyL = state.keys[i]; - var keyR = state.keys[i + 1]; + this._cache = new Splitter() + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._mode = mode + this._autopadding = true +} - // f(r, k) - utils.expand(r, state.tmp, 0); +inherits(Cipher, Transform) - keyL ^= state.tmp[0]; - keyR ^= state.tmp[1]; - var s = utils.substitute(keyL, keyR); - var f = utils.permute(s); +Cipher.prototype._update = function (data) { + this._cache.add(data) + var chunk + var thing + var out = [] - var t = r; - r = (l ^ f) >>> 0; - l = t; + while ((chunk = this._cache.get())) { + thing = this._mode.encrypt(this, chunk) + out.push(thing) } - // Reverse Initial Permutation - utils.rip(r, l, out, off); -}; + return Buffer.concat(out) +} -DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) { - var l = rStart; - var r = lStart; +var PADDING = Buffer.alloc(16, 0x10) - // Apply f() x16 times - for (var i = state.keys.length - 2; i >= 0; i -= 2) { - var keyL = state.keys[i]; - var keyR = state.keys[i + 1]; +Cipher.prototype._final = function () { + var chunk = this._cache.flush() + if (this._autopadding) { + chunk = this._mode.encrypt(this, chunk) + this._cipher.scrub() + return chunk + } - // f(r, k) - utils.expand(l, state.tmp, 0); + if (!chunk.equals(PADDING)) { + this._cipher.scrub() + throw new Error('data not multiple of block length') + } +} - keyL ^= state.tmp[0]; - keyR ^= state.tmp[1]; - var s = utils.substitute(keyL, keyR); - var f = utils.permute(s); +Cipher.prototype.setAutoPadding = function (setTo) { + this._autopadding = !!setTo + return this +} - var t = l; - l = (r ^ f) >>> 0; - r = t; +function Splitter () { + this.cache = Buffer.allocUnsafe(0) +} + +Splitter.prototype.add = function (data) { + this.cache = Buffer.concat([this.cache, data]) +} + +Splitter.prototype.get = function () { + if (this.cache.length > 15) { + var out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out } + return null +} - // Reverse Initial Permutation - utils.rip(l, r, out, off); -}; +Splitter.prototype.flush = function () { + var len = 16 - this.cache.length + var padBuff = Buffer.allocUnsafe(len) -},{"./cipher":116,"./utils":119,"inherits":175,"minimalistic-assert":182}],118:[function(require,module,exports){ -'use strict'; + var i = -1 + while (++i < len) { + padBuff.writeUInt8(len, i) + } -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); + return Buffer.concat([this.cache, padBuff]) +} -var Cipher = require('./cipher'); -var DES = require('./des'); +function createCipheriv (suite, password, iv) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') -function EDEState(type, key) { - assert.equal(key.length, 24, 'Invalid key length'); + if (typeof password === 'string') password = Buffer.from(password) + if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) - var k1 = key.slice(0, 8); - var k2 = key.slice(8, 16); - var k3 = key.slice(16, 24); + if (typeof iv === 'string') iv = Buffer.from(iv) + if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) - if (type === 'encrypt') { - this.ciphers = [ - DES.create({ type: 'encrypt', key: k1 }), - DES.create({ type: 'decrypt', key: k2 }), - DES.create({ type: 'encrypt', key: k3 }) - ]; - } else { - this.ciphers = [ - DES.create({ type: 'decrypt', key: k3 }), - DES.create({ type: 'encrypt', key: k2 }), - DES.create({ type: 'decrypt', key: k1 }) - ]; + if (config.type === 'stream') { + return new StreamCipher(config.module, password, iv) + } else if (config.type === 'auth') { + return new AuthCipher(config.module, password, iv) } + + return new Cipher(config.module, password, iv) } -function EDE(options) { - Cipher.call(this, options); +function createCipher (suite, password) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - var state = new EDEState(this.type, this.options.key); - this._edeState = state; + var keys = ebtk(password, false, config.key, config.iv) + return createCipheriv(suite, keys.key, keys.iv) } -inherits(EDE, Cipher); - -module.exports = EDE; -EDE.create = function create(options) { - return new EDE(options); -}; +exports.createCipheriv = createCipheriv +exports.createCipher = createCipher -EDE.prototype._update = function _update(inp, inOff, out, outOff) { - var state = this._edeState; +},{"./aes":83,"./authCipher":84,"./modes":96,"./streamCipher":99,"cipher-base":130,"evp_bytestokey":188,"inherits":224,"safe-buffer":277}],88:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var ZEROES = Buffer.alloc(16, 0) - state.ciphers[0]._update(inp, inOff, out, outOff); - state.ciphers[1]._update(out, outOff, out, outOff); - state.ciphers[2]._update(out, outOff, out, outOff); -}; +function toArray (buf) { + return [ + buf.readUInt32BE(0), + buf.readUInt32BE(4), + buf.readUInt32BE(8), + buf.readUInt32BE(12) + ] +} -EDE.prototype._pad = DES.prototype._pad; -EDE.prototype._unpad = DES.prototype._unpad; +function fromArray (out) { + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0] >>> 0, 0) + buf.writeUInt32BE(out[1] >>> 0, 4) + buf.writeUInt32BE(out[2] >>> 0, 8) + buf.writeUInt32BE(out[3] >>> 0, 12) + return buf +} -},{"./cipher":116,"./des":117,"inherits":175,"minimalistic-assert":182}],119:[function(require,module,exports){ -'use strict'; +function GHASH (key) { + this.h = key + this.state = Buffer.alloc(16, 0) + this.cache = Buffer.allocUnsafe(0) +} -exports.readUInt32BE = function readUInt32BE(bytes, off) { - var res = (bytes[0 + off] << 24) | - (bytes[1 + off] << 16) | - (bytes[2 + off] << 8) | - bytes[3 + off]; - return res >>> 0; -}; +// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html +// by Juho Vähä-Herttua +GHASH.prototype.ghash = function (block) { + var i = -1 + while (++i < block.length) { + this.state[i] ^= block[i] + } + this._multiply() +} -exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) { - bytes[0 + off] = value >>> 24; - bytes[1 + off] = (value >>> 16) & 0xff; - bytes[2 + off] = (value >>> 8) & 0xff; - bytes[3 + off] = value & 0xff; -}; +GHASH.prototype._multiply = function () { + var Vi = toArray(this.h) + var Zi = [0, 0, 0, 0] + var j, xi, lsbVi + var i = -1 + while (++i < 128) { + xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0 + if (xi) { + // Z_i+1 = Z_i ^ V_i + Zi[0] ^= Vi[0] + Zi[1] ^= Vi[1] + Zi[2] ^= Vi[2] + Zi[3] ^= Vi[3] + } -exports.ip = function ip(inL, inR, out, off) { - var outL = 0; - var outR = 0; + // Store the value of LSB(V_i) + lsbVi = (Vi[3] & 1) !== 0 - for (var i = 6; i >= 0; i -= 2) { - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >>> (j + i)) & 1; + // V_i+1 = V_i >> 1 + for (j = 3; j > 0; j--) { + Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31) } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inL >>> (j + i)) & 1; + Vi[0] = Vi[0] >>> 1 + + // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R + if (lsbVi) { + Vi[0] = Vi[0] ^ (0xe1 << 24) } } + this.state = fromArray(Zi) +} - for (var i = 6; i >= 0; i -= 2) { - for (var j = 1; j <= 25; j += 8) { - outR <<= 1; - outR |= (inR >>> (j + i)) & 1; - } - for (var j = 1; j <= 25; j += 8) { - outR <<= 1; - outR |= (inL >>> (j + i)) & 1; - } +GHASH.prototype.update = function (buf) { + this.cache = Buffer.concat([this.cache, buf]) + var chunk + while (this.cache.length >= 16) { + chunk = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + this.ghash(chunk) } +} - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; +GHASH.prototype.final = function (abl, bl) { + if (this.cache.length) { + this.ghash(Buffer.concat([this.cache, ZEROES], 16)) + } -exports.rip = function rip(inL, inR, out, off) { - var outL = 0; - var outR = 0; + this.ghash(fromArray([0, abl, 0, bl])) + return this.state +} - for (var i = 0; i < 4; i++) { - for (var j = 24; j >= 0; j -= 8) { - outL <<= 1; - outL |= (inR >>> (j + i)) & 1; - outL <<= 1; - outL |= (inL >>> (j + i)) & 1; - } - } - for (var i = 4; i < 8; i++) { - for (var j = 24; j >= 0; j -= 8) { - outR <<= 1; - outR |= (inR >>> (j + i)) & 1; - outR <<= 1; - outR |= (inL >>> (j + i)) & 1; +module.exports = GHASH + +},{"safe-buffer":277}],89:[function(require,module,exports){ +function incr32 (iv) { + var len = iv.length + var item + while (len--) { + item = iv.readUInt8(len) + if (item === 255) { + iv.writeUInt8(0, len) + } else { + item++ + iv.writeUInt8(item, len) + break } } +} +module.exports = incr32 - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; +},{}],90:[function(require,module,exports){ +var xor = require('buffer-xor') -exports.pc1 = function pc1(inL, inR, out, off) { - var outL = 0; - var outR = 0; +exports.encrypt = function (self, block) { + var data = xor(block, self._prev) - // 7, 15, 23, 31, 39, 47, 55, 63 - // 6, 14, 22, 30, 39, 47, 55, 63 - // 5, 13, 21, 29, 39, 47, 55, 63 - // 4, 12, 20, 28 - for (var i = 7; i >= 5; i--) { - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >> (j + i)) & 1; - } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inL >> (j + i)) & 1; - } - } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >> (j + i)) & 1; - } + self._prev = self._cipher.encryptBlock(data) + return self._prev +} - // 1, 9, 17, 25, 33, 41, 49, 57 - // 2, 10, 18, 26, 34, 42, 50, 58 - // 3, 11, 19, 27, 35, 43, 51, 59 - // 36, 44, 52, 60 - for (var i = 1; i <= 3; i++) { - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inR >> (j + i)) & 1; - } - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inL >> (j + i)) & 1; - } - } - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inL >> (j + i)) & 1; - } +exports.decrypt = function (self, block) { + var pad = self._prev - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; + self._prev = block + var out = self._cipher.decryptBlock(block) -exports.r28shl = function r28shl(num, shift) { - return ((num << shift) & 0xfffffff) | (num >>> (28 - shift)); -}; + return xor(out, pad) +} -var pc2table = [ - // inL => outL - 14, 11, 17, 4, 27, 23, 25, 0, - 13, 22, 7, 18, 5, 9, 16, 24, - 2, 20, 12, 21, 1, 8, 15, 26, +},{"buffer-xor":128}],91:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var xor = require('buffer-xor') - // inR => outR - 15, 4, 25, 19, 9, 1, 26, 16, - 5, 11, 23, 8, 12, 7, 17, 0, - 22, 3, 10, 14, 6, 20, 27, 24 -]; +function encryptStart (self, data, decrypt) { + var len = data.length + var out = xor(data, self._cache) + self._cache = self._cache.slice(len) + self._prev = Buffer.concat([self._prev, decrypt ? data : out]) + return out +} -exports.pc2 = function pc2(inL, inR, out, off) { - var outL = 0; - var outR = 0; +exports.encrypt = function (self, data, decrypt) { + var out = Buffer.allocUnsafe(0) + var len - var len = pc2table.length >>> 1; - for (var i = 0; i < len; i++) { - outL <<= 1; - outL |= (inL >>> pc2table[i]) & 0x1; - } - for (var i = len; i < pc2table.length; i++) { - outR <<= 1; - outR |= (inR >>> pc2table[i]) & 0x1; + while (data.length) { + if (self._cache.length === 0) { + self._cache = self._cipher.encryptBlock(self._prev) + self._prev = Buffer.allocUnsafe(0) + } + + if (self._cache.length <= data.length) { + len = self._cache.length + out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)]) + data = data.slice(len) + } else { + out = Buffer.concat([out, encryptStart(self, data, decrypt)]) + break + } } - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; + return out +} -exports.expand = function expand(r, out, off) { - var outL = 0; - var outR = 0; +},{"buffer-xor":128,"safe-buffer":277}],92:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer - outL = ((r & 1) << 5) | (r >>> 27); - for (var i = 23; i >= 15; i -= 4) { - outL <<= 6; - outL |= (r >>> i) & 0x3f; - } - for (var i = 11; i >= 3; i -= 4) { - outR |= (r >>> i) & 0x3f; - outR <<= 6; +function encryptByte (self, byteParam, decrypt) { + var pad + var i = -1 + var len = 8 + var out = 0 + var bit, value + while (++i < len) { + pad = self._cipher.encryptBlock(self._prev) + bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0 + value = pad[0] ^ bit + out += ((value & 0x80) >> (i % 8)) + self._prev = shiftIn(self._prev, decrypt ? bit : value) } - outR |= ((r & 0x1f) << 1) | (r >>> 31); + return out +} - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; +function shiftIn (buffer, value) { + var len = buffer.length + var i = -1 + var out = Buffer.allocUnsafe(buffer.length) + buffer = Buffer.concat([buffer, Buffer.from([value])]) -var sTable = [ - 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, - 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, - 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, - 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, + while (++i < len) { + out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) + } - 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, - 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, - 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, - 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, + return out +} - 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, - 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, - 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, - 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, +exports.encrypt = function (self, chunk, decrypt) { + var len = chunk.length + var out = Buffer.allocUnsafe(len) + var i = -1 - 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, - 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, - 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, - 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, + while (++i < len) { + out[i] = encryptByte(self, chunk[i], decrypt) + } - 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, - 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, - 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, - 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, + return out +} - 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, - 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, - 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, - 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, +},{"safe-buffer":277}],93:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer - 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, - 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, - 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, - 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, +function encryptByte (self, byteParam, decrypt) { + var pad = self._cipher.encryptBlock(self._prev) + var out = pad[0] ^ byteParam - 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, - 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, - 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, - 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 -]; + self._prev = Buffer.concat([ + self._prev.slice(1), + Buffer.from([decrypt ? byteParam : out]) + ]) -exports.substitute = function substitute(inL, inR) { - var out = 0; - for (var i = 0; i < 4; i++) { - var b = (inL >>> (18 - i * 6)) & 0x3f; - var sb = sTable[i * 0x40 + b]; - - out <<= 4; - out |= sb; - } - for (var i = 0; i < 4; i++) { - var b = (inR >>> (18 - i * 6)) & 0x3f; - var sb = sTable[4 * 0x40 + i * 0x40 + b]; - - out <<= 4; - out |= sb; - } - return out >>> 0; -}; + return out +} -var permuteTable = [ - 16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22, - 30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7 -]; +exports.encrypt = function (self, chunk, decrypt) { + var len = chunk.length + var out = Buffer.allocUnsafe(len) + var i = -1 -exports.permute = function permute(num) { - var out = 0; - for (var i = 0; i < permuteTable.length; i++) { - out <<= 1; - out |= (num >>> permuteTable[i]) & 0x1; + while (++i < len) { + out[i] = encryptByte(self, chunk[i], decrypt) } - return out >>> 0; -}; - -exports.padSplit = function padSplit(num, size, group) { - var str = num.toString(2); - while (str.length < size) - str = '0' + str; - var out = []; - for (var i = 0; i < size; i += group) - out.push(str.slice(i, i + group)); - return out.join(' '); -}; + return out +} -},{}],120:[function(require,module,exports){ -(function (Buffer){ -var generatePrime = require('./lib/generatePrime') -var primes = require('./lib/primes.json') +},{"safe-buffer":277}],94:[function(require,module,exports){ +var xor = require('buffer-xor') +var Buffer = require('safe-buffer').Buffer +var incr32 = require('../incr32') -var DH = require('./lib/dh') +function getBlock (self) { + var out = self._cipher.encryptBlockRaw(self._prev) + incr32(self._prev) + return out +} -function getDiffieHellman (mod) { - var prime = new Buffer(primes[mod].prime, 'hex') - var gen = new Buffer(primes[mod].gen, 'hex') +var blockSize = 16 +exports.encrypt = function (self, chunk) { + var chunkNum = Math.ceil(chunk.length / blockSize) + var start = self._cache.length + self._cache = Buffer.concat([ + self._cache, + Buffer.allocUnsafe(chunkNum * blockSize) + ]) + for (var i = 0; i < chunkNum; i++) { + var out = getBlock(self) + var offset = start + i * blockSize + self._cache.writeUInt32BE(out[0], offset + 0) + self._cache.writeUInt32BE(out[1], offset + 4) + self._cache.writeUInt32BE(out[2], offset + 8) + self._cache.writeUInt32BE(out[3], offset + 12) + } + var pad = self._cache.slice(0, chunk.length) + self._cache = self._cache.slice(chunk.length) + return xor(chunk, pad) +} - return new DH(prime, gen) +},{"../incr32":89,"buffer-xor":128,"safe-buffer":277}],95:[function(require,module,exports){ +exports.encrypt = function (self, block) { + return self._cipher.encryptBlock(block) } -var ENCODINGS = { - 'binary': true, 'hex': true, 'base64': true +exports.decrypt = function (self, block) { + return self._cipher.decryptBlock(block) } -function createDiffieHellman (prime, enc, generator, genc) { - if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) { - return createDiffieHellman(prime, 'binary', enc, generator) - } +},{}],96:[function(require,module,exports){ +var modeModules = { + ECB: require('./ecb'), + CBC: require('./cbc'), + CFB: require('./cfb'), + CFB8: require('./cfb8'), + CFB1: require('./cfb1'), + OFB: require('./ofb'), + CTR: require('./ctr'), + GCM: require('./ctr') +} - enc = enc || 'binary' - genc = genc || 'binary' - generator = generator || new Buffer([2]) +var modes = require('./list.json') - if (!Buffer.isBuffer(generator)) { - generator = new Buffer(generator, genc) - } +for (var key in modes) { + modes[key].module = modeModules[modes[key].mode] +} - if (typeof prime === 'number') { - return new DH(generatePrime(prime, generator), generator, true) - } +module.exports = modes - if (!Buffer.isBuffer(prime)) { - prime = new Buffer(prime, enc) +},{"./cbc":90,"./cfb":91,"./cfb1":92,"./cfb8":93,"./ctr":94,"./ecb":95,"./list.json":97,"./ofb":98}],97:[function(require,module,exports){ +module.exports={ + "aes-128-ecb": { + "cipher": "AES", + "key": 128, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-192-ecb": { + "cipher": "AES", + "key": 192, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-256-ecb": { + "cipher": "AES", + "key": 256, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-128-cbc": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-192-cbc": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-256-cbc": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes128": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes192": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes256": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-128-cfb": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-192-cfb": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-256-cfb": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-128-cfb8": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-192-cfb8": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-256-cfb8": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-128-cfb1": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-192-cfb1": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-256-cfb1": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-128-ofb": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-192-ofb": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-256-ofb": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-128-ctr": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-192-ctr": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-256-ctr": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-128-gcm": { + "cipher": "AES", + "key": 128, + "iv": 12, + "mode": "GCM", + "type": "auth" + }, + "aes-192-gcm": { + "cipher": "AES", + "key": 192, + "iv": 12, + "mode": "GCM", + "type": "auth" + }, + "aes-256-gcm": { + "cipher": "AES", + "key": 256, + "iv": 12, + "mode": "GCM", + "type": "auth" } - - return new DH(prime, generator, true) } -exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman -exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman - -}).call(this,require("buffer").Buffer) - -},{"./lib/dh":121,"./lib/generatePrime":122,"./lib/primes.json":123,"buffer":102}],121:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ (function (Buffer){ -var BN = require('bn.js'); -var MillerRabin = require('miller-rabin'); -var millerRabin = new MillerRabin(); -var TWENTYFOUR = new BN(24); -var ELEVEN = new BN(11); -var TEN = new BN(10); -var THREE = new BN(3); -var SEVEN = new BN(7); -var primes = require('./generatePrime'); -var randomBytes = require('randombytes'); -module.exports = DH; +var xor = require('buffer-xor') -function setPublicKey(pub, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(pub)) { - pub = new Buffer(pub, enc); - } - this._pub = new BN(pub); - return this; +function getBlock (self) { + self._prev = self._cipher.encryptBlock(self._prev) + return self._prev } -function setPrivateKey(priv, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(priv)) { - priv = new Buffer(priv, enc); +exports.encrypt = function (self, chunk) { + while (self._cache.length < chunk.length) { + self._cache = Buffer.concat([self._cache, getBlock(self)]) } - this._priv = new BN(priv); - return this; + + var pad = self._cache.slice(0, chunk.length) + self._cache = self._cache.slice(chunk.length) + return xor(chunk, pad) } -var primeCache = {}; -function checkPrime(prime, generator) { - var gen = generator.toString('hex'); - var hex = [gen, prime.toString(16)].join('_'); - if (hex in primeCache) { - return primeCache[hex]; - } - var error = 0; +}).call(this,require("buffer").Buffer) - if (prime.isEven() || - !primes.simpleSieve || - !primes.fermatTest(prime) || - !millerRabin.test(prime)) { - //not a prime so +1 - error += 1; +},{"buffer":129,"buffer-xor":128}],99:[function(require,module,exports){ +var aes = require('./aes') +var Buffer = require('safe-buffer').Buffer +var Transform = require('cipher-base') +var inherits = require('inherits') - if (gen === '02' || gen === '05') { - // we'd be able to check the generator - // it would fail so +8 - error += 8; - } else { - //we wouldn't be able to test the generator - // so +4 - error += 4; - } - primeCache[hex] = error; - return error; - } - if (!millerRabin.test(prime.shrn(1))) { - //not a safe prime - error += 2; - } - var rem; - switch (gen) { - case '02': - if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { - // unsuidable generator - error += 8; - } - break; - case '05': - rem = prime.mod(TEN); - if (rem.cmp(THREE) && rem.cmp(SEVEN)) { - // prime mod 10 needs to equal 3 or 7 - error += 8; - } - break; - default: - error += 4; - } - primeCache[hex] = error; - return error; -} +function StreamCipher (mode, key, iv, decrypt) { + Transform.call(this) -function DH(prime, generator, malleable) { - this.setGenerator(generator); - this.__prime = new BN(prime); - this._prime = BN.mont(this.__prime); - this._primeLen = prime.length; - this._pub = undefined; - this._priv = undefined; - this._primeCode = undefined; - if (malleable) { - this.setPublicKey = setPublicKey; - this.setPrivateKey = setPrivateKey; - } else { - this._primeCode = 8; - } + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._cache = Buffer.allocUnsafe(0) + this._secCache = Buffer.allocUnsafe(0) + this._decrypt = decrypt + this._mode = mode } -Object.defineProperty(DH.prototype, 'verifyError', { - enumerable: true, - get: function () { - if (typeof this._primeCode !== 'number') { - this._primeCode = checkPrime(this.__prime, this.__gen); - } - return this._primeCode; - } -}); -DH.prototype.generateKeys = function () { - if (!this._priv) { - this._priv = new BN(randomBytes(this._primeLen)); - } - this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); - return this.getPublicKey(); -}; -DH.prototype.computeSecret = function (other) { - other = new BN(other); - other = other.toRed(this._prime); - var secret = other.redPow(this._priv).fromRed(); - var out = new Buffer(secret.toArray()); - var prime = this.getPrime(); - if (out.length < prime.length) { - var front = new Buffer(prime.length - out.length); - front.fill(0); - out = Buffer.concat([front, out]); - } - return out; -}; +inherits(StreamCipher, Transform) -DH.prototype.getPublicKey = function getPublicKey(enc) { - return formatReturnValue(this._pub, enc); -}; +StreamCipher.prototype._update = function (chunk) { + return this._mode.encrypt(this, chunk, this._decrypt) +} -DH.prototype.getPrivateKey = function getPrivateKey(enc) { - return formatReturnValue(this._priv, enc); -}; +StreamCipher.prototype._final = function () { + this._cipher.scrub() +} -DH.prototype.getPrime = function (enc) { - return formatReturnValue(this.__prime, enc); -}; +module.exports = StreamCipher -DH.prototype.getGenerator = function (enc) { - return formatReturnValue(this._gen, enc); -}; +},{"./aes":83,"cipher-base":130,"inherits":224,"safe-buffer":277}],100:[function(require,module,exports){ +var DES = require('browserify-des') +var aes = require('browserify-aes/browser') +var aesModes = require('browserify-aes/modes') +var desModes = require('browserify-des/modes') +var ebtk = require('evp_bytestokey') -DH.prototype.setGenerator = function (gen, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(gen)) { - gen = new Buffer(gen, enc); - } - this.__gen = gen; - this._gen = new BN(gen); - return this; -}; +function createCipher (suite, password) { + suite = suite.toLowerCase() -function formatReturnValue(bn, enc) { - var buf = new Buffer(bn.toArray()); - if (!enc) { - return buf; + var keyLen, ivLen + if (aesModes[suite]) { + keyLen = aesModes[suite].key + ivLen = aesModes[suite].iv + } else if (desModes[suite]) { + keyLen = desModes[suite].key * 8 + ivLen = desModes[suite].iv } else { - return buf.toString(enc); + throw new TypeError('invalid suite type') } -} -}).call(this,require("buffer").Buffer) + var keys = ebtk(password, false, keyLen, ivLen) + return createCipheriv(suite, keys.key, keys.iv) +} -},{"./generatePrime":122,"bn.js":71,"buffer":102,"miller-rabin":181,"randombytes":205}],122:[function(require,module,exports){ -var randomBytes = require('randombytes'); -module.exports = findPrime; -findPrime.simpleSieve = simpleSieve; -findPrime.fermatTest = fermatTest; -var BN = require('bn.js'); -var TWENTYFOUR = new BN(24); -var MillerRabin = require('miller-rabin'); -var millerRabin = new MillerRabin(); -var ONE = new BN(1); -var TWO = new BN(2); -var FIVE = new BN(5); -var SIXTEEN = new BN(16); -var EIGHT = new BN(8); -var TEN = new BN(10); -var THREE = new BN(3); -var SEVEN = new BN(7); -var ELEVEN = new BN(11); -var FOUR = new BN(4); -var TWELVE = new BN(12); -var primes = null; +function createDecipher (suite, password) { + suite = suite.toLowerCase() -function _getPrimes() { - if (primes !== null) - return primes; + var keyLen, ivLen + if (aesModes[suite]) { + keyLen = aesModes[suite].key + ivLen = aesModes[suite].iv + } else if (desModes[suite]) { + keyLen = desModes[suite].key * 8 + ivLen = desModes[suite].iv + } else { + throw new TypeError('invalid suite type') + } - var limit = 0x100000; - var res = []; - res[0] = 2; - for (var i = 1, k = 3; k < limit; k += 2) { - var sqrt = Math.ceil(Math.sqrt(k)); - for (var j = 0; j < i && res[j] <= sqrt; j++) - if (k % res[j] === 0) - break; + var keys = ebtk(password, false, keyLen, ivLen) + return createDecipheriv(suite, keys.key, keys.iv) +} - if (i !== j && res[j] <= sqrt) - continue; +function createCipheriv (suite, key, iv) { + suite = suite.toLowerCase() + if (aesModes[suite]) return aes.createCipheriv(suite, key, iv) + if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite }) - res[i++] = k; - } - primes = res; - return res; + throw new TypeError('invalid suite type') } -function simpleSieve(p) { - var primes = _getPrimes(); - - for (var i = 0; i < primes.length; i++) - if (p.modn(primes[i]) === 0) { - if (p.cmpn(primes[i]) === 0) { - return true; - } else { - return false; - } - } +function createDecipheriv (suite, key, iv) { + suite = suite.toLowerCase() + if (aesModes[suite]) return aes.createDecipheriv(suite, key, iv) + if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite, decrypt: true }) - return true; + throw new TypeError('invalid suite type') } -function fermatTest(p) { - var red = BN.mont(p); - return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0; +function getCiphers () { + return Object.keys(desModes).concat(aes.getCiphers()) } -function findPrime(bits, gen) { - if (bits < 16) { - // this is what openssl does - if (gen === 2 || gen === 5) { - return new BN([0x8c, 0x7b]); - } else { - return new BN([0x8c, 0x27]); - } - } - gen = new BN(gen); +exports.createCipher = exports.Cipher = createCipher +exports.createCipheriv = exports.Cipheriv = createCipheriv +exports.createDecipher = exports.Decipher = createDecipher +exports.createDecipheriv = exports.Decipheriv = createDecipheriv +exports.listCiphers = exports.getCiphers = getCiphers - var num, n2; +},{"browserify-aes/browser":85,"browserify-aes/modes":96,"browserify-des":101,"browserify-des/modes":102,"evp_bytestokey":188}],101:[function(require,module,exports){ +var CipherBase = require('cipher-base') +var des = require('des.js') +var inherits = require('inherits') +var Buffer = require('safe-buffer').Buffer - while (true) { - num = new BN(randomBytes(Math.ceil(bits / 8))); - while (num.bitLength() > bits) { - num.ishrn(1); - } - if (num.isEven()) { - num.iadd(ONE); - } - if (!num.testn(1)) { - num.iadd(TWO); - } - if (!gen.cmp(TWO)) { - while (num.mod(TWENTYFOUR).cmp(ELEVEN)) { - num.iadd(FOUR); - } - } else if (!gen.cmp(FIVE)) { - while (num.mod(TEN).cmp(THREE)) { - num.iadd(FOUR); - } - } - n2 = num.shrn(1); - if (simpleSieve(n2) && simpleSieve(num) && - fermatTest(n2) && fermatTest(num) && - millerRabin.test(n2) && millerRabin.test(num)) { - return num; - } +var modes = { + 'des-ede3-cbc': des.CBC.instantiate(des.EDE), + 'des-ede3': des.EDE, + 'des-ede-cbc': des.CBC.instantiate(des.EDE), + 'des-ede': des.EDE, + 'des-cbc': des.CBC.instantiate(des.DES), + 'des-ecb': des.DES +} +modes.des = modes['des-cbc'] +modes.des3 = modes['des-ede3-cbc'] +module.exports = DES +inherits(DES, CipherBase) +function DES (opts) { + CipherBase.call(this) + var modeName = opts.mode.toLowerCase() + var mode = modes[modeName] + var type + if (opts.decrypt) { + type = 'decrypt' + } else { + type = 'encrypt' + } + var key = opts.key + if (!Buffer.isBuffer(key)) { + key = Buffer.from(key) + } + if (modeName === 'des-ede' || modeName === 'des-ede-cbc') { + key = Buffer.concat([key, key.slice(0, 8)]) + } + var iv = opts.iv + if (!Buffer.isBuffer(iv)) { + iv = Buffer.from(iv) } + this._des = mode.create({ + key: key, + iv: iv, + type: type + }) +} +DES.prototype._update = function (data) { + return Buffer.from(this._des.update(data)) +} +DES.prototype._final = function () { + return Buffer.from(this._des.final()) +} +},{"cipher-base":130,"des.js":142,"inherits":224,"safe-buffer":277}],102:[function(require,module,exports){ +exports['des-ecb'] = { + key: 8, + iv: 0 +} +exports['des-cbc'] = exports.des = { + key: 8, + iv: 8 +} +exports['des-ede3-cbc'] = exports.des3 = { + key: 24, + iv: 8 +} +exports['des-ede3'] = { + key: 24, + iv: 0 +} +exports['des-ede-cbc'] = { + key: 16, + iv: 8 +} +exports['des-ede'] = { + key: 16, + iv: 0 } -},{"bn.js":71,"miller-rabin":181,"randombytes":205}],123:[function(require,module,exports){ -module.exports={ - "modp1": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff" - }, - "modp2": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff" - }, - "modp5": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff" - }, - "modp14": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff" - }, - "modp15": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff" - }, - "modp16": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff" - }, - "modp17": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff" - }, - "modp18": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff" - } +},{}],103:[function(require,module,exports){ +(function (Buffer){ +var bn = require('bn.js'); +var randomBytes = require('randombytes'); +module.exports = crt; +function blind(priv) { + var r = getr(priv); + var blinder = r.toRed(bn.mont(priv.modulus)) + .redPow(new bn(priv.publicExponent)).fromRed(); + return { + blinder: blinder, + unblinder:r.invm(priv.modulus) + }; +} +function crt(msg, priv) { + var blinds = blind(priv); + var len = priv.modulus.byteLength(); + var mod = bn.mont(priv.modulus); + var blinded = new bn(msg).mul(blinds.blinder).umod(priv.modulus); + var c1 = blinded.toRed(bn.mont(priv.prime1)); + var c2 = blinded.toRed(bn.mont(priv.prime2)); + var qinv = priv.coefficient; + var p = priv.prime1; + var q = priv.prime2; + var m1 = c1.redPow(priv.exponent1); + var m2 = c2.redPow(priv.exponent2); + m1 = m1.fromRed(); + m2 = m2.fromRed(); + var h = m1.isub(m2).imul(qinv).umod(p); + h.imul(q); + m2.iadd(h); + return new Buffer(m2.imul(blinds.unblinder).umod(priv.modulus).toArray(false, len)); +} +crt.getr = getr; +function getr(priv) { + var len = priv.modulus.byteLength(); + var r = new bn(randomBytes(len)); + while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) { + r = new bn(randomBytes(len)); + } + return r; } -},{}],124:[function(require,module,exports){ -'use strict'; -var elliptic = exports; +}).call(this,require("buffer").Buffer) -elliptic.version = require('../package.json').version; -elliptic.utils = require('./elliptic/utils'); -elliptic.rand = require('brorand'); -elliptic.curve = require('./elliptic/curve'); -elliptic.curves = require('./elliptic/curves'); +},{"bn.js":104,"buffer":129,"randombytes":260}],104:[function(require,module,exports){ +arguments[4][75][0].apply(exports,arguments) +},{"buffer":82,"dup":75}],105:[function(require,module,exports){ +module.exports = require('./browser/algorithms.json') -// Protocols -elliptic.ec = require('./elliptic/ec'); -elliptic.eddsa = require('./elliptic/eddsa'); +},{"./browser/algorithms.json":106}],106:[function(require,module,exports){ +module.exports={ + "sha224WithRSAEncryption": { + "sign": "rsa", + "hash": "sha224", + "id": "302d300d06096086480165030402040500041c" + }, + "RSA-SHA224": { + "sign": "ecdsa/rsa", + "hash": "sha224", + "id": "302d300d06096086480165030402040500041c" + }, + "sha256WithRSAEncryption": { + "sign": "rsa", + "hash": "sha256", + "id": "3031300d060960864801650304020105000420" + }, + "RSA-SHA256": { + "sign": "ecdsa/rsa", + "hash": "sha256", + "id": "3031300d060960864801650304020105000420" + }, + "sha384WithRSAEncryption": { + "sign": "rsa", + "hash": "sha384", + "id": "3041300d060960864801650304020205000430" + }, + "RSA-SHA384": { + "sign": "ecdsa/rsa", + "hash": "sha384", + "id": "3041300d060960864801650304020205000430" + }, + "sha512WithRSAEncryption": { + "sign": "rsa", + "hash": "sha512", + "id": "3051300d060960864801650304020305000440" + }, + "RSA-SHA512": { + "sign": "ecdsa/rsa", + "hash": "sha512", + "id": "3051300d060960864801650304020305000440" + }, + "RSA-SHA1": { + "sign": "rsa", + "hash": "sha1", + "id": "3021300906052b0e03021a05000414" + }, + "ecdsa-with-SHA1": { + "sign": "ecdsa", + "hash": "sha1", + "id": "" + }, + "sha256": { + "sign": "ecdsa", + "hash": "sha256", + "id": "" + }, + "sha224": { + "sign": "ecdsa", + "hash": "sha224", + "id": "" + }, + "sha384": { + "sign": "ecdsa", + "hash": "sha384", + "id": "" + }, + "sha512": { + "sign": "ecdsa", + "hash": "sha512", + "id": "" + }, + "DSA-SHA": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA-SHA1": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA-WITH-SHA224": { + "sign": "dsa", + "hash": "sha224", + "id": "" + }, + "DSA-SHA224": { + "sign": "dsa", + "hash": "sha224", + "id": "" + }, + "DSA-WITH-SHA256": { + "sign": "dsa", + "hash": "sha256", + "id": "" + }, + "DSA-SHA256": { + "sign": "dsa", + "hash": "sha256", + "id": "" + }, + "DSA-WITH-SHA384": { + "sign": "dsa", + "hash": "sha384", + "id": "" + }, + "DSA-SHA384": { + "sign": "dsa", + "hash": "sha384", + "id": "" + }, + "DSA-WITH-SHA512": { + "sign": "dsa", + "hash": "sha512", + "id": "" + }, + "DSA-SHA512": { + "sign": "dsa", + "hash": "sha512", + "id": "" + }, + "DSA-RIPEMD160": { + "sign": "dsa", + "hash": "rmd160", + "id": "" + }, + "ripemd160WithRSA": { + "sign": "rsa", + "hash": "rmd160", + "id": "3021300906052b2403020105000414" + }, + "RSA-RIPEMD160": { + "sign": "rsa", + "hash": "rmd160", + "id": "3021300906052b2403020105000414" + }, + "md5WithRSAEncryption": { + "sign": "rsa", + "hash": "md5", + "id": "3020300c06082a864886f70d020505000410" + }, + "RSA-MD5": { + "sign": "rsa", + "hash": "md5", + "id": "3020300c06082a864886f70d020505000410" + } +} -},{"../package.json":139,"./elliptic/curve":127,"./elliptic/curves":130,"./elliptic/ec":131,"./elliptic/eddsa":134,"./elliptic/utils":138,"brorand":72}],125:[function(require,module,exports){ -'use strict'; +},{}],107:[function(require,module,exports){ +module.exports={ + "1.3.132.0.10": "secp256k1", + "1.3.132.0.33": "p224", + "1.2.840.10045.3.1.1": "p192", + "1.2.840.10045.3.1.7": "p256", + "1.3.132.0.34": "p384", + "1.3.132.0.35": "p521" +} -var BN = require('bn.js'); -var utils = require('../utils'); -var getNAF = utils.getNAF; -var getJSF = utils.getJSF; -var assert = utils.assert; +},{}],108:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var createHash = require('create-hash') +var stream = require('readable-stream') +var inherits = require('inherits') +var sign = require('./sign') +var verify = require('./verify') -function BaseCurve(type, conf) { - this.type = type; - this.p = new BN(conf.p, 16); +var algorithms = require('./algorithms.json') +Object.keys(algorithms).forEach(function (key) { + algorithms[key].id = Buffer.from(algorithms[key].id, 'hex') + algorithms[key.toLowerCase()] = algorithms[key] +}) - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); +function Sign (algorithm) { + stream.Writable.call(this) - // Useful for many curves - this.zero = new BN(0).toRed(this.red); - this.one = new BN(1).toRed(this.red); - this.two = new BN(2).toRed(this.red); + var data = algorithms[algorithm] + if (!data) throw new Error('Unknown message digest') - // Curve configuration, optional - this.n = conf.n && new BN(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + this._hashType = data.hash + this._hash = createHash(data.hash) + this._tag = data.id + this._signType = data.sign +} +inherits(Sign, stream.Writable) - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); +Sign.prototype._write = function _write (data, _, done) { + this._hash.update(data) + done() +} - this._bitLength = this.n ? this.n.bitLength() : 0; +Sign.prototype.update = function update (data, enc) { + if (typeof data === 'string') data = Buffer.from(data, enc) - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } + this._hash.update(data) + return this } -module.exports = BaseCurve; -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; +Sign.prototype.sign = function signMethod (key, enc) { + this.end() + var hash = this._hash.digest() + var sig = sign(hash, key, this._hashType, this._signType, this._tag) -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; + return enc ? sig.toString(enc) : sig +} -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert(p.precomputed); - var doubles = p._getDoubles(); +function Verify (algorithm) { + stream.Writable.call(this) - var naf = getNAF(k, 1, this._bitLength); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; + var data = algorithms[algorithm] + if (!data) throw new Error('Unknown message digest') - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } + this._hash = createHash(data.hash) + this._tag = data.id + this._signType = data.sign +} +inherits(Verify, stream.Writable) - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; +Verify.prototype._write = function _write (data, _, done) { + this._hash.update(data) + done() +} -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; +Verify.prototype.update = function update (data, enc) { + if (typeof data === 'string') data = Buffer.from(data, enc) - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; + this._hash.update(data) + return this +} - // Get NAF form - var naf = getNAF(k, w, this._bitLength); +Verify.prototype.verify = function verifyMethod (key, sig, enc) { + if (typeof sig === 'string') sig = Buffer.from(sig, enc) - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); + this.end() + var hash = this._hash.digest() + return verify(sig, hash, key, this._signType, this._tag) +} - if (i < 0) - break; - var z = naf[i]; - assert(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; +function createSign (algorithm) { + return new Sign(algorithm) +} -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; +function createVerify (algorithm) { + return new Verify(algorithm) +} - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } +module.exports = { + Sign: createSign, + Verify: createVerify, + createSign: createSign, + createVerify: createVerify +} - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a], this._bitLength); - naf[b] = getNAF(coeffs[b], wndWidth[b], this._bitLength); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } +},{"./algorithms.json":106,"./sign":109,"./verify":110,"create-hash":137,"inherits":111,"readable-stream":126,"safe-buffer":127}],109:[function(require,module,exports){ +// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js +var Buffer = require('safe-buffer').Buffer +var createHmac = require('create-hmac') +var crt = require('browserify-rsa') +var EC = require('elliptic').ec +var BN = require('bn.js') +var parseKeys = require('parse-asn1') +var curves = require('./curves.json') - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; +function sign (hash, key, hashType, signType, tag) { + var priv = parseKeys(key) + if (priv.curve) { + // rsa keys can be interpreted as ecdsa ones in openssl + if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') + return ecSign(hash, priv) + } else if (priv.type === 'dsa') { + if (signType !== 'dsa') throw new Error('wrong private key type') + return dsaSign(hash, priv, hashType) + } else { + if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') + } + hash = Buffer.concat([tag, hash]) + var len = priv.modulus.byteLength() + var pad = [0, 1] + while (hash.length + pad.length + 1 < len) pad.push(0xff) + pad.push(0x00) + var i = -1 + while (++i < hash.length) pad.push(hash[i]) - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } + var out = crt(pad, priv) + return out +} - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; +function ecSign (hash, priv) { + var curveId = curves[priv.curve.join('.')] + if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.')) - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; + var curve = new EC(curveId) + var key = curve.keyFromPrivate(priv.privateKey) + var out = key.sign(hash) - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; + return Buffer.from(out.toDER()) +} + +function dsaSign (hash, priv, algo) { + var x = priv.params.priv_key + var p = priv.params.p + var q = priv.params.q + var g = priv.params.g + var r = new BN(0) + var k + var H = bits2int(hash, q).mod(q) + var s = false + var kv = getKey(x, q, hash, algo) + while (s === false) { + k = makeKey(q, kv, algo) + r = makeR(g, k, p, q) + s = k.invm(q).imul(H.add(x.mul(r))).mod(q) + if (s.cmpn(0) === 0) { + s = false + r = new BN(0) } } + return toDER(r, s) +} - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; +function toDER (r, s) { + r = r.toArray() + s = s.toArray() - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; + // Pad values + if (r[0] & 0x80) r = [0].concat(r) + if (s[0] & 0x80) s = [0].concat(s) - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); + var total = r.length + s.length + 4 + var res = [0x30, total, 0x02, r.length] + res = res.concat(r, [0x02, s.length], s) + return Buffer.from(res) +} - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } +function getKey (x, q, hash, algo) { + x = Buffer.from(x.toArray()) + if (x.length < q.byteLength()) { + var zeros = Buffer.alloc(q.byteLength() - x.length) + x = Buffer.concat([zeros, x]) } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; + var hlen = hash.length + var hbits = bits2octets(hash, q) + var v = Buffer.alloc(hlen) + v.fill(1) + var k = Buffer.alloc(hlen) + k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest() + v = createHmac(algo, k).update(v).digest() + k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest() + v = createHmac(algo, k).update(v).digest() + return { k: k, v: v } +} - if (jacobianResult) - return acc; - else - return acc.toP(); -}; +function bits2int (obits, q) { + var bits = new BN(obits) + var shift = (obits.length << 3) - q.bitLength() + if (shift > 0) bits.ishrn(shift) + return bits +} -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; +function bits2octets (bits, q) { + bits = bits2int(bits, q) + bits = bits.mod(q) + var out = Buffer.from(bits.toArray()) + if (out.length < q.byteLength()) { + var zeros = Buffer.alloc(q.byteLength() - out.length) + out = Buffer.concat([zeros, out]) + } + return out } -BaseCurve.BasePoint = BasePoint; -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; +function makeKey (q, kv, algo) { + var t + var k -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; + do { + t = Buffer.alloc(0) -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils.toArray(bytes, enc); + while (t.length * 8 < q.bitLength()) { + kv.v = createHmac(algo, kv.k).update(kv.v).digest() + t = Buffer.concat([t, kv.v]) + } - var len = this.p.byteLength(); + k = bits2int(t, q) + kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest() + kv.v = createHmac(algo, kv.k).update(kv.v).digest() + } while (k.cmp(q) !== -1) - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert(bytes[bytes.length - 1] % 2 === 1); + return k +} - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); +function makeR (g, k, p, q) { + return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q) +} - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); +module.exports = sign +module.exports.getKey = getKey +module.exports.makeKey = makeKey + +},{"./curves.json":107,"bn.js":80,"browserify-rsa":103,"create-hmac":139,"elliptic":153,"parse-asn1":241,"safe-buffer":127}],110:[function(require,module,exports){ +// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js +var Buffer = require('safe-buffer').Buffer +var BN = require('bn.js') +var EC = require('elliptic').ec +var parseKeys = require('parse-asn1') +var curves = require('./curves.json') + +function verify (sig, hash, key, signType, tag) { + var pub = parseKeys(key) + if (pub.type === 'ec') { + // rsa keys can be interpreted as ecdsa ones in openssl + if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') + return ecVerify(sig, hash, pub) + } else if (pub.type === 'dsa') { + if (signType !== 'dsa') throw new Error('wrong public key type') + return dsaVerify(sig, hash, pub) + } else { + if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') } - throw new Error('Unknown point format'); -}; + hash = Buffer.concat([tag, hash]) + var len = pub.modulus.byteLength() + var pad = [1] + var padNum = 0 + while (hash.length + pad.length + 2 < len) { + pad.push(0xff) + padNum++ + } + pad.push(0x00) + var i = -1 + while (++i < hash.length) { + pad.push(hash[i]) + } + pad = Buffer.from(pad) + var red = BN.mont(pub.modulus) + sig = new BN(sig).toRed(red) -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; + sig = sig.redPow(new BN(pub.publicExponent)) + sig = Buffer.from(sig.fromRed().toArray()) + var out = padNum < 8 ? 1 : 0 + len = Math.min(sig.length, pad.length) + if (sig.length !== pad.length) out = 1 -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); + i = -1 + while (++i < len) out |= sig[i] ^ pad[i] + return out === 0 +} - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); +function ecVerify (sig, hash, pub) { + var curveId = curves[pub.data.algorithm.curve.join('.')] + if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.')) - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; -}; + var curve = new EC(curveId) + var pubkey = pub.data.subjectPrivateKey.data -BasePoint.prototype.encode = function encode(enc, compact) { - return utils.encode(this._encode(compact), enc); -}; + return curve.verify(hash, sig, pubkey) +} -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; +function dsaVerify (sig, hash, pub) { + var p = pub.data.p + var q = pub.data.q + var g = pub.data.g + var y = pub.data.pub_key + var unpacked = parseKeys.signature.decode(sig, 'der') + var s = unpacked.s + var r = unpacked.r + checkValue(s, q) + checkValue(r, q) + var montp = BN.mont(p) + var w = s.invm(q) + var v = g.toRed(montp) + .redPow(new BN(hash).mul(w).mod(q)) + .fromRed() + .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed()) + .mod(p) + .mod(q) + return v.cmp(r) === 0 +} - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; +function checkValue (b, q) { + if (b.cmpn(0) <= 0) throw new Error('invalid sig') + if (b.cmp(q) >= q) throw new Error('invalid sig') +} - return this; -}; +module.exports = verify -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; +},{"./curves.json":107,"bn.js":80,"elliptic":153,"parse-asn1":241,"safe-buffer":127}],111:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} - var doubles = this.precomputed.doubles; - if (!doubles) - return false; +},{}],112:[function(require,module,exports){ +'use strict'; - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; +var codes = {}; - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error; } - return { - step: step, - points: doubles - }; -}; -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; + function getMessage(arg1, arg2, arg3) { + if (typeof message === 'string') { + return message; + } else { + return message(arg1, arg2, arg3); + } + } - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; -}; + var NodeError = + /*#__PURE__*/ + function (_Base) { + _inheritsLoose(NodeError, _Base); -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; + function NodeError(arg1, arg2, arg3) { + return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; + } -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; + return NodeError; + }(Base); -},{"../utils":138,"bn.js":71}],126:[function(require,module,exports){ -'use strict'; + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + codes[code] = NodeError; +} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js -var utils = require('../utils'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); -var assert = utils.assert; +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + var len = expected.length; + expected = expected.map(function (i) { + return String(i); + }); -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; + if (len > 2) { + return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; + } else if (len === 2) { + return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); + } else { + return "of ".concat(thing, " ").concat(expected[0]); + } + } else { + return "of ".concat(thing, " ").concat(String(expected)); + } +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith - Base.call(this, 'edwards', conf); - - this.a = new BN(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new BN(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new BN(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, Base); -module.exports = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); + return str.substring(this_len - search.length, this_len) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} - return this.point(x, y); -}; +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"'; +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + var determiner; -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new BN(y, 16); - if (!y.red) - y = y.toRed(this.red); + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); + var msg; - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); + } else { + var type = includes(name, '.') ? 'property' : 'argument'; + msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); } - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); + msg += ". Received type ".concat(typeof actual); + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented'; +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg; +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); +module.exports.codes = codes; + +},{}],113:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. +'use strict'; +/**/ - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); +var objectKeys = Object.keys || function (obj) { + var keys = []; - return this.point(x, y); + for (var key in obj) { + keys.push(key); + } + + return keys; }; +/**/ -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); +module.exports = Duplex; - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); +var Readable = require('./_stream_readable'); - return lhs.cmp(rhs) === 0; -}; +var Writable = require('./_stream_writable'); -function Point(curve, x, y, z, t) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = z ? new BN(z, 16) : this.curve.one; - this.t = t && new BN(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; +require('inherits')(Duplex, Readable); - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } +{ + // Allow the keys array to be GC'ed. + var keys = objectKeys(Writable.prototype); + + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; } } -inherits(Point, Base.BasePoint); -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + this.allowHalfOpen = true; -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point(this, x, y, z, t); -}; + if (options) { + if (options.readable === false) this.readable = false; + if (options.writable === false) this.writable = false; -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1], obj[2]); -}; + if (options.allowHalfOpen === false) { + this.allowHalfOpen = false; + this.once('end', onend); + } + } +} -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); +Object.defineProperty(Duplex.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +Object.defineProperty(Duplex.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); // the no-half-open enforcer -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; +function onend() { + // If the writable side ended, then we're ok. + if (this._writableState.ended) return; // no more data can be written. + // But allow more writes to happen in this tick. -Point.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S + process.nextTick(onEndNT, this); +} - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; +function onEndNT(self) { + self.end(); +} -Point.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S +Object.defineProperty(Duplex.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } // backward compatibility, the user is explicitly + // managing destroyed - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); + + this._readableState.destroyed = value; + this._writableState.destroyed = value; } - return this.curve.point(nx, ny, nz); -}; +}); +}).call(this,require('_process')) -Point.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; +},{"./_stream_readable":115,"./_stream_writable":117,"_process":252,"inherits":111}],114:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. +'use strict'; - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; +module.exports = PassThrough; -Point.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M +var Transform = require('./_stream_transform'); - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; +require('inherits')(PassThrough, Transform); -Point.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + Transform.call(this, options); +} - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); }; +},{"./_stream_transform":116,"inherits":111}],115:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +'use strict'; -Point.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; +module.exports = Readable; +/**/ - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; +var Duplex; +/**/ -Point.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; +Readable.ReadableState = ReadableState; +/**/ -Point.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; +var EE = require('events').EventEmitter; -Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); +var EElistenerCount = function EElistenerCount(emitter, type) { + return emitter.listeners(type).length; }; +/**/ -Point.prototype.normalize = function normalize() { - if (this.zOne) - return this; +/**/ - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; -Point.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; +var Stream = require('./internal/streams/stream'); +/**/ -Point.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; -Point.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; +var Buffer = require('buffer').Buffer; -Point.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; +var OurUint8Array = global.Uint8Array || function () {}; -Point.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +/**/ - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; -// Compatibility with BaseCurve -Point.prototype.toP = Point.prototype.normalize; -Point.prototype.mixedAdd = Point.prototype.add; +var debugUtil = require('util'); -},{"../utils":138,"./base":125,"bn.js":71,"inherits":175}],127:[function(require,module,exports){ -'use strict'; +var debug; -var curve = exports; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function debug() {}; +} +/**/ -curve.base = require('./base'); -curve.short = require('./short'); -curve.mont = require('./mont'); -curve.edwards = require('./edwards'); -},{"./base":125,"./edwards":126,"./mont":128,"./short":129}],128:[function(require,module,exports){ -'use strict'; +var BufferList = require('./internal/streams/buffer_list'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); +var destroyImpl = require('./internal/streams/destroy'); -var utils = require('../utils'); +var _require = require('./internal/streams/state'), + getHighWaterMark = _require.getHighWaterMark; -function MontCurve(conf) { - Base.call(this, 'mont', conf); +var _require$codes = require('../errors').codes, + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; // Lazy loaded to improve the startup performance. - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.i4 = new BN(4).toRed(this.red).redInvm(); - this.two = new BN(2).toRed(this.red); - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, Base); -module.exports = MontCurve; -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); +var StringDecoder; +var createReadableStreamAsyncIterator; +var from; - return y.redSqr().cmp(rhs) === 0; -}; +require('inherits')(Readable, Stream); -function Point(curve, x, z) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new BN(x, 16); - this.z = new BN(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point, Base.BasePoint); +var errorOrDestroy = destroyImpl.errorOrDestroy; +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - return this.point(utils.toArray(bytes, enc), 1); -}; +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. -MontCurve.prototype.point = function point(x, z) { - return new Point(this, x, z); -}; + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; +function ReadableState(options, stream, isDuplex) { + Duplex = Duplex || require('./_stream_duplex'); + options = options || {}; // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. -Point.prototype.precompute = function precompute() { - // No-op -}; + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away -Point.prototype._encode = function _encode() { - return this.getX().toArray('be', this.curve.p.byteLength()); -}; + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1] || curve.one); -}; + this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; + this.sync = true; // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. -Point.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this.paused = true; // Should close be emitted on destroy. Defaults to true. - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; + this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'end' (and potentially 'finish') -Point.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; + this.autoDestroy = !!options.autoDestroy; // has it been destroyed -Point.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A + this.destroyed = false; // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; + this.defaultEncoding = options.defaultEncoding || 'utf8'; // the number of writers that are awaiting a drain event in .pipe()s -Point.prototype.mul = function mul(k) { - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q + this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); + this.readingMore = false; + this.decoder = null; + this.encoding = null; - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; } - return b; -}; +} -Point.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + if (!(this instanceof Readable)) return new Readable(options); // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5 -Point.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; + var isDuplex = this instanceof Duplex; + this._readableState = new ReadableState(options, this, isDuplex); // legacy -Point.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; + this.readable = true; -Point.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; + if (options) { + if (typeof options.read === 'function') this._read = options.read; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } -Point.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); + Stream.call(this); +} - return this.x.fromRed(); -}; +Object.defineProperty(Readable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined) { + return false; + } -},{"../utils":138,"./base":125,"bn.js":71,"inherits":175}],129:[function(require,module,exports){ -'use strict'; + return this._readableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } // backward compatibility, the user is explicitly + // managing destroyed -var utils = require('../utils'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); -var assert = utils.assert; + this._readableState.destroyed = value; + } +}); +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; -function ShortCurve(conf) { - Base.call(this, 'short', conf); +Readable.prototype._destroy = function (err, cb) { + cb(err); +}; // Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, Base); -module.exports = ShortCurve; + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new BN(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new BN(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + skipChunkCheck = true; } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new BN(vec.a, 16), - b: new BN(vec.b, 16) - }; - }); } else { - basis = this._getEndoBasis(lambda); + skipChunkCheck = true; } - return { - beta: beta, - lambda: lambda, - basis: basis - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : BN.mont(num); - var tinv = new BN(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; // Unshift should *always* be something directly out of read() - var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); }; -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + debug('readableAddChunk', chunk); + var state = stream._readableState; - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new BN(1); - var y1 = new BN(0); - var x2 = new BN(0); - var y2 = new BN(1); + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; + if (er) { + errorOrDestroy(stream, er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed) { + return false; + } else { + state.reading = false; - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); } - prevR = r; + } // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } + return !state.ended && (state.length < state.highWaterMark || state.length === 0); +} - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + state.awaitDrain = 0; + stream.emit('data', chunk); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + if (state.needReadable) emitReadable(stream); } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); + + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); } - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; -}; + return er; +} -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; // backwards compatibility. - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + var decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; // If setEncoding(null), decoder.encoding equals utf8 - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; + this._readableState.encoding = this._readableState.decoder.encoding; // Iterate over current buffer to convert already stored Buffers: -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); + var p = this._readableState.buffer.head; + var content = ''; - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); + while (p !== null) { + content += decoder.write(p.data); + p = p.next; + } - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); + this._readableState.buffer.clear(); - return this.point(x, y); -}; + if (content !== '') this._readableState.buffer.push(content); + this._readableState.length = content.length; + return this; +}; // Don't raise the hwm > 1GB -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - var x = point.x; - var y = point.y; +var MAX_HWM = 0x40000000; - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; -}; + return n; +} // This function is designed to be inlinable, so please take care when making +// changes to the function body. -function Point(curve, x, y, isRed) { - Base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, Base.BasePoint); -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } // If we're asking for more than the current hwm, then raise the hwm. -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; // Don't have enough - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; + if (!state.ended) { + state.needReadable = true; + return 0; } - return beta; -}; -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; + return state.length; +} // you can override either this method, or the async _read(n) below. - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; -}; -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + if (n !== 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; } - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; -}; + n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + // if we need a readable event, then we need to do some reading. -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; + var doRead = state.needReadable; + debug('need readable', doRead); // if we currently have less than the highWaterMark, then also read some - // P + O = P - if (p.inf) - return this; + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; // if the length is currently zero, then we *need* a readable event. - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); + if (state.length === 0) state.needReadable = true; // call internal read method - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; + this._read(state.highWaterMark); -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; + state.sync = false; // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); + if (!state.reading) n = howMuchToRead(nOrig, state); + } - var a = this.curve.a; + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + state.awaitDrain = 0; + } - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; // If we tried to read() past the EOF, then emit end on the next tick. -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; + if (nOrig !== n && state.ended) endReadable(this); + } -Point.prototype.getY = function getY() { - return this.y.fromRed(); + if (ret !== null) this.emit('data', ret); + return ret; }; -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; +function onEofChunk(stream, state) { + debug('onEofChunk'); + if (state.ended) return; -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; + if (state.decoder) { + var chunk = state.decoder.end(); -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; + state.ended = true; -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; + if (state.sync) { + // if we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call + emitReadable(stream); + } else { + // emit 'readable' now to make sure it gets picked up. + state.needReadable = false; - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } } - return res; -}; +} // Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; +function emitReadable(stream) { + var state = stream._readableState; + debug('emitReadable', state.needReadable, state.emittedReadable); + state.needReadable = false; -function JPoint(curve, x, y, z) { - Base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new BN(0); - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = new BN(z, 16); + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; } -inherits(JPoint, Base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); +function emitReadable_(stream) { + var state = stream._readableState; + debug('emitReadable_', state.destroyed, state.length, state.ended); - return this.curve.point(ax, ay); -}; + if (!state.destroyed && (state.length || state.ended)) { + stream.emit('readable'); + state.emittedReadable = false; + } // The stream needs another readable event if + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); +} // at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. - // P + O = P - if (p.isInfinity()) - return this; - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } +} - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); +function maybeReadMore_(stream, state) { + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { + var len = state.length; + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) // didn't get any data, stop spinning. + break; } - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); + state.readingMore = false; +} // abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - return this.curve.jpoint(nx, ny, nz); +Readable.prototype._read = function (n) { + errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); }; -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; - // P + O = P - if (p.isInfinity()) - return this; + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); + case 1: + state.pipes = [state.pipes, dest]; + break; - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); + default: + state.pipes.push(dest); + break; } - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); + dest.on('unpipe', onunpipe); - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); - return this.curve.jpoint(nx, ny, nz); -}; + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); + function onend() { + debug('onend'); + dest.end(); + } // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + var cleanedUp = false; - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + function cleanup() { + debug('cleanup'); // cleanup event handlers once the pipe is broken - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + cleanedUp = true; // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. - jx = nx; - jz = nz; - jyd = dny; + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); } - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; + src.on('data', ondata); -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + debug('dest.write', ret); - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; + if (ret === false) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', state.awaitDrain); + state.awaitDrain++; + } -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A + src.pause(); + } + } // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); + } // Make sure our error handler is attached before userland ones. - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); + prependListener(dest, 'error', onerror); // Both close and finish should trigger unpipe, but only once. - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); + dest.once('close', onclose); + + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); } - return this.curve.jpoint(nx, ny, nz); -}; + dest.once('finish', onfinish); -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } // tell the dest that it's being piped to - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + dest.emit('pipe', src); // start the flow if it hasn't been started already. + + if (!state.flowing) { + debug('pipe resume'); + src.resume(); } - return this.curve.jpoint(nx, ny, nz); + return dest; }; -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; +function pipeOnDrain(src) { + return function pipeOnDrainFunctionResult() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { + hasUnpiped: false + }; // if we're not piping anywhere, then do nothing. - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + if (state.pipesCount === 0) return this; // just one destination. most common case. - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + if (!dest) dest = state.pipes; // got a match. - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } // slow case. multiple pipe destinations. - return this.curve.jpoint(nx, ny, nz); -}; -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, { + hasUnpiped: false + }); + } - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + return this; + } // try to find the right one. - return this.curve.jpoint(nx, ny, nz); -}; -JPoint.prototype.mul = function mul(k, kbase) { - k = new BN(k, kbase); + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + dest.emit('unpipe', this, unpipeInfo); + return this; +}; // set up data events if they are asked for +// Ensure readable listeners eventually get something - return this.curve._wnafMul(this, k); -}; -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + var state = this._readableState; - if (this === p) - return true; + if (ev === 'data') { + // update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0; // Try start flowing on next tick if stream isn't explicitly paused - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; + if (state.flowing !== false) this.resume(); + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + debug('on readable', state.length, state.reading); - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + + return res; }; -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; +Readable.prototype.addListener = Readable.prototype.on; - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; +Readable.prototype.removeListener = function (ev, fn) { + var res = Stream.prototype.removeListener.call(this, ev, fn); - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); } -}; -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; + return res; }; -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; +Readable.prototype.removeAllListeners = function (ev) { + var res = Stream.prototype.removeAllListeners.apply(this, arguments); + + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + + return res; }; -},{"../utils":138,"./base":125,"bn.js":71,"inherits":175}],130:[function(require,module,exports){ -'use strict'; +function updateReadableListening(self) { + var state = self._readableState; + state.readableListening = self.listenerCount('readable') > 0; -var curves = exports; + if (state.resumeScheduled && !state.paused) { + // flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true; // crude way to check if we should resume + } else if (self.listenerCount('data') > 0) { + self.resume(); + } +} -var hash = require('hash.js'); -var curve = require('./curve'); -var utils = require('./utils'); +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} // pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. -var assert = utils.assert; -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve.short(options); - else if (options.type === 'edwards') - this.curve = new curve.edwards(options); - else - this.curve = new curve.mont(options); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; +Readable.prototype.resume = function () { + var state = this._readableState; - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O'); + if (!state.flowing) { + debug('resume'); // we flow only if there is no one listening + // for readable, but we still have to call + // resume() + + state.flowing = !state.readableListening; + resume(this, state); + } + + state.paused = false; + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } } -curves.PresetCurve = PresetCurve; -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); +function resume_(stream, state) { + debug('resume', state.reading); + + if (!state.reading) { + stream.read(0); + } + + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); } -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] -}); +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] -}); + if (this._readableState.flowing !== false) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] -}); + this._readableState.paused = true; + return this; +}; -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] -}); +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] -}); + while (state.flowing && stream.read() !== null) { + ; + } +} // wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - hash: hash.sha256, - gRed: false, - g: [ - '9' - ] -}); -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - hash: hash.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', +Readable.prototype.wrap = function (stream) { + var _this = this; - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] -}); + var state = this._readableState; + var paused = false; + stream.on('end', function () { + debug('wrapped end'); -var pre; -try { - pre = require('./precomputed/secp256k1'); -} catch (e) { - pre = undefined; -} + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash.sha256, + _this.push(null); + }); + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); // don't skip over falsy values in objectMode - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] -}); + var ret = _this.push(chunk); -},{"./curve":127,"./precomputed/secp256k1":137,"./utils":138,"hash.js":160}],131:[function(require,module,exports){ -'use strict'; + if (!ret) { + paused = true; + stream.pause(); + } + }); // proxy all the other methods. + // important when wrapping filters and duplexes. -var BN = require('bn.js'); -var HmacDRBG = require('hmac-drbg'); -var utils = require('../utils'); -var curves = require('../curves'); -var rand = require('brorand'); -var assert = utils.assert; + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function methodWrap(method) { + return function methodWrapReturnFunction() { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } // proxy certain important events. -var KeyPair = require('./key'); -var Signature = require('./signature'); -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } // when we try to consume some more bytes, simply unpause the + // underlying stream. - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert(curves.hasOwnProperty(options), 'Unknown curve ' + options); - options = curves[options]; - } + this._read = function (n) { + debug('wrapped _read', n); - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves.PresetCurve) - options = { curve: options }; + if (paused) { + paused = false; + stream.resume(); + } + }; - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; + return this; +}; - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); +if (typeof Symbol === 'function') { + Readable.prototype[Symbol.asyncIterator] = function () { + if (createReadableStreamAsyncIterator === undefined) { + createReadableStreamAsyncIterator = require('./internal/streams/async_iterator'); + } - // Hash for function for DRBG - this.hash = options.hash || options.curve.hash; + return createReadableStreamAsyncIterator(this); + }; } -module.exports = EC; -EC.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.highWaterMark; + } +}); +Object.defineProperty(Readable.prototype, 'readableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState && this._readableState.buffer; + } +}); +Object.defineProperty(Readable.prototype, 'readableFlowing', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.flowing; + }, + set: function set(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } +}); // exposed for testing purposes only. -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return KeyPair.fromPrivate(this, priv, enc); -}; +Readable._fromList = fromList; +Object.defineProperty(Readable.prototype, 'readableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.length; + } +}); // Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return KeyPair.fromPublic(this, pub, enc); -}; +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = state.buffer.consume(n, state.decoder); + } + return ret; +} -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; +function endReadable(stream) { + var state = stream._readableState; + debug('endReadable', state.endEmitted); - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } +} - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new BN(2)); - do { - var priv = new BN(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; +function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length); // Check that we didn't get one last unshift. - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); -}; + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); -EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { - var delta = msg.byteLength() * 8 - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well + var wState = stream._writableState; -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; + if (!wState || wState.autoDestroy && wState.finished) { + stream.destroy(); + } + } } - if (!options) - options = {}; +} - key = this.keyFromPrivate(key, enc); - msg = this._truncateToN(new BN(msg, 16)); +if (typeof Symbol === 'function') { + Readable.from = function (iterable, opts) { + if (from === undefined) { + from = require('./internal/streams/from'); + } - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); + return from(Readable, iterable, opts); + }; +} - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - // Number of bytes to generate - var ns1 = this.n.sub(new BN(1)); +},{"../errors":112,"./_stream_duplex":113,"./internal/streams/async_iterator":118,"./internal/streams/buffer_list":119,"./internal/streams/destroy":120,"./internal/streams/from":122,"./internal/streams/state":124,"./internal/streams/stream":125,"_process":252,"buffer":129,"events":187,"inherits":111,"string_decoder/":300,"util":82}],116:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. +'use strict'; - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new BN(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; +module.exports = Transform; - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; +var _require$codes = require('../errors').codes, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, + ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; +var Duplex = require('./_stream_duplex'); - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; +require('inherits')(Transform, Duplex); - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + var cb = ts.writecb; - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } + if (cb === null) { + return this.emit('error', new ERR_MULTIPLE_CALLBACK()); + } - return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); + ts.writechunk = null; + ts.writecb = null; + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + cb(er); + var rs = this._readableState; + rs.reading = false; + + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); } -}; +} -EC.prototype.verify = function verify(msg, signature, key, enc) { - msg = this._truncateToN(new BN(msg, 16)); - key = this.keyFromPublic(key, enc); - signature = new Signature(signature, 'hex'); +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + Duplex.call(this, options); + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; // start out asking for a readable event once data is transformed. - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; + this._readableState.needReadable = true; // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); + this._readableState.sync = false; - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + if (typeof options.flush === 'function') this._flush = options.flush; + } // When the writable side finishes, then flush out anything remaining. - return p.getX().umod(this.n).cmp(r) === 0; + + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function' && !this._readableState.destroyed) { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); } +} - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; // This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); +Transform.prototype._transform = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); }; -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert((3 & j) === j, 'The recovery param is more than two bits'); - signature = new Signature(signature, enc); - - var n = this.n; - var e = new BN(msg); - var r = signature.r; - var s = signature.s; +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; // Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); +Transform.prototype._read = function (n) { + var ts = this._transformState; - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; + if (ts.writechunk !== null && !ts.transforming) { + ts.transforming = true; -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new Signature(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; } - throw new Error('Unable to find valid recovery factor'); }; -},{"../curves":130,"../utils":138,"./key":132,"./signature":133,"bn.js":71,"brorand":72,"hmac-drbg":172}],132:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var utils = require('../utils'); -var assert = utils.assert; +Transform.prototype._destroy = function (err, cb) { + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + }); +}; -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; +function done(stream, er, data) { + if (er) return stream.emit('error', er); + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); // TODO(BridgeAR): Write a test for these two error cases + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); + if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); + if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); + return stream.push(null); } -module.exports = KeyPair; +},{"../errors":112,"./_stream_duplex":113,"inherits":111}],117:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. +'use strict'; -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; +module.exports = Writable; +/* */ - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); -}; +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} // It seems a linked list but it is not +// there will be only 2 of these for each stream -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); -}; +function CorkedRequest(state) { + var _this = this; -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); + this.next = null; + this.entry = null; - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ - return { result: true, reason: null }; -}; +/**/ -KeyPair.prototype.getPublic = function getPublic(compact, enc) { - // compact is optional argument - if (typeof compact === 'string') { - enc = compact; - compact = null; - } - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); +var Duplex; +/**/ - if (!enc) - return this.pub; +Writable.WritableState = WritableState; +/**/ - return this.pub.encode(enc, compact); +var internalUtil = { + deprecate: require('util-deprecate') }; +/**/ -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; +/**/ -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new BN(key, enc || 16); +var Stream = require('./internal/streams/stream'); +/**/ - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; +var Buffer = require('buffer').Buffer; -// ECDH -KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); -}; +var OurUint8Array = global.Uint8Array || function () {}; -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} -KeyPair.prototype.inspect = function inspect() { - return ''; -}; +var destroyImpl = require('./internal/streams/destroy'); -},{"../utils":138,"bn.js":71}],133:[function(require,module,exports){ -'use strict'; +var _require = require('./internal/streams/state'), + getHighWaterMark = _require.getHighWaterMark; -var BN = require('bn.js'); +var _require$codes = require('../errors').codes, + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, + ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; -var utils = require('../utils'); -var assert = utils.assert; +var errorOrDestroy = destroyImpl.errorOrDestroy; -function Signature(options, enc) { - if (options instanceof Signature) - return options; +require('inherits')(Writable, Stream); - if (this._importDER(options, enc)) - return; +function nop() {} - assert(options.r && options.s, 'Signature without r or s'); - this.r = new BN(options.r, 16); - this.s = new BN(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -module.exports = Signature; +function WritableState(options, stream, isDuplex) { + Duplex = Duplex || require('./_stream_duplex'); + options = options || {}; // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. -function Position() { - this.place = 0; -} + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream + // contains buffers or objects. -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; -} + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} + this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); // if _final has been called -Signature.prototype._importDER = function _importDER(data, enc) { - data = utils.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } + this.finalCalled = false; // drain event flag. - this.r = new BN(r); - this.s = new BN(s); - this.recoveryParam = null; + this.needDrain = false; // at the start of calling end() - return true; -}; + this.ending = false; // when end() has been called, and returned -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} + this.ended = false; // when 'finish' is emitted -Signature.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); + this.finished = false; // has it been destroyed - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); + this.destroyed = false; // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. - r = rmPadding(r); - s = rmPadding(s); + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils.encode(res, enc); -}; + this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. -},{"../utils":138,"bn.js":71}],134:[function(require,module,exports){ -'use strict'; + this.length = 0; // a flag to see when we're in the middle of a write. -var hash = require('hash.js'); -var curves = require('../curves'); -var utils = require('../utils'); -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var KeyPair = require('./key'); -var Signature = require('./signature'); + this.writing = false; // when true all writes will be buffered until .uncork() call -function EDDSA(curve) { - assert(curve === 'ed25519', 'only tested with ed25519 so far'); + this.corked = 0; // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. - if (!(this instanceof EDDSA)) - return new EDDSA(curve); + this.sync = true; // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. - var curve = curves[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); + this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash.sha512; -} + this.onwrite = function (er) { + onwrite(stream, er); + }; // the callback that the user supplies to write(chunk,encoding,cb) -module.exports = EDDSA; -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; + this.writecb = null; // the amount that is being written when _write is called. -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; + this.writelen = 0; + this.bufferedRequest = null; + this.lastBufferedRequest = null; // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils.intFromLE(hash.digest()).umod(this.curve.n); -}; + this.pendingcb = 0; // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return KeyPair.fromPublic(this, pub); -}; + this.prefinished = false; // True if the error was already emitted and should not be thrown again -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return KeyPair.fromSecret(this, secret); -}; + this.errorEmitted = false; // Should close be emitted on destroy. Defaults to true. -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof Signature) - return sig; - return new Signature(this, sig); -}; + this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'finish' (and potentially 'end') -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; + this.autoDestroy = !!options.autoDestroy; // count buffered requests -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils.parseBytes(bytes); + this.bufferedRequestCount = 0; // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + this.corkedRequestsFree = new CorkedRequest(this); +} - var y = utils.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; + while (current) { + out.push(current); + current = current.next; + } -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils.intFromLE(bytes); + return out; }; -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function writableStateBufferGetter() { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); // Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. -},{"../curves":130,"../utils":138,"./key":135,"./signature":136,"hash.js":160}],135:[function(require,module,exports){ -'use strict'; -var utils = require('../utils'); -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var cachedProperty = utils.cachedProperty; +var realHasInstance; -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair(eddsa, params) { - this.eddsa = eddsa; - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else - this._pubBytes = parseBytes(params.pub); +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function value(object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function realHasInstance(object) { + return object instanceof this; + }; } -KeyPair.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair) - return pub; - return new KeyPair(eddsa, { pub: pub }); -}; +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5 -KeyPair.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair) - return secret; - return new KeyPair(eddsa, { secret: secret }); -}; + var isDuplex = this instanceof Duplex; + if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex); // legacy. -KeyPair.prototype.secret = function secret() { - return this._secret; -}; + this.writable = true; -cachedProperty(KeyPair, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); + if (options) { + if (typeof options.write === 'function') this._write = options.write; + if (typeof options.writev === 'function') this._writev = options.writev; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.final === 'function') this._final = options.final; + } -cachedProperty(KeyPair, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); + Stream.call(this); +} // Otherwise people can pipe Writable streams, which is just wrong. -cachedProperty(KeyPair, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; +Writable.prototype.pipe = function () { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); +}; - return a; -}); +function writeAfterEnd(stream, cb) { + var er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb -cachedProperty(KeyPair, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); + errorOrDestroy(stream, er); + process.nextTick(cb, er); +} // Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. -cachedProperty(KeyPair, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); -cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); +function validChunk(stream, state, chunk, cb) { + var er; -KeyPair.prototype.sign = function sign(message) { - assert(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); + if (chunk === null) { + er = new ERR_STREAM_NULL_VALUES(); + } else if (typeof chunk !== 'string' && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); + } + + if (er) { + errorOrDestroy(stream, er); + process.nextTick(cb, er); + return false; + } + + return true; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (typeof cb !== 'function') cb = nop; + if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + return ret; }; -KeyPair.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); +Writable.prototype.cork = function () { + this._writableState.corked++; }; -KeyPair.prototype.getSecret = function getSecret(enc) { - assert(this._secret, 'KeyPair is public only'); - return utils.encode(this.secret(), enc); +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } }; -KeyPair.prototype.getPublic = function getPublic(enc) { - return utils.encode(this.pubBytes(), enc); +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; }; -module.exports = KeyPair; +Object.defineProperty(Writable.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); -},{"../utils":138}],136:[function(require,module,exports){ -'use strict'; +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } -var BN = require('bn.js'); -var utils = require('../utils'); -var assert = utils.assert; -var cachedProperty = utils.cachedProperty; -var parseBytes = utils.parseBytes; + return chunk; +} -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature(eddsa, sig) { - this.eddsa = eddsa; +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); // if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. - if (typeof sig !== 'object') - sig = parseBytes(sig); +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + + var len = state.objectMode ? 1 : chunk.length; + state.length += len; + var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false. + + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null }; + + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); } - assert(sig.R && sig.S, 'Signature without R or S'); + return ret; +} - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof BN) - this._S = sig.S; +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + process.nextTick(cb, er); // this can emit finish, and it will always happen + // after error + + process.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); // this can emit finish, but finish must + // always follow error + + finishMaybe(stream, state); + } } -cachedProperty(Signature, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} -cachedProperty(Signature, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state) || stream.destroyed; -cachedProperty(Signature, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + process.nextTick(afterWrite, stream, state, finished, cb); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} // Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. + + +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} // if there's something in the buffer waiting, then process it + + +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + var count = 0; + var allBuffers = true; + + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + + buffer.allBuffers = allBuffers; + doWrite(stream, state, true, state.length, buffer, '', holder.finish); // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + + state.pendingcb++; + state.lastBufferedRequest = null; + + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks + + if (state.corked) { + state.corked = 1; + this.uncork(); + } // ignore unnecessary end() calls. + + + if (!state.ending) endWritable(this, state, cb); + return this; +}; + +Object.defineProperty(Writable.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } }); -cachedProperty(Signature, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} + +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + + if (err) { + errorOrDestroy(stream, err); + } + + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} + +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.pendingcb++; + state.finalCalled = true; + process.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + + if (need) { + prefinish(stream, state); + + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well + var rState = stream._readableState; + + if (!rState || rState.autoDestroy && rState.endEmitted) { + stream.destroy(); + } + } + } + } + + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + + if (cb) { + if (state.finished) process.nextTick(cb);else stream.once('finish', cb); + } + + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } // reuse the free corkReq. + + + state.corkedRequestsFree.next = corkReq; +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._writableState === undefined) { + return false; + } + + return this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } // backward compatibility, the user is explicitly + // managing destroyed + + + this._writableState.destroyed = value; + } }); +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; -Signature.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); +Writable.prototype._destroy = function (err, cb) { + cb(err); }; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -Signature.prototype.toHex = function toHex() { - return utils.encode(this.toBytes(), 'hex').toUpperCase(); +},{"../errors":112,"./_stream_duplex":113,"./internal/streams/destroy":120,"./internal/streams/state":124,"./internal/streams/stream":125,"_process":252,"buffer":129,"inherits":111,"util-deprecate":303}],118:[function(require,module,exports){ +(function (process){ +'use strict'; + +var _Object$setPrototypeO; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var finished = require('./end-of-stream'); + +var kLastResolve = Symbol('lastResolve'); +var kLastReject = Symbol('lastReject'); +var kError = Symbol('error'); +var kEnded = Symbol('ended'); +var kLastPromise = Symbol('lastPromise'); +var kHandlePromise = Symbol('handlePromise'); +var kStream = Symbol('stream'); + +function createIterResult(value, done) { + return { + value: value, + done: done + }; +} + +function readAndResolve(iter) { + var resolve = iter[kLastResolve]; + + if (resolve !== null) { + var data = iter[kStream].read(); // we defer if data is null + // we can be expecting either 'end' or + // 'error' + + if (data !== null) { + iter[kLastPromise] = null; + iter[kLastResolve] = null; + iter[kLastReject] = null; + resolve(createIterResult(data, false)); + } + } +} + +function onReadable(iter) { + // we wait for the next tick, because it might + // emit an error with process.nextTick + process.nextTick(readAndResolve, iter); +} + +function wrapForNext(lastPromise, iter) { + return function (resolve, reject) { + lastPromise.then(function () { + if (iter[kEnded]) { + resolve(createIterResult(undefined, true)); + return; + } + + iter[kHandlePromise](resolve, reject); + }, reject); + }; +} + +var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); +var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { + get stream() { + return this[kStream]; + }, + + next: function next() { + var _this = this; + + // if we have detected an error in the meanwhile + // reject straight away + var error = this[kError]; + + if (error !== null) { + return Promise.reject(error); + } + + if (this[kEnded]) { + return Promise.resolve(createIterResult(undefined, true)); + } + + if (this[kStream].destroyed) { + // We need to defer via nextTick because if .destroy(err) is + // called, the error will be emitted via nextTick, and + // we cannot guarantee that there is no error lingering around + // waiting to be emitted. + return new Promise(function (resolve, reject) { + process.nextTick(function () { + if (_this[kError]) { + reject(_this[kError]); + } else { + resolve(createIterResult(undefined, true)); + } + }); + }); + } // if we have multiple next() calls + // we will wait for the previous Promise to finish + // this logic is optimized to support for await loops, + // where next() is only called once at a time + + + var lastPromise = this[kLastPromise]; + var promise; + + if (lastPromise) { + promise = new Promise(wrapForNext(lastPromise, this)); + } else { + // fast path needed to support multiple this.push() + // without triggering the next() queue + var data = this[kStream].read(); + + if (data !== null) { + return Promise.resolve(createIterResult(data, false)); + } + + promise = new Promise(this[kHandlePromise]); + } + + this[kLastPromise] = promise; + return promise; + } +}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { + return this; +}), _defineProperty(_Object$setPrototypeO, "return", function _return() { + var _this2 = this; + + // destroy(err, cb) is a private API + // we can guarantee we have that here, because we control the + // Readable class this is attached to + return new Promise(function (resolve, reject) { + _this2[kStream].destroy(null, function (err) { + if (err) { + reject(err); + return; + } + + resolve(createIterResult(undefined, true)); + }); + }); +}), _Object$setPrototypeO), AsyncIteratorPrototype); + +var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { + var _Object$create; + + var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { + value: stream, + writable: true + }), _defineProperty(_Object$create, kLastResolve, { + value: null, + writable: true + }), _defineProperty(_Object$create, kLastReject, { + value: null, + writable: true + }), _defineProperty(_Object$create, kError, { + value: null, + writable: true + }), _defineProperty(_Object$create, kEnded, { + value: stream._readableState.endEmitted, + writable: true + }), _defineProperty(_Object$create, kHandlePromise, { + value: function value(resolve, reject) { + var data = iterator[kStream].read(); + + if (data) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(data, false)); + } else { + iterator[kLastResolve] = resolve; + iterator[kLastReject] = reject; + } + }, + writable: true + }), _Object$create)); + iterator[kLastPromise] = null; + finished(stream, function (err) { + if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + var reject = iterator[kLastReject]; // reject if we are waiting for data in the Promise + // returned by next() and store the error + + if (reject !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + reject(err); + } + + iterator[kError] = err; + return; + } + + var resolve = iterator[kLastResolve]; + + if (resolve !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(undefined, true)); + } + + iterator[kEnded] = true; + }); + stream.on('readable', onReadable.bind(null, iterator)); + return iterator; }; -module.exports = Signature; +module.exports = createReadableStreamAsyncIterator; +}).call(this,require('_process')) -},{"../utils":138,"bn.js":71}],137:[function(require,module,exports){ -module.exports = { - doubles: { - step: 4, - points: [ +},{"./end-of-stream":121,"_process":252}],119:[function(require,module,exports){ +'use strict'; + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +var _require = require('buffer'), + Buffer = _require.Buffer; + +var _require2 = require('util'), + inspect = _require2.inspect; + +var custom = inspect && inspect.custom || 'inspect'; + +function copyBuffer(src, target, offset) { + Buffer.prototype.copy.call(src, target, offset); +} + +module.exports = +/*#__PURE__*/ +function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + _createClass(BufferList, [{ + key: "push", + value: function push(v) { + var entry = { + data: v, + next: null + }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + } + }, { + key: "unshift", + value: function unshift(v) { + var entry = { + data: v, + next: this.head + }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + } + }, { + key: "shift", + value: function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + } + }, { + key: "clear", + value: function clear() { + this.head = this.tail = null; + this.length = 0; + } + }, { + key: "join", + value: function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + + while (p = p.next) { + ret += s + p.data; + } + + return ret; + } + }, { + key: "concat", + value: function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + + return ret; + } // Consumes a specified amount of bytes or characters from the buffered data. + + }, { + key: "consume", + value: function consume(n, hasStrings) { + var ret; + + if (n < this.head.data.length) { + // `slice` is the same for buffers and strings. + ret = this.head.data.slice(0, n); + this.head.data = this.head.data.slice(n); + } else if (n === this.head.data.length) { + // First chunk is a perfect match. + ret = this.shift(); + } else { + // Result spans more than one buffer. + ret = hasStrings ? this._getString(n) : this._getBuffer(n); + } + + return ret; + } + }, { + key: "first", + value: function first() { + return this.head.data; + } // Consumes a specified amount of characters from the buffered data. + + }, { + key: "_getString", + value: function _getString(n) { + var p = this.head; + var c = 1; + var ret = p.data; + n -= ret.length; + + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = str.slice(nb); + } + + break; + } + + ++c; + } + + this.length -= c; + return ret; + } // Consumes a specified amount of bytes from the buffered data. + + }, { + key: "_getBuffer", + value: function _getBuffer(n) { + var ret = Buffer.allocUnsafe(n); + var p = this.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = buf.slice(nb); + } + + break; + } + + ++c; + } + + this.length -= c; + return ret; + } // Make sure the linked list only shows the minimal necessary information. + + }, { + key: custom, + value: function value(_, options) { + return inspect(this, _objectSpread({}, options, { + // Only inspect one level. + depth: 0, + // It should not recurse. + customInspect: false + })); + } + }]); + + return BufferList; +}(); +},{"buffer":129,"util":82}],120:[function(require,module,exports){ +(function (process){ +'use strict'; // undocumented cb() API, needed for core, not for public API + +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + process.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + process.nextTick(emitErrorNT, this, err); + } + } + + return this; + } // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + + if (this._readableState) { + this._readableState.destroyed = true; + } // if this is a duplex stream mark the writable part as destroyed as well + + + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + if (!_this._writableState) { + process.nextTick(emitErrorAndCloseNT, _this, err); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + process.nextTick(emitErrorAndCloseNT, _this, err); + } else { + process.nextTick(emitCloseNT, _this); + } + } else if (cb) { + process.nextTick(emitCloseNT, _this); + cb(err); + } else { + process.nextTick(emitCloseNT, _this); + } + }); + + return this; +} + +function emitErrorAndCloseNT(self, err) { + emitErrorNT(self, err); + emitCloseNT(self); +} + +function emitCloseNT(self) { + if (self._writableState && !self._writableState.emitClose) return; + if (self._readableState && !self._readableState.emitClose) return; + self.emit('close'); +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +function errorOrDestroy(stream, err) { + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + var rState = stream._readableState; + var wState = stream._writableState; + if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy, + errorOrDestroy: errorOrDestroy +}; +}).call(this,require('_process')) + +},{"_process":252}],121:[function(require,module,exports){ +// Ported from https://github.com/mafintosh/end-of-stream with +// permission from the author, Mathias Buus (@mafintosh). +'use strict'; + +var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE; + +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply(this, args); + }; +} + +function noop() {} + +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} + +function eos(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + callback = once(callback || noop); + var readable = opts.readable || opts.readable !== false && stream.readable; + var writable = opts.writable || opts.writable !== false && stream.writable; + + var onlegacyfinish = function onlegacyfinish() { + if (!stream.writable) onfinish(); + }; + + var writableEnded = stream._writableState && stream._writableState.finished; + + var onfinish = function onfinish() { + writable = false; + writableEnded = true; + if (!readable) callback.call(stream); + }; + + var readableEnded = stream._readableState && stream._readableState.endEmitted; + + var onend = function onend() { + readable = false; + readableEnded = true; + if (!writable) callback.call(stream); + }; + + var onerror = function onerror(err) { + callback.call(stream, err); + }; + + var onclose = function onclose() { + var err; + + if (readable && !readableEnded) { + if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + + if (writable && !writableEnded) { + if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + }; + + var onrequest = function onrequest() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest();else stream.on('request', onrequest); + } else if (writable && !stream._writableState) { + // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + return function () { + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +} + +module.exports = eos; +},{"../../../errors":112}],122:[function(require,module,exports){ +module.exports = function () { + throw new Error('Readable.from is not available in the browser') +}; + +},{}],123:[function(require,module,exports){ +// Ported from https://github.com/mafintosh/pump with +// permission from the author, Mathias Buus (@mafintosh). +'use strict'; + +var eos; + +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + callback.apply(void 0, arguments); + }; +} + +var _require$codes = require('../../../errors').codes, + ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; + +function noop(err) { + // Rethrow the error if it exists to avoid swallowing it + if (err) throw err; +} + +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} + +function destroyer(stream, reading, writing, callback) { + callback = once(callback); + var closed = false; + stream.on('close', function () { + closed = true; + }); + if (eos === undefined) eos = require('./end-of-stream'); + eos(stream, { + readable: reading, + writable: writing + }, function (err) { + if (err) return callback(err); + closed = true; + callback(); + }); + var destroyed = false; + return function (err) { + if (closed) return; + if (destroyed) return; + destroyed = true; // request.destroy just do .end - .abort is what we want + + if (isRequest(stream)) return stream.abort(); + if (typeof stream.destroy === 'function') return stream.destroy(); + callback(err || new ERR_STREAM_DESTROYED('pipe')); + }; +} + +function call(fn) { + fn(); +} + +function pipe(from, to) { + return from.pipe(to); +} + +function popCallback(streams) { + if (!streams.length) return noop; + if (typeof streams[streams.length - 1] !== 'function') return noop; + return streams.pop(); +} + +function pipeline() { + for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { + streams[_key] = arguments[_key]; + } + + var callback = popCallback(streams); + if (Array.isArray(streams[0])) streams = streams[0]; + + if (streams.length < 2) { + throw new ERR_MISSING_ARGS('streams'); + } + + var error; + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1; + var writing = i > 0; + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err; + if (err) destroys.forEach(call); + if (reading) return; + destroys.forEach(call); + callback(error); + }); + }); + return streams.reduce(pipe); +} + +module.exports = pipeline; +},{"../../../errors":112,"./end-of-stream":121}],124:[function(require,module,exports){ +'use strict'; + +var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE; + +function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; +} + +function getHighWaterMark(state, options, duplexKey, isDuplex) { + var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); + + if (hwm != null) { + if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { + var name = isDuplex ? duplexKey : 'highWaterMark'; + throw new ERR_INVALID_OPT_VALUE(name, hwm); + } + + return Math.floor(hwm); + } // Default value + + + return state.objectMode ? 16 : 16 * 1024; +} + +module.exports = { + getHighWaterMark: getHighWaterMark +}; +},{"../../../errors":112}],125:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":187}],126:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); +exports.finished = require('./lib/internal/streams/end-of-stream.js'); +exports.pipeline = require('./lib/internal/streams/pipeline.js'); + +},{"./lib/_stream_duplex.js":113,"./lib/_stream_passthrough.js":114,"./lib/_stream_readable.js":115,"./lib/_stream_transform.js":116,"./lib/_stream_writable.js":117,"./lib/internal/streams/end-of-stream.js":121,"./lib/internal/streams/pipeline.js":123}],127:[function(require,module,exports){ +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.prototype = Object.create(Buffer.prototype) + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":129}],128:[function(require,module,exports){ +(function (Buffer){ +module.exports = function xor (a, b) { + var length = Math.min(a.length, b.length) + var buffer = new Buffer(length) + + for (var i = 0; i < length; ++i) { + buffer[i] = a[i] ^ b[i] + } + + return buffer +} + +}).call(this,require("buffer").Buffer) + +},{"buffer":129}],129:[function(require,module,exports){ +(function (Buffer){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } + + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +}).call(this,require("buffer").Buffer) + +},{"base64-js":78,"buffer":129,"ieee754":222}],130:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var Transform = require('stream').Transform +var StringDecoder = require('string_decoder').StringDecoder +var inherits = require('inherits') + +function CipherBase (hashMode) { + Transform.call(this) + this.hashMode = typeof hashMode === 'string' + if (this.hashMode) { + this[hashMode] = this._finalOrDigest + } else { + this.final = this._finalOrDigest + } + if (this._final) { + this.__final = this._final + this._final = null + } + this._decoder = null + this._encoding = null +} +inherits(CipherBase, Transform) + +CipherBase.prototype.update = function (data, inputEnc, outputEnc) { + if (typeof data === 'string') { + data = Buffer.from(data, inputEnc) + } + + var outData = this._update(data) + if (this.hashMode) return this + + if (outputEnc) { + outData = this._toString(outData, outputEnc) + } + + return outData +} + +CipherBase.prototype.setAutoPadding = function () {} +CipherBase.prototype.getAuthTag = function () { + throw new Error('trying to get auth tag in unsupported state') +} + +CipherBase.prototype.setAuthTag = function () { + throw new Error('trying to set auth tag in unsupported state') +} + +CipherBase.prototype.setAAD = function () { + throw new Error('trying to set aad in unsupported state') +} + +CipherBase.prototype._transform = function (data, _, next) { + var err + try { + if (this.hashMode) { + this._update(data) + } else { + this.push(this._update(data)) + } + } catch (e) { + err = e + } finally { + next(err) + } +} +CipherBase.prototype._flush = function (done) { + var err + try { + this.push(this.__final()) + } catch (e) { + err = e + } + + done(err) +} +CipherBase.prototype._finalOrDigest = function (outputEnc) { + var outData = this.__final() || Buffer.alloc(0) + if (outputEnc) { + outData = this._toString(outData, outputEnc, true) + } + return outData +} + +CipherBase.prototype._toString = function (value, enc, fin) { + if (!this._decoder) { + this._decoder = new StringDecoder(enc) + this._encoding = enc + } + + if (this._encoding !== enc) throw new Error('can\'t switch encodings') + + var out = this._decoder.write(value) + if (fin) { + out += this._decoder.end() + } + + return out +} + +module.exports = CipherBase + +},{"inherits":224,"safe-buffer":277,"stream":299,"string_decoder":300}],131:[function(require,module,exports){ +/** + * Slice reference. + */ + +var slice = [].slice; + +/** + * Bind `obj` to `fn`. + * + * @param {Object} obj + * @param {Function|String} fn or string + * @return {Function} + * @api public + */ + +module.exports = function(obj, fn){ + if ('string' == typeof fn) fn = obj[fn]; + if ('function' != typeof fn) throw new Error('bind() requires a function'); + var args = slice.call(arguments, 2); + return function(){ + return fn.apply(obj, args.concat(slice.call(arguments))); + } +}; + +},{}],132:[function(require,module,exports){ + +/** + * Expose `Emitter`. + */ + +if (typeof module !== 'undefined') { + module.exports = Emitter; +} + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; + +},{}],133:[function(require,module,exports){ + +module.exports = function(a, b){ + var fn = function(){}; + fn.prototype = b.prototype; + a.prototype = new fn; + a.prototype.constructor = a; +}; +},{}],134:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) + +},{"../../is-buffer/index.js":225}],135:[function(require,module,exports){ +(function (Buffer){ +var elliptic = require('elliptic') +var BN = require('bn.js') + +module.exports = function createECDH (curve) { + return new ECDH(curve) +} + +var aliases = { + secp256k1: { + name: 'secp256k1', + byteLength: 32 + }, + secp224r1: { + name: 'p224', + byteLength: 28 + }, + prime256v1: { + name: 'p256', + byteLength: 32 + }, + prime192v1: { + name: 'p192', + byteLength: 24 + }, + ed25519: { + name: 'ed25519', + byteLength: 32 + }, + secp384r1: { + name: 'p384', + byteLength: 48 + }, + secp521r1: { + name: 'p521', + byteLength: 66 + } +} + +aliases.p224 = aliases.secp224r1 +aliases.p256 = aliases.secp256r1 = aliases.prime256v1 +aliases.p192 = aliases.secp192r1 = aliases.prime192v1 +aliases.p384 = aliases.secp384r1 +aliases.p521 = aliases.secp521r1 + +function ECDH (curve) { + this.curveType = aliases[curve] + if (!this.curveType) { + this.curveType = { + name: curve + } + } + this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap + this.keys = void 0 +} + +ECDH.prototype.generateKeys = function (enc, format) { + this.keys = this.curve.genKeyPair() + return this.getPublicKey(enc, format) +} + +ECDH.prototype.computeSecret = function (other, inenc, enc) { + inenc = inenc || 'utf8' + if (!Buffer.isBuffer(other)) { + other = new Buffer(other, inenc) + } + var otherPub = this.curve.keyFromPublic(other).getPublic() + var out = otherPub.mul(this.keys.getPrivate()).getX() + return formatReturnValue(out, enc, this.curveType.byteLength) +} + +ECDH.prototype.getPublicKey = function (enc, format) { + var key = this.keys.getPublic(format === 'compressed', true) + if (format === 'hybrid') { + if (key[key.length - 1] % 2) { + key[0] = 7 + } else { + key[0] = 6 + } + } + return formatReturnValue(key, enc) +} + +ECDH.prototype.getPrivateKey = function (enc) { + return formatReturnValue(this.keys.getPrivate(), enc) +} + +ECDH.prototype.setPublicKey = function (pub, enc) { + enc = enc || 'utf8' + if (!Buffer.isBuffer(pub)) { + pub = new Buffer(pub, enc) + } + this.keys._importPublic(pub) + return this +} + +ECDH.prototype.setPrivateKey = function (priv, enc) { + enc = enc || 'utf8' + if (!Buffer.isBuffer(priv)) { + priv = new Buffer(priv, enc) + } + + var _priv = new BN(priv) + _priv = _priv.toString(16) + this.keys = this.curve.genKeyPair() + this.keys._importPrivate(_priv) + return this +} + +function formatReturnValue (bn, enc, len) { + if (!Array.isArray(bn)) { + bn = bn.toArray() + } + var buf = new Buffer(bn) + if (len && buf.length < len) { + var zeros = new Buffer(len - buf.length) + zeros.fill(0) + buf = Buffer.concat([zeros, buf]) + } + if (!enc) { + return buf + } else { + return buf.toString(enc) + } +} + +}).call(this,require("buffer").Buffer) + +},{"bn.js":136,"buffer":129,"elliptic":153}],136:[function(require,module,exports){ +arguments[4][75][0].apply(exports,arguments) +},{"buffer":82,"dup":75}],137:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var MD5 = require('md5.js') +var RIPEMD160 = require('ripemd160') +var sha = require('sha.js') +var Base = require('cipher-base') + +function Hash (hash) { + Base.call(this, 'digest') + + this._hash = hash +} + +inherits(Hash, Base) + +Hash.prototype._update = function (data) { + this._hash.update(data) +} + +Hash.prototype._final = function () { + return this._hash.digest() +} + +module.exports = function createHash (alg) { + alg = alg.toLowerCase() + if (alg === 'md5') return new MD5() + if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160() + + return new Hash(sha(alg)) +} + +},{"cipher-base":130,"inherits":224,"md5.js":231,"ripemd160":276,"sha.js":279}],138:[function(require,module,exports){ +var MD5 = require('md5.js') + +module.exports = function (buffer) { + return new MD5().update(buffer).digest() +} + +},{"md5.js":231}],139:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Legacy = require('./legacy') +var Base = require('cipher-base') +var Buffer = require('safe-buffer').Buffer +var md5 = require('create-hash/md5') +var RIPEMD160 = require('ripemd160') + +var sha = require('sha.js') + +var ZEROS = Buffer.alloc(128) + +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } + + var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 + + this._alg = alg + this._key = key + if (key.length > blocksize) { + var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + key = hash.update(key).digest() + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } + + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) + + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + this._hash.update(ipad) +} + +inherits(Hmac, Base) + +Hmac.prototype._update = function (data) { + this._hash.update(data) +} + +Hmac.prototype._final = function () { + var h = this._hash.digest() + var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg) + return hash.update(this._opad).update(h).digest() +} + +module.exports = function createHmac (alg, key) { + alg = alg.toLowerCase() + if (alg === 'rmd160' || alg === 'ripemd160') { + return new Hmac('rmd160', key) + } + if (alg === 'md5') { + return new Legacy(md5, key) + } + return new Hmac(alg, key) +} + +},{"./legacy":140,"cipher-base":130,"create-hash/md5":138,"inherits":224,"ripemd160":276,"safe-buffer":277,"sha.js":279}],140:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Buffer = require('safe-buffer').Buffer + +var Base = require('cipher-base') + +var ZEROS = Buffer.alloc(128) +var blocksize = 64 + +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } + + this._alg = alg + this._key = key + + if (key.length > blocksize) { + key = alg(key) + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } + + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) + + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + + this._hash = [ipad] +} + +inherits(Hmac, Base) + +Hmac.prototype._update = function (data) { + this._hash.push(data) +} + +Hmac.prototype._final = function () { + var h = this._alg(Buffer.concat(this._hash)) + return this._alg(Buffer.concat([this._opad, h])) +} +module.exports = Hmac + +},{"cipher-base":130,"inherits":224,"safe-buffer":277}],141:[function(require,module,exports){ +'use strict' + +exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes') +exports.createHash = exports.Hash = require('create-hash') +exports.createHmac = exports.Hmac = require('create-hmac') + +var algos = require('browserify-sign/algos') +var algoKeys = Object.keys(algos) +var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys) +exports.getHashes = function () { + return hashes +} + +var p = require('pbkdf2') +exports.pbkdf2 = p.pbkdf2 +exports.pbkdf2Sync = p.pbkdf2Sync + +var aes = require('browserify-cipher') + +exports.Cipher = aes.Cipher +exports.createCipher = aes.createCipher +exports.Cipheriv = aes.Cipheriv +exports.createCipheriv = aes.createCipheriv +exports.Decipher = aes.Decipher +exports.createDecipher = aes.createDecipher +exports.Decipheriv = aes.Decipheriv +exports.createDecipheriv = aes.createDecipheriv +exports.getCiphers = aes.getCiphers +exports.listCiphers = aes.listCiphers + +var dh = require('diffie-hellman') + +exports.DiffieHellmanGroup = dh.DiffieHellmanGroup +exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup +exports.getDiffieHellman = dh.getDiffieHellman +exports.createDiffieHellman = dh.createDiffieHellman +exports.DiffieHellman = dh.DiffieHellman + +var sign = require('browserify-sign') + +exports.createSign = sign.createSign +exports.Sign = sign.Sign +exports.createVerify = sign.createVerify +exports.Verify = sign.Verify + +exports.createECDH = require('create-ecdh') + +var publicEncrypt = require('public-encrypt') + +exports.publicEncrypt = publicEncrypt.publicEncrypt +exports.privateEncrypt = publicEncrypt.privateEncrypt +exports.publicDecrypt = publicEncrypt.publicDecrypt +exports.privateDecrypt = publicEncrypt.privateDecrypt + +// the least I can do is make error messages for the rest of the node.js/crypto api. +// ;[ +// 'createCredentials' +// ].forEach(function (name) { +// exports[name] = function () { +// throw new Error([ +// 'sorry, ' + name + ' is not implemented yet', +// 'we accept pull requests', +// 'https://github.com/crypto-browserify/crypto-browserify' +// ].join('\n')) +// } +// }) + +var rf = require('randomfill') + +exports.randomFill = rf.randomFill +exports.randomFillSync = rf.randomFillSync + +exports.createCredentials = function () { + throw new Error([ + 'sorry, createCredentials is not implemented yet', + 'we accept pull requests', + 'https://github.com/crypto-browserify/crypto-browserify' + ].join('\n')) +} + +exports.constants = { + 'DH_CHECK_P_NOT_SAFE_PRIME': 2, + 'DH_CHECK_P_NOT_PRIME': 1, + 'DH_UNABLE_TO_CHECK_GENERATOR': 4, + 'DH_NOT_SUITABLE_GENERATOR': 8, + 'NPN_ENABLED': 1, + 'ALPN_ENABLED': 1, + 'RSA_PKCS1_PADDING': 1, + 'RSA_SSLV23_PADDING': 2, + 'RSA_NO_PADDING': 3, + 'RSA_PKCS1_OAEP_PADDING': 4, + 'RSA_X931_PADDING': 5, + 'RSA_PKCS1_PSS_PADDING': 6, + 'POINT_CONVERSION_COMPRESSED': 2, + 'POINT_CONVERSION_UNCOMPRESSED': 4, + 'POINT_CONVERSION_HYBRID': 6 +} + +},{"browserify-cipher":100,"browserify-sign":108,"browserify-sign/algos":105,"create-ecdh":135,"create-hash":137,"create-hmac":139,"diffie-hellman":148,"pbkdf2":245,"public-encrypt":253,"randombytes":260,"randomfill":261}],142:[function(require,module,exports){ +'use strict'; + +exports.utils = require('./des/utils'); +exports.Cipher = require('./des/cipher'); +exports.DES = require('./des/des'); +exports.CBC = require('./des/cbc'); +exports.EDE = require('./des/ede'); + +},{"./des/cbc":143,"./des/cipher":144,"./des/des":145,"./des/ede":146,"./des/utils":147}],143:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); + +var proto = {}; + +function CBCState(iv) { + assert.equal(iv.length, 8, 'Invalid IV length'); + + this.iv = new Array(8); + for (var i = 0; i < this.iv.length; i++) + this.iv[i] = iv[i]; +} + +function instantiate(Base) { + function CBC(options) { + Base.call(this, options); + this._cbcInit(); + } + inherits(CBC, Base); + + var keys = Object.keys(proto); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + CBC.prototype[key] = proto[key]; + } + + CBC.create = function create(options) { + return new CBC(options); + }; + + return CBC; +} + +exports.instantiate = instantiate; + +proto._cbcInit = function _cbcInit() { + var state = new CBCState(this.options.iv); + this._cbcState = state; +}; + +proto._update = function _update(inp, inOff, out, outOff) { + var state = this._cbcState; + var superProto = this.constructor.super_.prototype; + + var iv = state.iv; + if (this.type === 'encrypt') { + for (var i = 0; i < this.blockSize; i++) + iv[i] ^= inp[inOff + i]; + + superProto._update.call(this, iv, 0, out, outOff); + + for (var i = 0; i < this.blockSize; i++) + iv[i] = out[outOff + i]; + } else { + superProto._update.call(this, inp, inOff, out, outOff); + + for (var i = 0; i < this.blockSize; i++) + out[outOff + i] ^= iv[i]; + + for (var i = 0; i < this.blockSize; i++) + iv[i] = inp[inOff + i]; + } +}; + +},{"inherits":224,"minimalistic-assert":234}],144:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); + +function Cipher(options) { + this.options = options; + + this.type = this.options.type; + this.blockSize = 8; + this._init(); + + this.buffer = new Array(this.blockSize); + this.bufferOff = 0; +} +module.exports = Cipher; + +Cipher.prototype._init = function _init() { + // Might be overrided +}; + +Cipher.prototype.update = function update(data) { + if (data.length === 0) + return []; + + if (this.type === 'decrypt') + return this._updateDecrypt(data); + else + return this._updateEncrypt(data); +}; + +Cipher.prototype._buffer = function _buffer(data, off) { + // Append data to buffer + var min = Math.min(this.buffer.length - this.bufferOff, data.length - off); + for (var i = 0; i < min; i++) + this.buffer[this.bufferOff + i] = data[off + i]; + this.bufferOff += min; + + // Shift next + return min; +}; + +Cipher.prototype._flushBuffer = function _flushBuffer(out, off) { + this._update(this.buffer, 0, out, off); + this.bufferOff = 0; + return this.blockSize; +}; + +Cipher.prototype._updateEncrypt = function _updateEncrypt(data) { + var inputOff = 0; + var outputOff = 0; + + var count = ((this.bufferOff + data.length) / this.blockSize) | 0; + var out = new Array(count * this.blockSize); + + if (this.bufferOff !== 0) { + inputOff += this._buffer(data, inputOff); + + if (this.bufferOff === this.buffer.length) + outputOff += this._flushBuffer(out, outputOff); + } + + // Write blocks + var max = data.length - ((data.length - inputOff) % this.blockSize); + for (; inputOff < max; inputOff += this.blockSize) { + this._update(data, inputOff, out, outputOff); + outputOff += this.blockSize; + } + + // Queue rest + for (; inputOff < data.length; inputOff++, this.bufferOff++) + this.buffer[this.bufferOff] = data[inputOff]; + + return out; +}; + +Cipher.prototype._updateDecrypt = function _updateDecrypt(data) { + var inputOff = 0; + var outputOff = 0; + + var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1; + var out = new Array(count * this.blockSize); + + // TODO(indutny): optimize it, this is far from optimal + for (; count > 0; count--) { + inputOff += this._buffer(data, inputOff); + outputOff += this._flushBuffer(out, outputOff); + } + + // Buffer rest of the input + inputOff += this._buffer(data, inputOff); + + return out; +}; + +Cipher.prototype.final = function final(buffer) { + var first; + if (buffer) + first = this.update(buffer); + + var last; + if (this.type === 'encrypt') + last = this._finalEncrypt(); + else + last = this._finalDecrypt(); + + if (first) + return first.concat(last); + else + return last; +}; + +Cipher.prototype._pad = function _pad(buffer, off) { + if (off === 0) + return false; + + while (off < buffer.length) + buffer[off++] = 0; + + return true; +}; + +Cipher.prototype._finalEncrypt = function _finalEncrypt() { + if (!this._pad(this.buffer, this.bufferOff)) + return []; + + var out = new Array(this.blockSize); + this._update(this.buffer, 0, out, 0); + return out; +}; + +Cipher.prototype._unpad = function _unpad(buffer) { + return buffer; +}; + +Cipher.prototype._finalDecrypt = function _finalDecrypt() { + assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt'); + var out = new Array(this.blockSize); + this._flushBuffer(out, 0); + + return this._unpad(out); +}; + +},{"minimalistic-assert":234}],145:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); + +var utils = require('./utils'); +var Cipher = require('./cipher'); + +function DESState() { + this.tmp = new Array(2); + this.keys = null; +} + +function DES(options) { + Cipher.call(this, options); + + var state = new DESState(); + this._desState = state; + + this.deriveKeys(state, options.key); +} +inherits(DES, Cipher); +module.exports = DES; + +DES.create = function create(options) { + return new DES(options); +}; + +var shiftTable = [ + 1, 1, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 1 +]; + +DES.prototype.deriveKeys = function deriveKeys(state, key) { + state.keys = new Array(16 * 2); + + assert.equal(key.length, this.blockSize, 'Invalid key length'); + + var kL = utils.readUInt32BE(key, 0); + var kR = utils.readUInt32BE(key, 4); + + utils.pc1(kL, kR, state.tmp, 0); + kL = state.tmp[0]; + kR = state.tmp[1]; + for (var i = 0; i < state.keys.length; i += 2) { + var shift = shiftTable[i >>> 1]; + kL = utils.r28shl(kL, shift); + kR = utils.r28shl(kR, shift); + utils.pc2(kL, kR, state.keys, i); + } +}; + +DES.prototype._update = function _update(inp, inOff, out, outOff) { + var state = this._desState; + + var l = utils.readUInt32BE(inp, inOff); + var r = utils.readUInt32BE(inp, inOff + 4); + + // Initial Permutation + utils.ip(l, r, state.tmp, 0); + l = state.tmp[0]; + r = state.tmp[1]; + + if (this.type === 'encrypt') + this._encrypt(state, l, r, state.tmp, 0); + else + this._decrypt(state, l, r, state.tmp, 0); + + l = state.tmp[0]; + r = state.tmp[1]; + + utils.writeUInt32BE(out, l, outOff); + utils.writeUInt32BE(out, r, outOff + 4); +}; + +DES.prototype._pad = function _pad(buffer, off) { + var value = buffer.length - off; + for (var i = off; i < buffer.length; i++) + buffer[i] = value; + + return true; +}; + +DES.prototype._unpad = function _unpad(buffer) { + var pad = buffer[buffer.length - 1]; + for (var i = buffer.length - pad; i < buffer.length; i++) + assert.equal(buffer[i], pad); + + return buffer.slice(0, buffer.length - pad); +}; + +DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) { + var l = lStart; + var r = rStart; + + // Apply f() x16 times + for (var i = 0; i < state.keys.length; i += 2) { + var keyL = state.keys[i]; + var keyR = state.keys[i + 1]; + + // f(r, k) + utils.expand(r, state.tmp, 0); + + keyL ^= state.tmp[0]; + keyR ^= state.tmp[1]; + var s = utils.substitute(keyL, keyR); + var f = utils.permute(s); + + var t = r; + r = (l ^ f) >>> 0; + l = t; + } + + // Reverse Initial Permutation + utils.rip(r, l, out, off); +}; + +DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) { + var l = rStart; + var r = lStart; + + // Apply f() x16 times + for (var i = state.keys.length - 2; i >= 0; i -= 2) { + var keyL = state.keys[i]; + var keyR = state.keys[i + 1]; + + // f(r, k) + utils.expand(l, state.tmp, 0); + + keyL ^= state.tmp[0]; + keyR ^= state.tmp[1]; + var s = utils.substitute(keyL, keyR); + var f = utils.permute(s); + + var t = l; + l = (r ^ f) >>> 0; + r = t; + } + + // Reverse Initial Permutation + utils.rip(l, r, out, off); +}; + +},{"./cipher":144,"./utils":147,"inherits":224,"minimalistic-assert":234}],146:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); + +var Cipher = require('./cipher'); +var DES = require('./des'); + +function EDEState(type, key) { + assert.equal(key.length, 24, 'Invalid key length'); + + var k1 = key.slice(0, 8); + var k2 = key.slice(8, 16); + var k3 = key.slice(16, 24); + + if (type === 'encrypt') { + this.ciphers = [ + DES.create({ type: 'encrypt', key: k1 }), + DES.create({ type: 'decrypt', key: k2 }), + DES.create({ type: 'encrypt', key: k3 }) + ]; + } else { + this.ciphers = [ + DES.create({ type: 'decrypt', key: k3 }), + DES.create({ type: 'encrypt', key: k2 }), + DES.create({ type: 'decrypt', key: k1 }) + ]; + } +} + +function EDE(options) { + Cipher.call(this, options); + + var state = new EDEState(this.type, this.options.key); + this._edeState = state; +} +inherits(EDE, Cipher); + +module.exports = EDE; + +EDE.create = function create(options) { + return new EDE(options); +}; + +EDE.prototype._update = function _update(inp, inOff, out, outOff) { + var state = this._edeState; + + state.ciphers[0]._update(inp, inOff, out, outOff); + state.ciphers[1]._update(out, outOff, out, outOff); + state.ciphers[2]._update(out, outOff, out, outOff); +}; + +EDE.prototype._pad = DES.prototype._pad; +EDE.prototype._unpad = DES.prototype._unpad; + +},{"./cipher":144,"./des":145,"inherits":224,"minimalistic-assert":234}],147:[function(require,module,exports){ +'use strict'; + +exports.readUInt32BE = function readUInt32BE(bytes, off) { + var res = (bytes[0 + off] << 24) | + (bytes[1 + off] << 16) | + (bytes[2 + off] << 8) | + bytes[3 + off]; + return res >>> 0; +}; + +exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) { + bytes[0 + off] = value >>> 24; + bytes[1 + off] = (value >>> 16) & 0xff; + bytes[2 + off] = (value >>> 8) & 0xff; + bytes[3 + off] = value & 0xff; +}; + +exports.ip = function ip(inL, inR, out, off) { + var outL = 0; + var outR = 0; + + for (var i = 6; i >= 0; i -= 2) { + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >>> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inL >>> (j + i)) & 1; + } + } + + for (var i = 6; i >= 0; i -= 2) { + for (var j = 1; j <= 25; j += 8) { + outR <<= 1; + outR |= (inR >>> (j + i)) & 1; + } + for (var j = 1; j <= 25; j += 8) { + outR <<= 1; + outR |= (inL >>> (j + i)) & 1; + } + } + + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; + +exports.rip = function rip(inL, inR, out, off) { + var outL = 0; + var outR = 0; + + for (var i = 0; i < 4; i++) { + for (var j = 24; j >= 0; j -= 8) { + outL <<= 1; + outL |= (inR >>> (j + i)) & 1; + outL <<= 1; + outL |= (inL >>> (j + i)) & 1; + } + } + for (var i = 4; i < 8; i++) { + for (var j = 24; j >= 0; j -= 8) { + outR <<= 1; + outR |= (inR >>> (j + i)) & 1; + outR <<= 1; + outR |= (inL >>> (j + i)) & 1; + } + } + + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; + +exports.pc1 = function pc1(inL, inR, out, off) { + var outL = 0; + var outR = 0; + + // 7, 15, 23, 31, 39, 47, 55, 63 + // 6, 14, 22, 30, 39, 47, 55, 63 + // 5, 13, 21, 29, 39, 47, 55, 63 + // 4, 12, 20, 28 + for (var i = 7; i >= 5; i--) { + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inL >> (j + i)) & 1; + } + } + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >> (j + i)) & 1; + } + + // 1, 9, 17, 25, 33, 41, 49, 57 + // 2, 10, 18, 26, 34, 42, 50, 58 + // 3, 11, 19, 27, 35, 43, 51, 59 + // 36, 44, 52, 60 + for (var i = 1; i <= 3; i++) { + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inR >> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inL >> (j + i)) & 1; + } + } + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inL >> (j + i)) & 1; + } + + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; + +exports.r28shl = function r28shl(num, shift) { + return ((num << shift) & 0xfffffff) | (num >>> (28 - shift)); +}; + +var pc2table = [ + // inL => outL + 14, 11, 17, 4, 27, 23, 25, 0, + 13, 22, 7, 18, 5, 9, 16, 24, + 2, 20, 12, 21, 1, 8, 15, 26, + + // inR => outR + 15, 4, 25, 19, 9, 1, 26, 16, + 5, 11, 23, 8, 12, 7, 17, 0, + 22, 3, 10, 14, 6, 20, 27, 24 +]; + +exports.pc2 = function pc2(inL, inR, out, off) { + var outL = 0; + var outR = 0; + + var len = pc2table.length >>> 1; + for (var i = 0; i < len; i++) { + outL <<= 1; + outL |= (inL >>> pc2table[i]) & 0x1; + } + for (var i = len; i < pc2table.length; i++) { + outR <<= 1; + outR |= (inR >>> pc2table[i]) & 0x1; + } + + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; + +exports.expand = function expand(r, out, off) { + var outL = 0; + var outR = 0; + + outL = ((r & 1) << 5) | (r >>> 27); + for (var i = 23; i >= 15; i -= 4) { + outL <<= 6; + outL |= (r >>> i) & 0x3f; + } + for (var i = 11; i >= 3; i -= 4) { + outR |= (r >>> i) & 0x3f; + outR <<= 6; + } + outR |= ((r & 0x1f) << 1) | (r >>> 31); + + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; + +var sTable = [ + 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, + 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, + 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, + 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, + + 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, + 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, + 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, + 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, + + 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, + 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, + 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, + 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, + + 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, + 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, + 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, + 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, + + 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, + 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, + 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, + 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, + + 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, + 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, + 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, + 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, + + 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, + 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, + 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, + 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, + + 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, + 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, + 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, + 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 +]; + +exports.substitute = function substitute(inL, inR) { + var out = 0; + for (var i = 0; i < 4; i++) { + var b = (inL >>> (18 - i * 6)) & 0x3f; + var sb = sTable[i * 0x40 + b]; + + out <<= 4; + out |= sb; + } + for (var i = 0; i < 4; i++) { + var b = (inR >>> (18 - i * 6)) & 0x3f; + var sb = sTable[4 * 0x40 + i * 0x40 + b]; + + out <<= 4; + out |= sb; + } + return out >>> 0; +}; + +var permuteTable = [ + 16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22, + 30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7 +]; + +exports.permute = function permute(num) { + var out = 0; + for (var i = 0; i < permuteTable.length; i++) { + out <<= 1; + out |= (num >>> permuteTable[i]) & 0x1; + } + return out >>> 0; +}; + +exports.padSplit = function padSplit(num, size, group) { + var str = num.toString(2); + while (str.length < size) + str = '0' + str; + + var out = []; + for (var i = 0; i < size; i += group) + out.push(str.slice(i, i + group)); + return out.join(' '); +}; + +},{}],148:[function(require,module,exports){ +(function (Buffer){ +var generatePrime = require('./lib/generatePrime') +var primes = require('./lib/primes.json') + +var DH = require('./lib/dh') + +function getDiffieHellman (mod) { + var prime = new Buffer(primes[mod].prime, 'hex') + var gen = new Buffer(primes[mod].gen, 'hex') + + return new DH(prime, gen) +} + +var ENCODINGS = { + 'binary': true, 'hex': true, 'base64': true +} + +function createDiffieHellman (prime, enc, generator, genc) { + if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) { + return createDiffieHellman(prime, 'binary', enc, generator) + } + + enc = enc || 'binary' + genc = genc || 'binary' + generator = generator || new Buffer([2]) + + if (!Buffer.isBuffer(generator)) { + generator = new Buffer(generator, genc) + } + + if (typeof prime === 'number') { + return new DH(generatePrime(prime, generator), generator, true) + } + + if (!Buffer.isBuffer(prime)) { + prime = new Buffer(prime, enc) + } + + return new DH(prime, generator, true) +} + +exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman +exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman + +}).call(this,require("buffer").Buffer) + +},{"./lib/dh":149,"./lib/generatePrime":150,"./lib/primes.json":151,"buffer":129}],149:[function(require,module,exports){ +(function (Buffer){ +var BN = require('bn.js'); +var MillerRabin = require('miller-rabin'); +var millerRabin = new MillerRabin(); +var TWENTYFOUR = new BN(24); +var ELEVEN = new BN(11); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); +var primes = require('./generatePrime'); +var randomBytes = require('randombytes'); +module.exports = DH; + +function setPublicKey(pub, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(pub)) { + pub = new Buffer(pub, enc); + } + this._pub = new BN(pub); + return this; +} + +function setPrivateKey(priv, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(priv)) { + priv = new Buffer(priv, enc); + } + this._priv = new BN(priv); + return this; +} + +var primeCache = {}; +function checkPrime(prime, generator) { + var gen = generator.toString('hex'); + var hex = [gen, prime.toString(16)].join('_'); + if (hex in primeCache) { + return primeCache[hex]; + } + var error = 0; + + if (prime.isEven() || + !primes.simpleSieve || + !primes.fermatTest(prime) || + !millerRabin.test(prime)) { + //not a prime so +1 + error += 1; + + if (gen === '02' || gen === '05') { + // we'd be able to check the generator + // it would fail so +8 + error += 8; + } else { + //we wouldn't be able to test the generator + // so +4 + error += 4; + } + primeCache[hex] = error; + return error; + } + if (!millerRabin.test(prime.shrn(1))) { + //not a safe prime + error += 2; + } + var rem; + switch (gen) { + case '02': + if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { + // unsuidable generator + error += 8; + } + break; + case '05': + rem = prime.mod(TEN); + if (rem.cmp(THREE) && rem.cmp(SEVEN)) { + // prime mod 10 needs to equal 3 or 7 + error += 8; + } + break; + default: + error += 4; + } + primeCache[hex] = error; + return error; +} + +function DH(prime, generator, malleable) { + this.setGenerator(generator); + this.__prime = new BN(prime); + this._prime = BN.mont(this.__prime); + this._primeLen = prime.length; + this._pub = undefined; + this._priv = undefined; + this._primeCode = undefined; + if (malleable) { + this.setPublicKey = setPublicKey; + this.setPrivateKey = setPrivateKey; + } else { + this._primeCode = 8; + } +} +Object.defineProperty(DH.prototype, 'verifyError', { + enumerable: true, + get: function () { + if (typeof this._primeCode !== 'number') { + this._primeCode = checkPrime(this.__prime, this.__gen); + } + return this._primeCode; + } +}); +DH.prototype.generateKeys = function () { + if (!this._priv) { + this._priv = new BN(randomBytes(this._primeLen)); + } + this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); + return this.getPublicKey(); +}; + +DH.prototype.computeSecret = function (other) { + other = new BN(other); + other = other.toRed(this._prime); + var secret = other.redPow(this._priv).fromRed(); + var out = new Buffer(secret.toArray()); + var prime = this.getPrime(); + if (out.length < prime.length) { + var front = new Buffer(prime.length - out.length); + front.fill(0); + out = Buffer.concat([front, out]); + } + return out; +}; + +DH.prototype.getPublicKey = function getPublicKey(enc) { + return formatReturnValue(this._pub, enc); +}; + +DH.prototype.getPrivateKey = function getPrivateKey(enc) { + return formatReturnValue(this._priv, enc); +}; + +DH.prototype.getPrime = function (enc) { + return formatReturnValue(this.__prime, enc); +}; + +DH.prototype.getGenerator = function (enc) { + return formatReturnValue(this._gen, enc); +}; + +DH.prototype.setGenerator = function (gen, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(gen)) { + gen = new Buffer(gen, enc); + } + this.__gen = gen; + this._gen = new BN(gen); + return this; +}; + +function formatReturnValue(bn, enc) { + var buf = new Buffer(bn.toArray()); + if (!enc) { + return buf; + } else { + return buf.toString(enc); + } +} + +}).call(this,require("buffer").Buffer) + +},{"./generatePrime":150,"bn.js":152,"buffer":129,"miller-rabin":232,"randombytes":260}],150:[function(require,module,exports){ +var randomBytes = require('randombytes'); +module.exports = findPrime; +findPrime.simpleSieve = simpleSieve; +findPrime.fermatTest = fermatTest; +var BN = require('bn.js'); +var TWENTYFOUR = new BN(24); +var MillerRabin = require('miller-rabin'); +var millerRabin = new MillerRabin(); +var ONE = new BN(1); +var TWO = new BN(2); +var FIVE = new BN(5); +var SIXTEEN = new BN(16); +var EIGHT = new BN(8); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); +var ELEVEN = new BN(11); +var FOUR = new BN(4); +var TWELVE = new BN(12); +var primes = null; + +function _getPrimes() { + if (primes !== null) + return primes; + + var limit = 0x100000; + var res = []; + res[0] = 2; + for (var i = 1, k = 3; k < limit; k += 2) { + var sqrt = Math.ceil(Math.sqrt(k)); + for (var j = 0; j < i && res[j] <= sqrt; j++) + if (k % res[j] === 0) + break; + + if (i !== j && res[j] <= sqrt) + continue; + + res[i++] = k; + } + primes = res; + return res; +} + +function simpleSieve(p) { + var primes = _getPrimes(); + + for (var i = 0; i < primes.length; i++) + if (p.modn(primes[i]) === 0) { + if (p.cmpn(primes[i]) === 0) { + return true; + } else { + return false; + } + } + + return true; +} + +function fermatTest(p) { + var red = BN.mont(p); + return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0; +} + +function findPrime(bits, gen) { + if (bits < 16) { + // this is what openssl does + if (gen === 2 || gen === 5) { + return new BN([0x8c, 0x7b]); + } else { + return new BN([0x8c, 0x27]); + } + } + gen = new BN(gen); + + var num, n2; + + while (true) { + num = new BN(randomBytes(Math.ceil(bits / 8))); + while (num.bitLength() > bits) { + num.ishrn(1); + } + if (num.isEven()) { + num.iadd(ONE); + } + if (!num.testn(1)) { + num.iadd(TWO); + } + if (!gen.cmp(TWO)) { + while (num.mod(TWENTYFOUR).cmp(ELEVEN)) { + num.iadd(FOUR); + } + } else if (!gen.cmp(FIVE)) { + while (num.mod(TEN).cmp(THREE)) { + num.iadd(FOUR); + } + } + n2 = num.shrn(1); + if (simpleSieve(n2) && simpleSieve(num) && + fermatTest(n2) && fermatTest(num) && + millerRabin.test(n2) && millerRabin.test(num)) { + return num; + } + } + +} + +},{"bn.js":152,"miller-rabin":232,"randombytes":260}],151:[function(require,module,exports){ +module.exports={ + "modp1": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff" + }, + "modp2": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff" + }, + "modp5": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff" + }, + "modp14": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff" + }, + "modp15": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff" + }, + "modp16": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff" + }, + "modp17": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff" + }, + "modp18": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff" + } +} +},{}],152:[function(require,module,exports){ +arguments[4][75][0].apply(exports,arguments) +},{"buffer":82,"dup":75}],153:[function(require,module,exports){ +'use strict'; + +var elliptic = exports; + +elliptic.version = require('../package.json').version; +elliptic.utils = require('./elliptic/utils'); +elliptic.rand = require('brorand'); +elliptic.curve = require('./elliptic/curve'); +elliptic.curves = require('./elliptic/curves'); + +// Protocols +elliptic.ec = require('./elliptic/ec'); +elliptic.eddsa = require('./elliptic/eddsa'); + +},{"../package.json":169,"./elliptic/curve":156,"./elliptic/curves":159,"./elliptic/ec":160,"./elliptic/eddsa":163,"./elliptic/utils":167,"brorand":81}],154:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var utils = require('../utils'); +var getNAF = utils.getNAF; +var getJSF = utils.getJSF; +var assert = utils.assert; + +function BaseCurve(type, conf) { + this.type = type; + this.p = new BN(conf.p, 16); + + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); + + // Useful for many curves + this.zero = new BN(0).toRed(this.red); + this.one = new BN(1).toRed(this.red); + this.two = new BN(2).toRed(this.red); + + // Curve configuration, optional + this.n = conf.n && new BN(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); + + this._bitLength = this.n ? this.n.bitLength() : 0; + + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } +} +module.exports = BaseCurve; + +BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert(p.precomputed); + var doubles = p._getDoubles(); + + var naf = getNAF(k, 1, this._bitLength); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; + + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } + + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); +}; + +BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; + + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + + // Get NAF form + var naf = getNAF(k, w, this._bitLength); + + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); + + if (i < 0) + break; + var z = naf[i]; + assert(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; +}; + +BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; + + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } + + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a], this._bitLength); + naf[b] = getNAF(coeffs[b], wndWidth[b], this._bitLength); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } + + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; + + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } + + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; + + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; + + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } + } + + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; + + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; + + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); + + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; + + if (jacobianResult) + return acc; + else + return acc.toP(); +}; + +function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; +} +BaseCurve.BasePoint = BasePoint; + +BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); +}; + +BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); +}; + +BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils.toArray(bytes, enc); + + var len = this.p.byteLength(); + + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert(bytes[bytes.length - 1] % 2 === 1); + + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); + + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); +}; + +BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); +}; + +BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); + + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); + + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; +}; + +BasePoint.prototype.encode = function encode(enc, compact) { + return utils.encode(this._encode(compact), enc); +}; + +BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; + + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; + + return this; +}; + +BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; + + var doubles = this.precomputed.doubles; + if (!doubles) + return false; + + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); +}; + +BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; + + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); + } + return { + step: step, + points: doubles + }; +}; + +BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; +}; + +BasePoint.prototype._getBeta = function _getBeta() { + return null; +}; + +BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; +}; + +},{"../utils":167,"bn.js":168}],155:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); + +var assert = utils.assert; + +function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; + + Base.call(this, 'edwards', conf); + + this.a = new BN(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new BN(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new BN(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); + + assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; +} +inherits(EdwardsCurve, Base); +module.exports = EdwardsCurve; + +EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); +}; + +EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); +}; + +// Just for compatibility with Short curve +EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); +}; + +EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); + + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new BN(y, 16); + if (!y.red) + y = y.toRed(this.red); + + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); + + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } + + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; + + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); + + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); + + return lhs.cmp(rhs) === 0; +}; + +function Point(curve, x, y, z, t) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = z ? new BN(z, 16) : this.curve.one; + this.t = t && new BN(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; + + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } +} +inherits(Point, Base.BasePoint); + +EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; + +EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point(this, x, y, z, t); +}; + +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1], obj[2]); +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); +}; + +Point.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); + + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); + } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); + } + return this.curve.point(nx, ny, nz); +}; + +Point.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); +}; + +Point.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M + + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S + + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); + } + return this.curve.point(nx, ny, nz); +}; + +Point.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; + + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); +}; + +Point.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); +}; + +Point.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); +}; + +Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); +}; + +Point.prototype.normalize = function normalize() { + if (this.zOne) + return this; + + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; +}; + +Point.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); +}; + +Point.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); +}; + +Point.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); +}; + +Point.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; +}; + +Point.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +// Compatibility with BaseCurve +Point.prototype.toP = Point.prototype.normalize; +Point.prototype.mixedAdd = Point.prototype.add; + +},{"../utils":167,"./base":154,"bn.js":168,"inherits":224}],156:[function(require,module,exports){ +'use strict'; + +var curve = exports; + +curve.base = require('./base'); +curve.short = require('./short'); +curve.mont = require('./mont'); +curve.edwards = require('./edwards'); + +},{"./base":154,"./edwards":155,"./mont":157,"./short":158}],157:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); + +var utils = require('../utils'); + +function MontCurve(conf) { + Base.call(this, 'mont', conf); + + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.i4 = new BN(4).toRed(this.red).redInvm(); + this.two = new BN(2).toRed(this.red); + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); +} +inherits(MontCurve, Base); +module.exports = MontCurve; + +MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); + + return y.redSqr().cmp(rhs) === 0; +}; + +function Point(curve, x, z) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new BN(x, 16); + this.z = new BN(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } +} +inherits(Point, Base.BasePoint); + +MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + return this.point(utils.toArray(bytes, enc), 1); +}; + +MontCurve.prototype.point = function point(x, z) { + return new Point(this, x, z); +}; + +MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; + +Point.prototype.precompute = function precompute() { + // No-op +}; + +Point.prototype._encode = function _encode() { + return this.getX().toArray('be', this.curve.p.byteLength()); +}; + +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1] || curve.one); +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +Point.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); +}; + +Point.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A + + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); +}; + +Point.prototype.mul = function mul(k) { + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q + + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; +}; + +Point.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; +}; + +Point.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; +}; + +Point.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); +}; + +},{"../utils":167,"./base":154,"bn.js":168,"inherits":224}],158:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); + +var assert = utils.assert; + +function ShortCurve(conf) { + Base.call(this, 'short', conf); + + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); + + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; + + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); +} +inherits(ShortCurve, Base); +module.exports = ShortCurve; + +ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; + + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new BN(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new BN(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } + + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new BN(vec.a, 16), + b: new BN(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } + + return { + beta: beta, + lambda: lambda, + basis: basis + }; +}; + +ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : BN.mont(num); + var tinv = new BN(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); + + var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); + + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; +}; + +ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); + + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new BN(1); + var y1 = new BN(0); + var x2 = new BN(0); + var y2 = new BN(1); + + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; + + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; + + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; + + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } + + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; +}; + +ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; + + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); + + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); + + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; +}; + +ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; + + var x = point.x; + var y = point.y; + + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; +}; + +ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); + + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } + + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; +}; + +function Point(curve, x, y, isRed) { + Base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } +} +inherits(Point, Base.BasePoint); + +ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); +}; + +ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); +}; + +Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) + } + }; + } + return beta; +}; + +Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) + } + } ]; +}; + +Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } + + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + return this.inf; +}; + +Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; + + // P + O = P + if (p.inf) + return this; + + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.dbl = function dbl() { + if (this.inf) + return this; + + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); + + var a = this.curve.a; + + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.getX = function getX() { + return this.x.fromRed(); +}; + +Point.prototype.getY = function getY() { + return this.y.fromRed(); +}; + +Point.prototype.mul = function mul(k) { + k = new BN(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); +}; + +Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); +}; + +Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); +}; + +Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); +}; + +Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; + + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; + } + return res; +}; + +Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); + + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; +}; + +function JPoint(curve, x, y, z) { + Base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new BN(0); + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = new BN(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; +} +inherits(JPoint, Base.BasePoint); + +ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); +}; + +JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); + + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); + + return this.curve.point(ax, ay); +}; + +JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); +}; + +JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; + + // P + O = P + if (p.isInfinity()) + return this; + + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); + + // P + O = P + if (p.isInfinity()) + return this; + + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); + + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; + } + + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; + + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); + + jx = nx; + jz = nz; + jyd = dny; + } + + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); +}; + +JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); +}; + +JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); + + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); + + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); + + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S + + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; + + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); + + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); + + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mul = function mul(k, kbase) { + k = new BN(k, kbase); + + return this.curve._wnafMul(this, k); +}; + +JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); + + if (this === p) + return true; + + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; + + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; +}; + +JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +},{"../utils":167,"./base":154,"bn.js":168,"inherits":224}],159:[function(require,module,exports){ +'use strict'; + +var curves = exports; + +var hash = require('hash.js'); +var curve = require('./curve'); +var utils = require('./utils'); + +var assert = utils.assert; + +function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve.short(options); + else if (options.type === 'edwards') + this.curve = new curve.edwards(options); + else + this.curve = new curve.mont(options); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; + + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O'); +} +curves.PresetCurve = PresetCurve; + +function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; + } + }); +} + +defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] +}); + +defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] +}); + +defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] +}); + +defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] +}); + +defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] +}); + +defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + hash: hash.sha256, + gRed: false, + g: [ + '9' + ] +}); + +defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + hash: hash.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] +}); + +var pre; +try { + pre = require('./precomputed/secp256k1'); +} catch (e) { + pre = undefined; +} + +defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash.sha256, + + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], + + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] +}); + +},{"./curve":156,"./precomputed/secp256k1":166,"./utils":167,"hash.js":209}],160:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var HmacDRBG = require('hmac-drbg'); +var utils = require('../utils'); +var curves = require('../curves'); +var rand = require('brorand'); +var assert = utils.assert; + +var KeyPair = require('./key'); +var Signature = require('./signature'); + +function EC(options) { + if (!(this instanceof EC)) + return new EC(options); + + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert(curves.hasOwnProperty(options), 'Unknown curve ' + options); + + options = curves[options]; + } + + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves.PresetCurve) + options = { curve: options }; + + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; + + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); + + // Hash for function for DRBG + this.hash = options.hash || options.curve.hash; +} +module.exports = EC; + +EC.prototype.keyPair = function keyPair(options) { + return new KeyPair(this, options); +}; + +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return KeyPair.fromPrivate(this, priv, enc); +}; + +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return KeyPair.fromPublic(this, pub, enc); +}; + +EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || rand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); + + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new BN(2)); + do { + var priv = new BN(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; + + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); +}; + +EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { + var delta = msg.byteLength() * 8 - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; +}; + +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; + + key = this.keyFromPrivate(key, enc); + msg = this._truncateToN(new BN(msg, 16)); + + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); + + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); + + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); + + // Number of bytes to generate + var ns1 = this.n.sub(new BN(1)); + + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new BN(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; + + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; + + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; + + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; + + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); + } +}; + +EC.prototype.verify = function verify(msg, signature, key, enc) { + msg = this._truncateToN(new BN(msg, 16)); + key = this.keyFromPublic(key, enc); + signature = new Signature(signature, 'hex'); + + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; + + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + return p.getX().umod(this.n).cmp(r) === 0; + } + + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K + + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); +}; + +EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert((3 & j) === j, 'The recovery param is more than two bits'); + signature = new Signature(signature, enc); + + var n = this.n; + var e = new BN(msg); + var r = signature.r; + var s = signature.s; + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); + + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); + + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); +}; + +EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new Signature(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } + + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); +}; + +},{"../curves":159,"../utils":167,"./key":161,"./signature":162,"bn.js":168,"brorand":81,"hmac-drbg":221}],161:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var utils = require('../utils'); +var assert = utils.assert; + +function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; + + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); +} +module.exports = KeyPair; + +KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; + + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); +}; + +KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; + + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); +}; + +KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); + + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; + + return { result: true, reason: null }; +}; + +KeyPair.prototype.getPublic = function getPublic(compact, enc) { + // compact is optional argument + if (typeof compact === 'string') { + enc = compact; + compact = null; + } + + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); + + if (!enc) + return this.pub; + + return this.pub.encode(enc, compact); +}; + +KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; +}; + +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new BN(key, enc || 16); + + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); +}; + +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); +}; + +// ECDH +KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); +}; + +// ECDSA +KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); +}; + +KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); +}; + +KeyPair.prototype.inspect = function inspect() { + return ''; +}; + +},{"../utils":167,"bn.js":168}],162:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); + +var utils = require('../utils'); +var assert = utils.assert; + +function Signature(options, enc) { + if (options instanceof Signature) + return options; + + if (this._importDER(options, enc)) + return; + + assert(options.r && options.s, 'Signature without r or s'); + this.r = new BN(options.r, 16); + this.s = new BN(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; +} +module.exports = Signature; + +function Position() { + this.place = 0; +} + +function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; +} + +function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); +} + +Signature.prototype._importDER = function _importDER(data, enc) { + data = utils.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } + + this.r = new BN(r); + this.s = new BN(s); + this.recoveryParam = null; + + return true; +}; + +function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); +} + +Signature.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); + + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); + + r = rmPadding(r); + s = rmPadding(s); + + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils.encode(res, enc); +}; + +},{"../utils":167,"bn.js":168}],163:[function(require,module,exports){ +'use strict'; + +var hash = require('hash.js'); +var curves = require('../curves'); +var utils = require('../utils'); +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var KeyPair = require('./key'); +var Signature = require('./signature'); + +function EDDSA(curve) { + assert(curve === 'ed25519', 'only tested with ed25519 so far'); + + if (!(this instanceof EDDSA)) + return new EDDSA(curve); + + var curve = curves[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); + + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash.sha512; +} + +module.exports = EDDSA; + +/** +* @param {Array|String} message - message bytes +* @param {Array|String|KeyPair} secret - secret bytes or a keypair +* @returns {Signature} - signature +*/ +EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); +}; + +/** +* @param {Array} message - message bytes +* @param {Array|String|Signature} sig - sig bytes +* @param {Array|String|Point|KeyPair} pub - public key +* @returns {Boolean} - true if public key matches sig of message +*/ +EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); +}; + +EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils.intFromLE(hash.digest()).umod(this.curve.n); +}; + +EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return KeyPair.fromPublic(this, pub); +}; + +EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return KeyPair.fromSecret(this, secret); +}; + +EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof Signature) + return sig; + return new Signature(this, sig); +}; + +/** +* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 +* +* EDDSA defines methods for encoding and decoding points and integers. These are +* helper convenience methods, that pass along to utility functions implied +* parameters. +* +*/ +EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; +}; + +EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); +}; + +EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); +}; + +EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils.intFromLE(bytes); +}; + +EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; +}; + +},{"../curves":159,"../utils":167,"./key":164,"./signature":165,"hash.js":209}],164:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var cachedProperty = utils.cachedProperty; + +/** +* @param {EDDSA} eddsa - instance +* @param {Object} params - public/private key parameters +* +* @param {Array} [params.secret] - secret seed bytes +* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) +* @param {Array} [params.pub] - public key point encoded as bytes +* +*/ +function KeyPair(eddsa, params) { + this.eddsa = eddsa; + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else + this._pubBytes = parseBytes(params.pub); +} + +KeyPair.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair) + return pub; + return new KeyPair(eddsa, { pub: pub }); +}; + +KeyPair.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair) + return secret; + return new KeyPair(eddsa, { secret: secret }); +}; + +KeyPair.prototype.secret = function secret() { + return this._secret; +}; + +cachedProperty(KeyPair, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); +}); + +cachedProperty(KeyPair, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); +}); + +cachedProperty(KeyPair, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; + + return a; +}); + +cachedProperty(KeyPair, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); +}); + +cachedProperty(KeyPair, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); +}); + +cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); +}); + +KeyPair.prototype.sign = function sign(message) { + assert(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); +}; + +KeyPair.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); +}; + +KeyPair.prototype.getSecret = function getSecret(enc) { + assert(this._secret, 'KeyPair is public only'); + return utils.encode(this.secret(), enc); +}; + +KeyPair.prototype.getPublic = function getPublic(enc) { + return utils.encode(this.pubBytes(), enc); +}; + +module.exports = KeyPair; + +},{"../utils":167}],165:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var utils = require('../utils'); +var assert = utils.assert; +var cachedProperty = utils.cachedProperty; +var parseBytes = utils.parseBytes; + +/** +* @param {EDDSA} eddsa - eddsa instance +* @param {Array|Object} sig - +* @param {Array|Point} [sig.R] - R point as Point or bytes +* @param {Array|bn} [sig.S] - S scalar as bn or bytes +* @param {Array} [sig.Rencoded] - R point encoded +* @param {Array} [sig.Sencoded] - S scalar encoded +*/ +function Signature(eddsa, sig) { + this.eddsa = eddsa; + + if (typeof sig !== 'object') + sig = parseBytes(sig); + + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; + } + + assert(sig.R && sig.S, 'Signature without R or S'); + + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof BN) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; +} + +cachedProperty(Signature, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); +}); + +cachedProperty(Signature, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); +}); + +cachedProperty(Signature, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); +}); + +cachedProperty(Signature, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); +}); + +Signature.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); +}; + +Signature.prototype.toHex = function toHex() { + return utils.encode(this.toBytes(), 'hex').toUpperCase(); +}; + +module.exports = Signature; + +},{"../utils":167,"bn.js":168}],166:[function(require,module,exports){ +module.exports = { + doubles: { + step: 4, + points: [ [ 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' @@ -23244,4746 +30957,7242 @@ module.exports = { ] ] } -}; +}; + +},{}],167:[function(require,module,exports){ +'use strict'; + +var utils = exports; +var BN = require('bn.js'); +var minAssert = require('minimalistic-assert'); +var minUtils = require('minimalistic-crypto-utils'); + +utils.assert = minAssert; +utils.toArray = minUtils.toArray; +utils.zero2 = minUtils.zero2; +utils.toHex = minUtils.toHex; +utils.encode = minUtils.encode; + +// Represent num in a w-NAF form +function getNAF(num, w, bits) { + var naf = new Array(Math.max(num.bitLength(), bits) + 1); + naf.fill(0); + + var ws = 1 << (w + 1); + var k = num.clone(); + + for (var i = 0; i < naf.length; i++) { + var z; + var mod = k.andln(ws - 1); + if (k.isOdd()) { + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); + } else { + z = 0; + } + + naf[i] = z; + k.iushrn(1); + } + + return naf; +} +utils.getNAF = getNAF; + +// Represent k1, k2 in a Joint Sparse Form +function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; + + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { + + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); + + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); + + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); + } + + return jsf; +} +utils.getJSF = getJSF; + +function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; +} +utils.cachedProperty = cachedProperty; + +function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; +} +utils.parseBytes = parseBytes; + +function intFromLE(bytes) { + return new BN(bytes, 'hex', 'le'); +} +utils.intFromLE = intFromLE; + + +},{"bn.js":168,"minimalistic-assert":234,"minimalistic-crypto-utils":235}],168:[function(require,module,exports){ +arguments[4][75][0].apply(exports,arguments) +},{"buffer":82,"dup":75}],169:[function(require,module,exports){ +module.exports={ + "_from": "elliptic@^6.5.2", + "_id": "elliptic@6.5.2", + "_inBundle": false, + "_integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "_location": "/elliptic", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "elliptic@^6.5.2", + "name": "elliptic", + "escapedName": "elliptic", + "rawSpec": "^6.5.2", + "saveSpec": null, + "fetchSpec": "^6.5.2" + }, + "_requiredBy": [ + "/browserify-sign", + "/create-ecdh" + ], + "_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "_shasum": "05c5678d7173c049d8ca433552224a495d0e3762", + "_spec": "elliptic@^6.5.2", + "_where": "C:\\Program Files\\nodejs\\node_modules\\jiff\\node_modules\\browserify-sign", + "author": { + "name": "Fedor Indutny", + "email": "fedor@indutny.com" + }, + "bugs": { + "url": "https://github.com/indutny/elliptic/issues" + }, + "bundleDependencies": false, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "deprecated": false, + "description": "EC cryptography", + "devDependencies": { + "brfs": "^1.4.3", + "coveralls": "^3.0.8", + "grunt": "^1.0.4", + "grunt-browserify": "^5.0.0", + "grunt-cli": "^1.2.0", + "grunt-contrib-connect": "^1.0.0", + "grunt-contrib-copy": "^1.0.0", + "grunt-contrib-uglify": "^1.0.1", + "grunt-mocha-istanbul": "^3.0.1", + "grunt-saucelabs": "^9.0.1", + "istanbul": "^0.4.2", + "jscs": "^3.0.7", + "jshint": "^2.10.3", + "mocha": "^6.2.2" + }, + "files": [ + "lib" + ], + "homepage": "https://github.com/indutny/elliptic", + "keywords": [ + "EC", + "Elliptic", + "curve", + "Cryptography" + ], + "license": "MIT", + "main": "lib/elliptic.js", + "name": "elliptic", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/indutny/elliptic.git" + }, + "scripts": { + "jscs": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js", + "jshint": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js", + "lint": "npm run jscs && npm run jshint", + "test": "npm run lint && npm run unit", + "unit": "istanbul test _mocha --reporter=spec test/index.js", + "version": "grunt dist && git add dist/" + }, + "version": "6.5.2" +} + +},{}],170:[function(require,module,exports){ +module.exports = (function () { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else { + return Function('return this')(); // eslint-disable-line no-new-func + } +})(); + +},{}],171:[function(require,module,exports){ + +module.exports = require('./socket'); + +/** + * Exports parser + * + * @api public + * + */ +module.exports.parser = require('engine.io-parser'); + +},{"./socket":172,"engine.io-parser":184}],172:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var transports = require('./transports/index'); +var Emitter = require('component-emitter'); +var debug = require('debug')('engine.io-client:socket'); +var index = require('indexof'); +var parser = require('engine.io-parser'); +var parseuri = require('parseuri'); +var parseqs = require('parseqs'); + +/** + * Module exports. + */ + +module.exports = Socket; + +/** + * Socket constructor. + * + * @param {String|Object} uri or options + * @param {Object} options + * @api public + */ + +function Socket (uri, opts) { + if (!(this instanceof Socket)) return new Socket(uri, opts); + + opts = opts || {}; + + if (uri && 'object' === typeof uri) { + opts = uri; + uri = null; + } + + if (uri) { + uri = parseuri(uri); + opts.hostname = uri.host; + opts.secure = uri.protocol === 'https' || uri.protocol === 'wss'; + opts.port = uri.port; + if (uri.query) opts.query = uri.query; + } else if (opts.host) { + opts.hostname = parseuri(opts.host).host; + } + + this.secure = null != opts.secure ? opts.secure + : (typeof location !== 'undefined' && 'https:' === location.protocol); + + if (opts.hostname && !opts.port) { + // if no port is specified manually, use the protocol default + opts.port = this.secure ? '443' : '80'; + } + + this.agent = opts.agent || false; + this.hostname = opts.hostname || + (typeof location !== 'undefined' ? location.hostname : 'localhost'); + this.port = opts.port || (typeof location !== 'undefined' && location.port + ? location.port + : (this.secure ? 443 : 80)); + this.query = opts.query || {}; + if ('string' === typeof this.query) this.query = parseqs.decode(this.query); + this.upgrade = false !== opts.upgrade; + this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; + this.forceJSONP = !!opts.forceJSONP; + this.jsonp = false !== opts.jsonp; + this.forceBase64 = !!opts.forceBase64; + this.enablesXDR = !!opts.enablesXDR; + this.withCredentials = false !== opts.withCredentials; + this.timestampParam = opts.timestampParam || 't'; + this.timestampRequests = opts.timestampRequests; + this.transports = opts.transports || ['polling', 'websocket']; + this.transportOptions = opts.transportOptions || {}; + this.readyState = ''; + this.writeBuffer = []; + this.prevBufferLen = 0; + this.policyPort = opts.policyPort || 843; + this.rememberUpgrade = opts.rememberUpgrade || false; + this.binaryType = null; + this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; + this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false; + + if (true === this.perMessageDeflate) this.perMessageDeflate = {}; + if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) { + this.perMessageDeflate.threshold = 1024; + } + + // SSL options for Node.js client + this.pfx = opts.pfx || null; + this.key = opts.key || null; + this.passphrase = opts.passphrase || null; + this.cert = opts.cert || null; + this.ca = opts.ca || null; + this.ciphers = opts.ciphers || null; + this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized; + this.forceNode = !!opts.forceNode; + + // detect ReactNative environment + this.isReactNative = (typeof navigator !== 'undefined' && typeof navigator.product === 'string' && navigator.product.toLowerCase() === 'reactnative'); + + // other options for Node.js or ReactNative client + if (typeof self === 'undefined' || this.isReactNative) { + if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) { + this.extraHeaders = opts.extraHeaders; + } + + if (opts.localAddress) { + this.localAddress = opts.localAddress; + } + } + + // set on handshake + this.id = null; + this.upgrades = null; + this.pingInterval = null; + this.pingTimeout = null; + + // set on heartbeat + this.pingIntervalTimer = null; + this.pingTimeoutTimer = null; + + this.open(); +} + +Socket.priorWebsocketSuccess = false; + +/** + * Mix in `Emitter`. + */ + +Emitter(Socket.prototype); + +/** + * Protocol version. + * + * @api public + */ + +Socket.protocol = parser.protocol; // this is an int + +/** + * Expose deps for legacy compatibility + * and standalone browser access. + */ + +Socket.Socket = Socket; +Socket.Transport = require('./transport'); +Socket.transports = require('./transports/index'); +Socket.parser = require('engine.io-parser'); + +/** + * Creates transport of the given type. + * + * @param {String} transport name + * @return {Transport} + * @api private + */ + +Socket.prototype.createTransport = function (name) { + debug('creating transport "%s"', name); + var query = clone(this.query); + + // append engine.io protocol identifier + query.EIO = parser.protocol; + + // transport name + query.transport = name; + + // per-transport options + var options = this.transportOptions[name] || {}; + + // session id if we already have one + if (this.id) query.sid = this.id; + + var transport = new transports[name]({ + query: query, + socket: this, + agent: options.agent || this.agent, + hostname: options.hostname || this.hostname, + port: options.port || this.port, + secure: options.secure || this.secure, + path: options.path || this.path, + forceJSONP: options.forceJSONP || this.forceJSONP, + jsonp: options.jsonp || this.jsonp, + forceBase64: options.forceBase64 || this.forceBase64, + enablesXDR: options.enablesXDR || this.enablesXDR, + withCredentials: options.withCredentials || this.withCredentials, + timestampRequests: options.timestampRequests || this.timestampRequests, + timestampParam: options.timestampParam || this.timestampParam, + policyPort: options.policyPort || this.policyPort, + pfx: options.pfx || this.pfx, + key: options.key || this.key, + passphrase: options.passphrase || this.passphrase, + cert: options.cert || this.cert, + ca: options.ca || this.ca, + ciphers: options.ciphers || this.ciphers, + rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized, + perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate, + extraHeaders: options.extraHeaders || this.extraHeaders, + forceNode: options.forceNode || this.forceNode, + localAddress: options.localAddress || this.localAddress, + requestTimeout: options.requestTimeout || this.requestTimeout, + protocols: options.protocols || void (0), + isReactNative: this.isReactNative + }); + + return transport; +}; + +function clone (obj) { + var o = {}; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + o[i] = obj[i]; + } + } + return o; +} + +/** + * Initializes transport to use and starts probe. + * + * @api private + */ +Socket.prototype.open = function () { + var transport; + if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) { + transport = 'websocket'; + } else if (0 === this.transports.length) { + // Emit error on next tick so it can be listened to + var self = this; + setTimeout(function () { + self.emit('error', 'No transports available'); + }, 0); + return; + } else { + transport = this.transports[0]; + } + this.readyState = 'opening'; + + // Retry with the next transport if the transport is disabled (jsonp: false) + try { + transport = this.createTransport(transport); + } catch (e) { + this.transports.shift(); + this.open(); + return; + } + + transport.open(); + this.setTransport(transport); +}; + +/** + * Sets the current transport. Disables the existing one (if any). + * + * @api private + */ + +Socket.prototype.setTransport = function (transport) { + debug('setting transport %s', transport.name); + var self = this; + + if (this.transport) { + debug('clearing existing transport %s', this.transport.name); + this.transport.removeAllListeners(); + } + + // set up transport + this.transport = transport; + + // set up transport listeners + transport + .on('drain', function () { + self.onDrain(); + }) + .on('packet', function (packet) { + self.onPacket(packet); + }) + .on('error', function (e) { + self.onError(e); + }) + .on('close', function () { + self.onClose('transport close'); + }); +}; + +/** + * Probes a transport. + * + * @param {String} transport name + * @api private + */ + +Socket.prototype.probe = function (name) { + debug('probing transport "%s"', name); + var transport = this.createTransport(name, { probe: 1 }); + var failed = false; + var self = this; + + Socket.priorWebsocketSuccess = false; + + function onTransportOpen () { + if (self.onlyBinaryUpgrades) { + var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; + failed = failed || upgradeLosesBinary; + } + if (failed) return; + + debug('probe transport "%s" opened', name); + transport.send([{ type: 'ping', data: 'probe' }]); + transport.once('packet', function (msg) { + if (failed) return; + if ('pong' === msg.type && 'probe' === msg.data) { + debug('probe transport "%s" pong', name); + self.upgrading = true; + self.emit('upgrading', transport); + if (!transport) return; + Socket.priorWebsocketSuccess = 'websocket' === transport.name; + + debug('pausing current transport "%s"', self.transport.name); + self.transport.pause(function () { + if (failed) return; + if ('closed' === self.readyState) return; + debug('changing transport and sending upgrade packet'); + + cleanup(); + + self.setTransport(transport); + transport.send([{ type: 'upgrade' }]); + self.emit('upgrade', transport); + transport = null; + self.upgrading = false; + self.flush(); + }); + } else { + debug('probe transport "%s" failed', name); + var err = new Error('probe error'); + err.transport = transport.name; + self.emit('upgradeError', err); + } + }); + } + + function freezeTransport () { + if (failed) return; + + // Any callback called by transport should be ignored since now + failed = true; + + cleanup(); + + transport.close(); + transport = null; + } + + // Handle any error that happens while probing + function onerror (err) { + var error = new Error('probe error: ' + err); + error.transport = transport.name; + + freezeTransport(); + + debug('probe transport "%s" failed because of error: %s', name, err); + + self.emit('upgradeError', error); + } + + function onTransportClose () { + onerror('transport closed'); + } + + // When the socket is closed while we're probing + function onclose () { + onerror('socket closed'); + } + + // When the socket is upgraded while we're probing + function onupgrade (to) { + if (transport && to.name !== transport.name) { + debug('"%s" works - aborting "%s"', to.name, transport.name); + freezeTransport(); + } + } + + // Remove all listeners on the transport and on self + function cleanup () { + transport.removeListener('open', onTransportOpen); + transport.removeListener('error', onerror); + transport.removeListener('close', onTransportClose); + self.removeListener('close', onclose); + self.removeListener('upgrading', onupgrade); + } + + transport.once('open', onTransportOpen); + transport.once('error', onerror); + transport.once('close', onTransportClose); + + this.once('close', onclose); + this.once('upgrading', onupgrade); + + transport.open(); +}; + +/** + * Called when connection is deemed open. + * + * @api public + */ + +Socket.prototype.onOpen = function () { + debug('socket open'); + this.readyState = 'open'; + Socket.priorWebsocketSuccess = 'websocket' === this.transport.name; + this.emit('open'); + this.flush(); + + // we check for `readyState` in case an `open` + // listener already closed the socket + if ('open' === this.readyState && this.upgrade && this.transport.pause) { + debug('starting upgrade probes'); + for (var i = 0, l = this.upgrades.length; i < l; i++) { + this.probe(this.upgrades[i]); + } + } +}; + +/** + * Handles a packet. + * + * @api private + */ + +Socket.prototype.onPacket = function (packet) { + if ('opening' === this.readyState || 'open' === this.readyState || + 'closing' === this.readyState) { + debug('socket receive: type "%s", data "%s"', packet.type, packet.data); + + this.emit('packet', packet); + + // Socket is live - any packet counts + this.emit('heartbeat'); + + switch (packet.type) { + case 'open': + this.onHandshake(JSON.parse(packet.data)); + break; + + case 'pong': + this.setPing(); + this.emit('pong'); + break; + + case 'error': + var err = new Error('server error'); + err.code = packet.data; + this.onError(err); + break; + + case 'message': + this.emit('data', packet.data); + this.emit('message', packet.data); + break; + } + } else { + debug('packet received with socket readyState "%s"', this.readyState); + } +}; + +/** + * Called upon handshake completion. + * + * @param {Object} handshake obj + * @api private + */ + +Socket.prototype.onHandshake = function (data) { + this.emit('handshake', data); + this.id = data.sid; + this.transport.query.sid = data.sid; + this.upgrades = this.filterUpgrades(data.upgrades); + this.pingInterval = data.pingInterval; + this.pingTimeout = data.pingTimeout; + this.onOpen(); + // In case open handler closes socket + if ('closed' === this.readyState) return; + this.setPing(); + + // Prolong liveness of socket on heartbeat + this.removeListener('heartbeat', this.onHeartbeat); + this.on('heartbeat', this.onHeartbeat); +}; + +/** + * Resets ping timeout. + * + * @api private + */ + +Socket.prototype.onHeartbeat = function (timeout) { + clearTimeout(this.pingTimeoutTimer); + var self = this; + self.pingTimeoutTimer = setTimeout(function () { + if ('closed' === self.readyState) return; + self.onClose('ping timeout'); + }, timeout || (self.pingInterval + self.pingTimeout)); +}; + +/** + * Pings server every `this.pingInterval` and expects response + * within `this.pingTimeout` or closes connection. + * + * @api private + */ + +Socket.prototype.setPing = function () { + var self = this; + clearTimeout(self.pingIntervalTimer); + self.pingIntervalTimer = setTimeout(function () { + debug('writing ping packet - expecting pong within %sms', self.pingTimeout); + self.ping(); + self.onHeartbeat(self.pingTimeout); + }, self.pingInterval); +}; + +/** +* Sends a ping packet. +* +* @api private +*/ + +Socket.prototype.ping = function () { + var self = this; + this.sendPacket('ping', function () { + self.emit('ping'); + }); +}; + +/** + * Called on `drain` event + * + * @api private + */ + +Socket.prototype.onDrain = function () { + this.writeBuffer.splice(0, this.prevBufferLen); + + // setting prevBufferLen = 0 is very important + // for example, when upgrading, upgrade packet is sent over, + // and a nonzero prevBufferLen could cause problems on `drain` + this.prevBufferLen = 0; + + if (0 === this.writeBuffer.length) { + this.emit('drain'); + } else { + this.flush(); + } +}; + +/** + * Flush write buffers. + * + * @api private + */ + +Socket.prototype.flush = function () { + if ('closed' !== this.readyState && this.transport.writable && + !this.upgrading && this.writeBuffer.length) { + debug('flushing %d packets in socket', this.writeBuffer.length); + this.transport.send(this.writeBuffer); + // keep track of current length of writeBuffer + // splice writeBuffer and callbackBuffer on `drain` + this.prevBufferLen = this.writeBuffer.length; + this.emit('flush'); + } +}; + +/** + * Sends a message. + * + * @param {String} message. + * @param {Function} callback function. + * @param {Object} options. + * @return {Socket} for chaining. + * @api public + */ + +Socket.prototype.write = +Socket.prototype.send = function (msg, options, fn) { + this.sendPacket('message', msg, options, fn); + return this; +}; + +/** + * Sends a packet. + * + * @param {String} packet type. + * @param {String} data. + * @param {Object} options. + * @param {Function} callback function. + * @api private + */ + +Socket.prototype.sendPacket = function (type, data, options, fn) { + if ('function' === typeof data) { + fn = data; + data = undefined; + } + + if ('function' === typeof options) { + fn = options; + options = null; + } + + if ('closing' === this.readyState || 'closed' === this.readyState) { + return; + } + + options = options || {}; + options.compress = false !== options.compress; + + var packet = { + type: type, + data: data, + options: options + }; + this.emit('packetCreate', packet); + this.writeBuffer.push(packet); + if (fn) this.once('flush', fn); + this.flush(); +}; + +/** + * Closes the connection. + * + * @api private + */ + +Socket.prototype.close = function () { + if ('opening' === this.readyState || 'open' === this.readyState) { + this.readyState = 'closing'; + + var self = this; + + if (this.writeBuffer.length) { + this.once('drain', function () { + if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + }); + } else if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + } + + function close () { + self.onClose('forced close'); + debug('socket closing - telling transport to close'); + self.transport.close(); + } + + function cleanupAndClose () { + self.removeListener('upgrade', cleanupAndClose); + self.removeListener('upgradeError', cleanupAndClose); + close(); + } + + function waitForUpgrade () { + // wait for upgrade to finish since we can't send packets while pausing a transport + self.once('upgrade', cleanupAndClose); + self.once('upgradeError', cleanupAndClose); + } + + return this; +}; + +/** + * Called upon transport error + * + * @api private + */ + +Socket.prototype.onError = function (err) { + debug('socket error %j', err); + Socket.priorWebsocketSuccess = false; + this.emit('error', err); + this.onClose('transport error', err); +}; + +/** + * Called upon transport close. + * + * @api private + */ + +Socket.prototype.onClose = function (reason, desc) { + if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { + debug('socket close with reason: "%s"', reason); + var self = this; + + // clear timers + clearTimeout(this.pingIntervalTimer); + clearTimeout(this.pingTimeoutTimer); + + // stop event from firing again for transport + this.transport.removeAllListeners('close'); + + // ensure transport won't stay open + this.transport.close(); + + // ignore further transport communication + this.transport.removeAllListeners(); + + // set ready state + this.readyState = 'closed'; + + // clear session id + this.id = null; + + // emit close event + this.emit('close', reason, desc); + + // clean buffers after, so users can still + // grab the buffers on `close` event + self.writeBuffer = []; + self.prevBufferLen = 0; + } +}; + +/** + * Filters upgrades, returning only those matching client transports. + * + * @param {Array} server upgrades + * @api private + * + */ + +Socket.prototype.filterUpgrades = function (upgrades) { + var filteredUpgrades = []; + for (var i = 0, j = upgrades.length; i < j; i++) { + if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); + } + return filteredUpgrades; +}; + +},{"./transport":173,"./transports/index":174,"component-emitter":180,"debug":181,"engine.io-parser":184,"indexof":223,"parseqs":242,"parseuri":243}],173:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var parser = require('engine.io-parser'); +var Emitter = require('component-emitter'); + +/** + * Module exports. + */ + +module.exports = Transport; + +/** + * Transport abstract constructor. + * + * @param {Object} options. + * @api private + */ + +function Transport (opts) { + this.path = opts.path; + this.hostname = opts.hostname; + this.port = opts.port; + this.secure = opts.secure; + this.query = opts.query; + this.timestampParam = opts.timestampParam; + this.timestampRequests = opts.timestampRequests; + this.readyState = ''; + this.agent = opts.agent || false; + this.socket = opts.socket; + this.enablesXDR = opts.enablesXDR; + this.withCredentials = opts.withCredentials; + + // SSL options for Node.js client + this.pfx = opts.pfx; + this.key = opts.key; + this.passphrase = opts.passphrase; + this.cert = opts.cert; + this.ca = opts.ca; + this.ciphers = opts.ciphers; + this.rejectUnauthorized = opts.rejectUnauthorized; + this.forceNode = opts.forceNode; + + // results of ReactNative environment detection + this.isReactNative = opts.isReactNative; + + // other options for Node.js client + this.extraHeaders = opts.extraHeaders; + this.localAddress = opts.localAddress; +} + +/** + * Mix in `Emitter`. + */ + +Emitter(Transport.prototype); + +/** + * Emits an error. + * + * @param {String} str + * @return {Transport} for chaining + * @api public + */ + +Transport.prototype.onError = function (msg, desc) { + var err = new Error(msg); + err.type = 'TransportError'; + err.description = desc; + this.emit('error', err); + return this; +}; + +/** + * Opens the transport. + * + * @api public + */ + +Transport.prototype.open = function () { + if ('closed' === this.readyState || '' === this.readyState) { + this.readyState = 'opening'; + this.doOpen(); + } + + return this; +}; + +/** + * Closes the transport. + * + * @api private + */ + +Transport.prototype.close = function () { + if ('opening' === this.readyState || 'open' === this.readyState) { + this.doClose(); + this.onClose(); + } + + return this; +}; + +/** + * Sends multiple packets. + * + * @param {Array} packets + * @api private + */ + +Transport.prototype.send = function (packets) { + if ('open' === this.readyState) { + this.write(packets); + } else { + throw new Error('Transport not open'); + } +}; + +/** + * Called upon open + * + * @api private + */ + +Transport.prototype.onOpen = function () { + this.readyState = 'open'; + this.writable = true; + this.emit('open'); +}; + +/** + * Called with data. + * + * @param {String} data + * @api private + */ + +Transport.prototype.onData = function (data) { + var packet = parser.decodePacket(data, this.socket.binaryType); + this.onPacket(packet); +}; + +/** + * Called with a decoded packet. + */ + +Transport.prototype.onPacket = function (packet) { + this.emit('packet', packet); +}; + +/** + * Called upon close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + this.readyState = 'closed'; + this.emit('close'); +}; + +},{"component-emitter":180,"engine.io-parser":184}],174:[function(require,module,exports){ +/** + * Module dependencies + */ + +var XMLHttpRequest = require('xmlhttprequest-ssl'); +var XHR = require('./polling-xhr'); +var JSONP = require('./polling-jsonp'); +var websocket = require('./websocket'); + +/** + * Export transports. + */ + +exports.polling = polling; +exports.websocket = websocket; + +/** + * Polling transport polymorphic constructor. + * Decides on xhr vs jsonp based on feature detection. + * + * @api private + */ + +function polling (opts) { + var xhr; + var xd = false; + var xs = false; + var jsonp = false !== opts.jsonp; + + if (typeof location !== 'undefined') { + var isSSL = 'https:' === location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (!port) { + port = isSSL ? 443 : 80; + } + + xd = opts.hostname !== location.hostname || port !== opts.port; + xs = opts.secure !== isSSL; + } + + opts.xdomain = xd; + opts.xscheme = xs; + xhr = new XMLHttpRequest(opts); + + if ('open' in xhr && !opts.forceJSONP) { + return new XHR(opts); + } else { + if (!jsonp) throw new Error('JSONP disabled'); + return new JSONP(opts); + } +} + +},{"./polling-jsonp":175,"./polling-xhr":176,"./websocket":178,"xmlhttprequest-ssl":179}],175:[function(require,module,exports){ +/** + * Module requirements. + */ + +var Polling = require('./polling'); +var inherit = require('component-inherit'); +var globalThis = require('../globalThis'); + +/** + * Module exports. + */ + +module.exports = JSONPPolling; + +/** + * Cached regular expressions. + */ + +var rNewline = /\n/g; +var rEscapedNewline = /\\n/g; + +/** + * Global JSONP callbacks. + */ + +var callbacks; + +/** + * Noop. + */ + +function empty () { } + +/** + * JSONP Polling constructor. + * + * @param {Object} opts. + * @api public + */ + +function JSONPPolling (opts) { + Polling.call(this, opts); + + this.query = this.query || {}; + + // define global callbacks array if not present + // we do this here (lazily) to avoid unneeded global pollution + if (!callbacks) { + // we need to consider multiple engines in the same page + callbacks = globalThis.___eio = (globalThis.___eio || []); + } + + // callback identifier + this.index = callbacks.length; + + // add callback to jsonp global + var self = this; + callbacks.push(function (msg) { + self.onData(msg); + }); + + // append to query string + this.query.j = this.index; + + // prevent spurious errors from being emitted when the window is unloaded + if (typeof addEventListener === 'function') { + addEventListener('beforeunload', function () { + if (self.script) self.script.onerror = empty; + }, false); + } +} + +/** + * Inherits from Polling. + */ + +inherit(JSONPPolling, Polling); + +/* + * JSONP only supports binary as base64 encoded strings + */ + +JSONPPolling.prototype.supportsBinary = false; + +/** + * Closes the socket. + * + * @api private + */ + +JSONPPolling.prototype.doClose = function () { + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + if (this.form) { + this.form.parentNode.removeChild(this.form); + this.form = null; + this.iframe = null; + } + + Polling.prototype.doClose.call(this); +}; + +/** + * Starts a poll cycle. + * + * @api private + */ + +JSONPPolling.prototype.doPoll = function () { + var self = this; + var script = document.createElement('script'); + + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + script.async = true; + script.src = this.uri(); + script.onerror = function (e) { + self.onError('jsonp poll error', e); + }; + + var insertAt = document.getElementsByTagName('script')[0]; + if (insertAt) { + insertAt.parentNode.insertBefore(script, insertAt); + } else { + (document.head || document.body).appendChild(script); + } + this.script = script; + + var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent); + + if (isUAgecko) { + setTimeout(function () { + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + document.body.removeChild(iframe); + }, 100); + } +}; + +/** + * Writes with a hidden iframe. + * + * @param {String} data to send + * @param {Function} called upon flush. + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data, fn) { + var self = this; + + if (!this.form) { + var form = document.createElement('form'); + var area = document.createElement('textarea'); + var id = this.iframeId = 'eio_iframe_' + this.index; + var iframe; + + form.className = 'socketio'; + form.style.position = 'absolute'; + form.style.top = '-1000px'; + form.style.left = '-1000px'; + form.target = id; + form.method = 'POST'; + form.setAttribute('accept-charset', 'utf-8'); + area.name = 'd'; + form.appendChild(area); + document.body.appendChild(form); + + this.form = form; + this.area = area; + } + + this.form.action = this.uri(); + + function complete () { + initIframe(); + fn(); + } + + function initIframe () { + if (self.iframe) { + try { + self.form.removeChild(self.iframe); + } catch (e) { + self.onError('jsonp polling iframe removal error', e); + } + } + + try { + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) + var html = '