Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

review changes for parties receiving multiple shares #169

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 79 additions & 49 deletions lib/jiff-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
* if the party that calls this function is not a receiver then the map
* will be empty.
*/
function jiff_share(jiff, secret, threshold, receivers_list, senders_list, Zp, share_id) {
function jiff_share(jiff, secret, threshold, receivers_list, senders_list, Zp, share_id, receivers_ratios) {
var i, p_id;

// defaults
Expand Down Expand Up @@ -214,6 +214,12 @@
if (threshold > receivers_list.length) {
threshold = receivers_list.length;
}
if (receivers_ratios == null) {
receivers_ratios = {};
for (var i = 1; i <= jiff.party_count; i++){
receivers_ratios[i] = 2;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please what is the rational for setting to 2.

}
}

// if party is uninvolved in the share, do nothing
if (receivers_list.indexOf(jiff.id) === -1 && senders_list.indexOf(jiff.id) === -1) {
Expand All @@ -233,7 +239,7 @@
secret = jiff.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);
var shares = jiff.hooks.computeShares(jiff, secret, receivers_list, threshold, Zp, receivers_ratios);

// Call hook
shares = jiff.execute_array_hooks('afterComputeShare', [jiff, shares, threshold, receivers_list, senders_list, Zp], 1);
Expand All @@ -246,10 +252,13 @@
}

// 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 };
var p_ratio = (p_id in receivers_ratios) ? receivers_ratios[p_id] : 1;
var msg = {party_id: p_id, share: shares[p_id].slice(), op_id: share_id};
msg = jiff.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);
for (var j = 0; j < p_ratio; j++) {
msg['share'][j] = jiff.hooks.encryptSign(jiff, msg['share'][j].toString(10), jiff.keymap[msg['party_id']], jiff.secret_key);
}
jiff.socket.safe_emit('share', JSON.stringify(msg));
}
}
Expand Down Expand Up @@ -285,11 +294,10 @@
});
})(promise, p_id);

// receive share_i[id] from party p_id
//receive share_i[id] from party p_id
result[p_id] = jiff.secret_share(jiff, false, promise, undefined, receivers_list, threshold, Zp, share_id + ':' + p_id);
}
}

return result;
}

Expand All @@ -308,7 +316,7 @@
* point from the polynomial.
*
*/
function jiff_compute_shares(jiff, secret, parties_list, threshold, Zp) {
function jiff_compute_shares(jiff, secret, parties_list, threshold, Zp, parties_ratios) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does parties_ratios differ from receivers_ratio?

var shares = {}; // Keeps the shares
var i;

Expand All @@ -330,16 +338,19 @@
// 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);
var p_ratio = p_id in parties_ratios ? parties_ratios[p_id] : 1;
shares[p_id] = [];
for (var share_num = 0; share_num < p_ratio; share_num++) {
shares[p_id][share_num] = polynomial[0];
var power = jiff.helpers.get_party_number(p_id, share_num);

for (var j = 1; j < polynomial.length; j++) {
var tmp = jiff.helpers.mod((polynomial[j] * power), Zp);
shares[p_id][share_num] = jiff.helpers.mod((shares[p_id][share_num] + tmp), Zp);
power = jiff.helpers.mod(power * jiff.helpers.get_party_number(p_id, share_num), Zp);
}
}
}

return shares;
}

