client/arch/hooks.js

/**
 * The hooks for this instance.
 * Checkout the <a href="hooks.html">hooks documentation</a>
 * @see {@link 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;