phi-function.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright 2018 Scytl Secure Electronic Voting SA
  3. *
  4. * All rights reserved
  5. *
  6. * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
  7. */
  8. /* jshint node:true */
  9. 'use strict';
  10. module.exports = PhiFunction;
  11. /**
  12. * @class PhiFunction
  13. * @classdesc Encapsulates the PHI function defined by Maurer's unified
  14. * framework for zero-knowledge proofs of knowledge. This object is
  15. * instantiated internally by the <code>prove</code> method of any
  16. * zero-knowledge proof of knowledge prover object or the
  17. * <code>verify</code> method of any zero-knowledge proof of
  18. * knowledge verifier object.
  19. * @private
  20. * @param {number}
  21. * numInputs The number of inputs of the PHI function.
  22. * @param {number}
  23. * numOutputs The number of outputs of the PHI function.
  24. * @param {number[][][]}
  25. * computationRules The computation rules of the PHI function.
  26. * @param {ZpGroupElement[]}
  27. * baseElements The base elements of the PHI function.
  28. */
  29. function PhiFunction(numInputs, numOutputs, computationRules, baseElements) {
  30. validateComputationRules(
  31. numInputs, numOutputs, computationRules, baseElements);
  32. this.numInputs = numInputs;
  33. this.numOutputs = numOutputs;
  34. Object.freeze(this.computationRules = computationRules);
  35. Object.freeze(this.baseElements = baseElements);
  36. function validateComputationRules(
  37. numSecrets, numOutputs, computationRules, baseElements) {
  38. // Validate that both of the values in each of the
  39. // pairs of rules have values in the correct ranges.
  40. var numBaseElements = baseElements.length;
  41. for (var i = 0; i < numOutputs; i++) {
  42. for (var j = 0; j < computationRules[i].length; j++) {
  43. // Validate the first value of the pair
  44. var pairValue1 = computationRules[i][j][0];
  45. if ((pairValue1 < 1) || (pairValue1 > numBaseElements)) {
  46. throw new Error(
  47. 'First value in index pair is invalid; It should be within the range [1, ' +
  48. numBaseElements + '], but it was ' + pairValue1);
  49. }
  50. // Validate the second value of the pair.
  51. var pairValue2 = computationRules[i][j][1];
  52. if ((pairValue2 < 1) || (pairValue2 > numSecrets)) {
  53. throw new Error(
  54. 'Second value in index pair is valid; It should be within the range [1, ' +
  55. numSecrets + '], but it was ' + pairValue2);
  56. }
  57. }
  58. }
  59. }
  60. }
  61. PhiFunction.prototype = {
  62. /**
  63. * Performs the PHI function calculation.
  64. *
  65. * @function calculate
  66. * @memberof PhiFunction
  67. * @param {Exponent[]}
  68. * exponents The exponents with which to exponentiate the base
  69. * elements.
  70. * @param {function}
  71. * [progressCallback] An optional callback function if a progress
  72. * meter is being used.
  73. * @returns {ZpGroupElement[]} The array of Zp group elements that comprise
  74. * the output of the PHI function calculation.
  75. */
  76. calculate: function(exponents, progressMeter) {
  77. var measureProgress = false;
  78. if (typeof progressMeter !== 'undefined') {
  79. progressMeter.reset();
  80. measureProgress = true;
  81. }
  82. var partialResult;
  83. var resultForThisListOfPairs;
  84. var result = [];
  85. var progress = 0;
  86. for (var i = 0; i < this.computationRules.length; i++) {
  87. var numPairsInList = this.computationRules[i].length;
  88. resultForThisListOfPairs =
  89. this.baseElements[this.computationRules[i][0][0] - 1].exponentiate(
  90. exponents[this.computationRules[i][0][1] - 1]);
  91. if (measureProgress) {
  92. progressMeter.update(++progress);
  93. }
  94. for (var j = 1; j < numPairsInList; j++) {
  95. var index1 = this.computationRules[i][j][0];
  96. index1 = index1 - 1;
  97. var index2 = this.computationRules[i][j][1];
  98. index2 = index2 - 1;
  99. partialResult =
  100. this.baseElements[index1].exponentiate(exponents[index2]);
  101. resultForThisListOfPairs =
  102. resultForThisListOfPairs.multiply(partialResult);
  103. if (measureProgress) {
  104. progressMeter.update(++progress);
  105. }
  106. }
  107. result.push(resultForThisListOfPairs);
  108. }
  109. return result;
  110. }
  111. };