/// <summary> /// Implementation according to GRR. /// </summary> public virtual void RunReductionRandomization(Zp oldSecret) { // randomize the coeficients // generate a t degree polynomial, hi(x), // with a free coef that equals 'ab' and create share for users from it. var sharesValues = ShamirSharing.Share(oldSecret, NumParties, PolynomialDeg); var shareMsgs = new List <ShareMsg <Zp> >(); foreach (var shareValue in sharesValues) { shareMsgs.Add(new ShareMsg <Zp>(new Share <Zp>(shareValue), Stage.RandomizationReceive)); } // send to the j-th user hi(j) and receive from every other k player hk(i) Send(shareMsgs); OnReceive((int)Stage.RandomizationReceive, delegate(List <Msg> shares) { var vanderFirstRow = ZpMatrix.GetSymmetricVanderMondeMatrix(NumParties, Prime) .Transpose.Inverse.GetMatrixRow(0); // Calculate the value of the polynomial H(x) at i = H(i) as defined at GRR var tempSecret = new Zp(Prime, 0); for (int i = 0; i < NumParties; i++) { tempSecret.Add(((shares[i] as ShareMsg <Zp>).Share as Share <Zp>).Value.Mul(vanderFirstRow[i])); } }); }
/// <summary> /// Creates a random polynomial f(x,y) and then to create from it for /// the i-th player two polynomials : fi(x) = f(x,w^i) and gi(y) = f(w^i,y). /// </summary> public static IList <SecretPolynomials> ShareByzantineCase(Zp secret, int numPlayers, int polynomDeg) { if (numPlayers <= 4 * polynomDeg) { throw new System.ArgumentException("Cannot use Byzantine algoritm -- numberOfPlayers <= 4*polynomDeg - " + "use regular computation instead"); } // Creating the Random Polynomial - f(x , y) // Note : there are (t+1)^2 coefficiet for the polynomial including the free coefficient (the secret) // first row coef are of (x^0,x^1,x^2,...,x^t)y^0, second row coef are (x^0, x1,...,x^t)y^1 and so forth... var randomMatrix_f_xy = ZpMatrix.GetRandomMatrix(polynomDeg + 1, polynomDeg + 1, secret.Prime); randomMatrix_f_xy.SetMatrixCell(0, 0, secret); var polynomialShares = new List <SecretPolynomials>(); for (int i = 0; i < numPlayers; i++) { var pSecret = new SecretPolynomials(); pSecret.Fi_xPolynomial = GenerateF_i_xPolynomial(randomMatrix_f_xy, secret, i); pSecret.Gi_yPolynomial = GenerateG_i_yPolynomial(randomMatrix_f_xy, secret, i); polynomialShares.Add(pSecret); } return(polynomialShares); }
private static IList<Zp> GenerateF_i_xPolynomial(ZpMatrix f_x_y, Zp secret, int playerNum) { int w = NumTheoryUtils.GetFieldMinimumPrimitive(secret.Prime); int w_i = NumTheoryUtils.ModPow(w, playerNum, secret.Prime); var y_values = new int[f_x_y.ColCount]; for (int i = 0; i < f_x_y.ColCount; i++) { y_values[i] = NumTheoryUtils.ModPow(w_i, i, secret.Prime); } return f_x_y.MulMatrixByScalarsVector(y_values).SumMatrixRows(); }
// TODO: MAHDI: HAS WRONG ORDERING! private IList <Zp> GetMultStepCoeffsForCheaters(int j) { var rowsToRemove = new bool[NumParties]; for (int i = 0; i < NumParties; i++) { rowsToRemove[i] = BadPlayers.Contains(i); } var vanderMonde = ZpMatrix.GetSymmetricPrimitiveVandermondeMatrix(NumParties, Prime).Transpose; var filteredMatrix = vanderMonde.RemoveRowsFromMatrix(rowsToRemove).Inverse; return(filteredMatrix.GetMatrixRow(j)); }
private static IList <Zp> GenerateF_i_xPolynomial(ZpMatrix f_x_y, Zp secret, int playerNum) { int w = NumTheoryUtils.GetFieldMinimumPrimitive(secret.Prime); int w_i = NumTheoryUtils.ModPow(w, playerNum, secret.Prime); var y_values = new int[f_x_y.ColCount]; for (int i = 0; i < f_x_y.ColCount; i++) { y_values[i] = NumTheoryUtils.ModPow(w_i, i, secret.Prime); } return(f_x_y.MulMatrixByScalarsVector(y_values).SumMatrixRows()); }
private static IList<Zp> GenerateG_i_yPolynomial(ZpMatrix f_x_y, Zp secret, int playerNum) { int w = NumTheoryUtils.GetFieldMinimumPrimitive(secret.Prime); int w_i = NumTheoryUtils.ModPow(w, playerNum, secret.Prime); var x_values = new Zp[f_x_y.RowCount]; for (int i = 0; i < f_x_y.RowCount; i++) { x_values[i] = new Zp(secret.Prime, NumTheoryUtils.ModPow(w_i, i, secret.Prime)); } var tempArr = f_x_y.Times(new ZpMatrix(x_values, VectorType.Column)).ZpVector; return tempArr; }
private static ZpMatrix getWelchBerlekampMatrix(IList <Zp> XVlaues, IList <Zp> YVlaues, int n, int e, int prime) { var NVanderMonde = ZpMatrix.GetVandermondeMatrix(n - e, XVlaues, prime).Transpose; var EVanderMonde = ZpMatrix.GetVandermondeMatrix(e, XVlaues, prime).Transpose; int[] scalarVector = new int[YVlaues.Count]; int i = 0; foreach (Zp zp in YVlaues) { scalarVector[i++] = -zp.Value; } EVanderMonde = EVanderMonde.MulMatrixByScalarsVector(scalarVector); return(ZpMatrix.GetConcatenationMatrix(NVanderMonde, EVanderMonde)); }
private static IList <Zp> GenerateG_i_yPolynomial(ZpMatrix f_x_y, Zp secret, int playerNum) { int w = NumTheoryUtils.GetFieldMinimumPrimitive(secret.Prime); int w_i = NumTheoryUtils.ModPow(w, playerNum, secret.Prime); var x_values = new Zp[f_x_y.RowCount]; for (int i = 0; i < f_x_y.RowCount; i++) { x_values[i] = new Zp(secret.Prime, NumTheoryUtils.ModPow(w_i, i, secret.Prime)); } var tempArr = f_x_y.Times(new ZpMatrix(x_values, VectorType.Column)).ZpVector; return(tempArr); }
/// <summary> /// Evaluates the shares of secret with polynomial of degree 'polynomDeg' and 'numPlayers' players. /// </summary> private static IList <Zp> Share(Zp secret, int numPlayers, int polynomDeg, bool usePrimitiveShare, out IList <Zp> coeffs) { #if NO_COMPUTATION // send some dummy shares var shares = new Zp[numPlayers]; for (int i = 0; i < numPlayers; i++) { shares[i] = new Zp(secret.Prime); } return(shares); #else Debug.Assert(numPlayers > polynomDeg, "Polynomial degree cannot be greater than or equal to the number of players!"); // Create a random polynomial - f(x) // Note: Polynomial of degree d has d+1 coefficients var randomMatrix = ZpMatrix.GetRandomMatrix(1, polynomDeg + 1, secret.Prime); // The free variable in the Random Polynomial (i.e. f(x)) is the secret randomMatrix.SetMatrixCell(0, 0, secret); // Polynomial coefficients coeffs = randomMatrix.GetMatrixRow(0); // Create vanderMonde matrix ZpMatrix vanderMonde; if (usePrimitiveShare) { vanderMonde = ZpMatrix.GetPrimitiveVandermondeMatrix(polynomDeg + 1, numPlayers, secret.Prime); } else { vanderMonde = ZpMatrix.GetVandermondeMatrix(polynomDeg + 1, numPlayers, secret.Prime); } // Compute f(i) for the i-th player var sharesArr = randomMatrix.Times(vanderMonde).ZpVector; Debug.Assert(sharesArr != null); Debug.Assert(sharesArr.Length == numPlayers); return(sharesArr); #endif }
private void SendVerifications(IEnumerable <ShareMsg <Zp> > recvShares) { // input stage checking - check that each input is legal // each iteration in the loop is a verification of player with ID 'playerToVerify'. foreach (var recvShare in recvShares) { var playerToVerify = recvShare.SenderId; var secretPoly = recvShare.Share as SecretPolynomials; // first check if the verified dealer had already been caught as a cheater if (BadPlayers.Contains(playerToVerify)) { // no need to check a cheater player's input sharesForComp.Add(new Zp(Prime, 0)); continue; } /* Step 1 - Verify player 'playerToVerify' input */ // Extract the received share from the polynomial you received from player with ID 'playerToVerify' // Assume I'm the j-th player. Calculate fj(w^i). // first check if you received a proper polynomial. var isOrigPolyLegal = IsSecretPolynomialsLegal((SecretPolynomials)secretPoly); if (isOrigPolyLegal) { var verifList_f_j_w_i = secretPoly.CalculateF_i_xValuesForPlayers(NumParties, Prime); var verifMsgs = GetVerifShareMessages(verifList_f_j_w_i, playerToVerify, true); Send(verifMsgs); } else // received polynomials are corrupted Send random list and remember to complain { // received a corrupted polynomials from player with ID 'playerToVerify' var verifList_f_j_w_i = ZpMatrix.GetRandomMatrix(1, NumParties, Prime).GetMatrixRow(0); var verifMsgs = GetVerifShareMessages(verifList_f_j_w_i, playerToVerify, false); Send(verifMsgs); } } }
static void Main(string[] args) { Console.WriteLine("Started."); StaticRandom.Init(seed); int quorumSize = 20; int degree = quorumSize / 3; var secret = new Zp(Prime, 3); var shareMatrix = ZpMatrix.GetIdentityMatrix(quorumSize, Prime); // create the initial shares var initalShares = ShamirSharing.Share(secret, quorumSize, degree); for (var i = 0; i < quorumSize; i++) { IList <Zp> reshares = QuorumSharing.CreateReshares(initalShares[i], quorumSize, degree); for (var j = 0; j < quorumSize; j++) { shareMatrix.SetMatrixCell(j, i, reshares[j]); } } // combine the reshares List <Zp> finalShares = new List <Zp>(); for (var i = 0; i < quorumSize; i++) { Zp finalShare = QuorumSharing.CombineReshares(shareMatrix.GetMatrixRow(i), quorumSize, Prime); finalShares.Add(finalShare); } // combine the shares Zp final = ShamirSharing.Recombine(finalShares, degree, Prime); Console.WriteLine(final.Value); Console.WriteLine("Press any key to continue..."); Console.ReadKey(); }
/// <summary> /// Each party in the new quorum needs to call this with the shares received from the old quorum to calculate its share /// </summary> public static Zp CombineReshares(IList <Zp> reshares, int newQuorumSize, int prime) { int oldQuorumSize = reshares.Count; if (oldQuorumSize != newQuorumSize) { throw new System.ArgumentException("Do not support case where quorums are of different sizes"); } // Compute the first row of the inverse Vandermonde matrix var vandermonde = ZpMatrix.GetVandermondeMatrix(oldQuorumSize, newQuorumSize, prime); var vandermondeInv = vandermonde.Inverse.GetMatrixColumn(0); var S = new Zp(prime); for (var i = 0; i < newQuorumSize; i++) { S += vandermondeInv[i] * reshares[i]; } return(S); }
/// <summary> /// Evaluates the shared secrets of secret with polynom of degree t and numberOfPlayers players. /// </summary> public static ShareDetails DetailedShare(Zp secret, int numPlayers, int polynomDeg) { if (numPlayers <= polynomDeg) { throw new ArgumentException("Polynomial degree cannot be bigger or equal to the number of players"); } // Creating the Random Polynomial - f(x) var randomMatrix = ZpMatrix.GetRandomMatrix(1, polynomDeg + 1, secret.Prime); // The free variable in the Random Polynomial( f(x) ) is the seceret randomMatrix.SetMatrixCell(0, 0, secret); // Create vanderMonde matrix var vanderMonde = ZpMatrix.GetPrimitiveVandermondeMatrix(polynomDeg + 1, numPlayers, secret.Prime); // Compute f(i) for the i-th player var sharesArr = randomMatrix.Times(vanderMonde).ZpVector; var details = new ShareDetails(randomMatrix.GetMatrixRow(0), sharesArr); return(details); }
/* * Finds a solution to a system of linear equations represtented by an * n-by-n+1 matrix A: namely, denoting by B the left n-by-n submatrix of A * and by C the last column of A, finds a column vector x such that Bx=C. * If more than one solution exists, chooses one arbitrarily by setting some * values to 0. If no solutions exists, returns false. Otherwise, places * a solution into the first argument and returns true. * * Note : matrix A changes (gets converted to row echelon form). */ private static Zp[] linearSolve(ZpMatrix A, ZpMatrix B, int prime) { var invArray = NumTheoryUtils.GetFieldInverse(prime); var C = ZpMatrix.GetConcatenationMatrix(A, B); // augmented matrix int n = C.RowCount; int[] solution = new int[n]; int temp; int firstDeterminedValue = n; // we will be determining values of the solution // from n-1 down to 0. At any given time, // values from firstDeterminedValue to n-1 have been // found. Initializing to n means // no values have been found yet. // To put it another way, the variabe firstDeterminedValue // stores the position of first nonzero entry in the row just examined // (except at initialization) int rank = C.Gauss(); int[][] cContent = C.Data; // can start at rank-1, because below that are all zeroes for (int row = rank - 1; row >= 0; row--) { // remove all the known variables from the equation temp = cContent[row][n]; int col; for (col = n - 1; col >= firstDeterminedValue; col--) { temp = Zp.Modulo(temp - (cContent[row][col] * solution[col]), prime); } // now we need to find the first nonzero coefficient in this row // if it exists before firstDeterminedValue // because the matrix is in row echelon form, the first nonzero // coefficient cannot be before the diagonal for (col = row; col < firstDeterminedValue; col++) { if (cContent[row][col] != 0) { break; } } if (col < firstDeterminedValue) // this means we found a nonzero coefficient { // we can determine the variables in position from col to firstDeterminedValue // if this loop executes even once, then the system is undertermined // we arbitrarily set the undetermined variables to 0, because it make math easier for (int j = col + 1; j < firstDeterminedValue; j++) { solution[j] = 0; } // Now determine the variable at the nonzero coefficient //div(solution[col], temp, A.getContent()[row][col]); solution[col] = temp * invArray[Zp.Modulo(cContent[row][col], prime)]; firstDeterminedValue = col; } else { // this means there are no nonzero coefficients before firstDeterminedValue. // Because we skip all the zero rows at the bottom, the matrix is in // row echelon form, and firstDeterminedValue is equal to the // position of first nonzero entry in row+1 (unless it is equal to n), // this means we are at a row with all zeroes except in column n // The system has no solution. return(null); } } // set the remaining undetermined values, if any, to 0 for (int col = 0; col < firstDeterminedValue; col++) { solution[col] = 0; } var ResultVec = new Zp[n]; for (int i = 0; i < n; i++) { ResultVec[i] = new Zp(prime, solution[i]); } return(ResultVec); }
/* * Finds a solution to a system of linear equations represtented by an * n-by-n+1 matrix A: namely, denoting by B the left n-by-n submatrix of A * and by C the last column of A, finds a column vector x such that Bx=C. * If more than one solution exists, chooses one arbitrarily by setting some * values to 0. If no solutions exists, returns false. Otherwise, places * a solution into the first argument and returns true. * * Note : matrix A changes (gets converted to row echelon form). */ private static Zp[] linearSolve(ZpMatrix A, ZpMatrix B, int prime) { var invArray = NumTheoryUtils.GetFieldInverse(prime); var C = ZpMatrix.GetConcatenationMatrix(A, B); // augmented matrix int n = C.RowCount; int[] solution = new int[n]; int temp; int firstDeterminedValue = n; // we will be determining values of the solution // from n-1 down to 0. At any given time, // values from firstDeterminedValue to n-1 have been // found. Initializing to n means // no values have been found yet. // To put it another way, the variabe firstDeterminedValue // stores the position of first nonzero entry in the row just examined // (except at initialization) int rank = C.Gauss(); int[][] cContent = C.Data; // can start at rank-1, because below that are all zeroes for (int row = rank - 1; row >= 0; row--) { // remove all the known variables from the equation temp = cContent[row][n]; int col; for (col = n - 1; col >= firstDeterminedValue; col--) temp = Zp.Modulo(temp - (cContent[row][col] * solution[col]), prime); // now we need to find the first nonzero coefficient in this row // if it exists before firstDeterminedValue // because the matrix is in row echelon form, the first nonzero // coefficient cannot be before the diagonal for (col = row; col < firstDeterminedValue; col++) { if (cContent[row][col] != 0) break; } if (col < firstDeterminedValue) // this means we found a nonzero coefficient { // we can determine the variables in position from col to firstDeterminedValue // if this loop executes even once, then the system is undertermined // we arbitrarily set the undetermined variables to 0, because it make math easier for (int j = col + 1; j < firstDeterminedValue; j++) solution[j] = 0; // Now determine the variable at the nonzero coefficient //div(solution[col], temp, A.getContent()[row][col]); solution[col] = temp * invArray[Zp.Modulo(cContent[row][col], prime)]; firstDeterminedValue = col; } else { // this means there are no nonzero coefficients before firstDeterminedValue. // Because we skip all the zero rows at the bottom, the matrix is in // row echelon form, and firstDeterminedValue is equal to the // position of first nonzero entry in row+1 (unless it is equal to n), // this means we are at a row with all zeroes except in column n // The system has no solution. return null; } } // set the remaining undetermined values, if any, to 0 for (int col = 0; col < firstDeterminedValue; col++) solution[col] = 0; var ResultVec = new Zp[n]; for (int i = 0; i < n; i++) ResultVec[i] = new Zp(prime, solution[i]); return ResultVec; }