Expand All @@ -352,7 +363,10 @@
*/
function receive_share(jiff, json_msg) {
// Decrypt share
json_msg['share'] = jiff.hooks.decryptSign(jiff, json_msg['share'], jiff.secret_key, jiff.keymap[json_msg['party_id']]);
var num_shares = json_msg['share'].length;
for (var i = 0; i < num_shares; i++) {
json_msg['share'][i] = jiff.hooks.decryptSign(jiff, json_msg['share'][i], jiff.secret_key, jiff.keymap[json_msg['party_id']]);
}
json_msg = jiff.execute_array_hooks('afterOperation', [jiff, 'share', json_msg], 2);

var sender_id = json_msg['party_id'];
Expand Down Expand Up @@ -452,6 +466,7 @@
// Party is a receiver
if (parties.indexOf(jiff.id) > -1) {
var shares = []; // this will store received shares
var numberofshares = 0;
var final_deferred = new Deferred(); // will be resolved when the final value is reconstructed
var final_promise = final_deferred.promise;
for (i = 0; i < share.holders.length; i++) {
Expand All @@ -473,9 +488,10 @@
promise.then(function (received_share) {
jiff.deferreds[op_ids[jiff.id]][p_id] = null;
shares.push(received_share);
numberofshares = numberofshares + received_share.value.length;

// Too few shares, nothing to do.
if (shares.length < share.threshold) {
if (numberofshares < share.threshold) {
return;
}

Expand All @@ -484,7 +500,6 @@
if (final_deferred != null) {
var recons_secret = jiff.hooks.reconstructShare(jiff, shares);
recons_secret = jiff.execute_array_hooks('afterReconstructShare', [jiff, recons_secret], 1);

final_deferred.resolve(recons_secret);
final_deferred = null;
}
Expand Down Expand Up @@ -518,15 +533,17 @@
for (var index = 0; index < parties.length; index++) {
var i = parties[index]; // Party id
if (i === jiff.id) {
receive_open(jiff, { party_id: i, share: share.value, op_id: op_ids[i], Zp: share.Zp });
receive_open(jiff, {party_id: i, share: share.value, op_id: op_ids[i], Zp: share.Zp});
continue;
}

// encrypt, sign and send
var msg = {party_id: i, share: share.value, op_id: op_ids[i], Zp: share.Zp};
var msg = {party_id: i, share: share.value.slice(), op_id: op_ids[i], Zp: share.Zp};
msg = jiff.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);
for (var j = 0; j < msg['share'].length; j++) {
msg['share'][j] = jiff.hooks.encryptSign(jiff, msg['share'][j].toString(), jiff.keymap[msg['party_id']], jiff.secret_key);
}
jiff.socket.safe_emit('open', JSON.stringify(msg));
}
}
Expand All @@ -540,7 +557,9 @@
function receive_open(jiff, json_msg) {
// Decrypt share
if (json_msg['party_id'] !== jiff.id) {
json_msg['share'] = jiff.hooks.decryptSign(jiff, json_msg['share'], jiff.secret_key, jiff.keymap[json_msg['party_id']]);
for (var i = 0; i < json_msg['share'].length; i++) {
json_msg['share'][i] = jiff.hooks.decryptSign(jiff, json_msg['share'][i], jiff.secret_key, jiff.keymap[json_msg['party_id']]);
}
json_msg = jiff.execute_array_hooks('afterOperation', [jiff, 'open', json_msg], 2);
}

Expand Down Expand Up @@ -576,29 +595,34 @@
function jiff_lagrange(jiff, shares) {
var lagrange_coeff = []; // will contain shares.length many elements.

// Compute the Langrange coefficients at 0.
// Compute the Lagrange 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);
for (var share_num = 0; share_num < shares[i].value.length; share_num++) {
var pi = jiff.helpers.get_party_number(shares[i].sender_id, share_num);
lagrange_coeff[pi] = 1;

for (var j = 0; j < shares.length; j++) {
for (var n = 0; n < shares[j].value.length; n++) {
var pj = jiff.helpers.get_party_number(shares[j].sender_id, n);
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);
for (share_num = 0; share_num < shares[p].value.length; share_num++) {
var party = jiff.helpers.get_party_number(shares[p].sender_id, share_num);
var tmp = jiff.helpers.mod((shares[p].value[share_num] * lagrange_coeff[party]), shares[p].Zp);
recons_secret = jiff.helpers.mod((recons_secret + tmp), shares[p].Zp);
}
}

return recons_secret;
}

Expand Down Expand Up @@ -1298,7 +1322,7 @@
* @param {jiff-instance} jiff - the jiff instance.
* @param {boolean} ready - whether the value of the share is ready or deferred.
* @param {promise} promise - a promise to the value of the share.
* @param {number} value - the value of the share (null if not ready).
* @param {Array} value - the value of the share (null if not ready).
* @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.
Expand Down Expand Up @@ -1377,7 +1401,7 @@
*/
self.promise = promise;
/**
* @member {number} value
* @member {Array} value
* @memberof SecretShare
* @instance
*/
Expand Down Expand Up @@ -1532,7 +1556,8 @@
* @instance
*/
self.refresh = function (op_id) {
return self.isadd(self.jiff.server_generate_and_share({number: 0}, self.holders, self.threshold, self.Zp, op_id)[0]);
return self
//return self.isadd(self.jiff.server_generate_and_share({number: 0}, self.holders, self.threshold, self.Zp, op_id)[0]);
};

/**
Expand Down Expand Up @@ -3374,7 +3399,9 @@
// parse content of share/open messages to be integers (instead of strings due to encryption/decryption)
jiff.hooks.afterOperation.unshift(function (jiff, label, msg) {
if (label === 'share' || label === 'open') {
msg['share'] = parseInt(msg['share'], 10);
for (var i = 0; i < msg['share'].length; i++) {
msg['share'][i] = parseInt(msg['share'][i], 10);
}
}
return msg;
});
Expand Down Expand Up @@ -3851,14 +3878,17 @@
* @param {number/string} party_id - the party id from which to compute the number.
* @return {number} the party number (> 0).
*/
jiff.helpers.get_party_number = function (party_id) {
jiff.helpers.get_party_number = function (party_id, share_num) {
if (share_num == null){
share_num = 0;
}
if (typeof(party_id) === 'number') {
return party_id;
return party_id + (share_num * (jiff.party_count+1));
}
if (party_id.startsWith('s')) {
return -1 * parseInt(party_id.substring(1), 10);
return parseInt(party_id.substring(1), 10) * (jiff.party_count+1); // n+1 reserved for server
}
return parseInt(party_id, 10);
return parseInt(party_id, 10) + (share_num * (jiff.party_count+1));
};

/**
Expand Down Expand Up @@ -3903,7 +3933,7 @@
* and the value is the share object that wraps
* the value sent from that party (the internal value maybe deferred).
*/
jiff.share = function (secret, threshold, receivers_list, senders_list, Zp, share_id) {
jiff.share = function (secret, threshold, receivers_list, senders_list, Zp, share_id, receivers_ratios) {
// 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)) {
Expand All @@ -3912,14 +3942,14 @@
if (secret != null && (secret >= (Zp == null ? jiff.Zp : Zp))) {
throw new Error('secret must fit inside Zp');
}
return jiff.internal_share(secret, threshold, receivers_list, senders_list, Zp, share_id);
return jiff.internal_share(secret, threshold, receivers_list, senders_list, Zp, share_id, receivers_ratios);
};

/**
* Same as jiff-instance.share, but used by internal JIFF primitives/protocols (bgw).
*/
jiff.internal_share = function (secret, threshold, receivers_list, senders_list, Zp, share_id) {
return jiff_share(jiff, secret, threshold, receivers_list, senders_list, Zp, share_id);
jiff.internal_share = function (secret, threshold, receivers_list, senders_list, Zp, share_id, receivers_ratios) {
return jiff_share(jiff, secret, threshold, receivers_list, senders_list, Zp, share_id, receivers_ratios);
};

/**
Expand Down Expand Up @@ -4728,7 +4758,7 @@

// Setup receiving matching shares
jiff.socket.on('share', function (msg, callback) {
callback(true); // send ack to server
callback(true); // send back to server

// parse message
var json_msg = JSON.parse(msg);
Expand Down