github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/StadiumForWaterCarver/src/Functions.cpp (about)

     1  /*
     2   * Functions.cpp
     3   *
     4   *  Created on: 26.10.2010
     5   *      Author: stephaniebayer
     6   */
     7  
     8  #include <string.h>
     9  #include "Functions.h"
    10  #include "G_q.h"
    11  #include "Cipher_elg.h"
    12  #include "FakeZZ.h"
    13  #include "CurvePoint.h"
    14  #include "SchnorrProof.h"
    15  #include <mutex>
    16  #include <iomanip>
    17  #include <atomic>
    18  NTL_CLIENT
    19  
    20  #include <cmath>
    21  #include <vector>
    22  #include <iostream>
    23  #include <time.h>
    24  #include <fstream>
    25  #include <sstream>
    26  #include <random>
    27  #include <unistd.h>
    28  #include "sha256.h"
    29  
    30  using namespace std;
    31  
    32  extern G_q G;
    33  extern G_q H;
    34  
    35  //OpenMP config
    36  extern bool parallel;
    37  extern int num_threads;
    38  
    39  Functions::Functions() {}
    40  
    41  Functions::~Functions() {}
    42  
    43  //get parameters selected by Stephanie Bayer
    44  void Functions::get_config(vector<long> &num, int m_in, int n_in)
    45  {
    46  
    47  	//# This parameter determine which version of the program is executed.
    48  	//# 0 stands for no optimization inside of the code
    49  	//# 1 uses multi-exponentiation techniques
    50  	//# 2 uses multi-exponentiation techniques and FFT to find values E_i
    51  	//# 3 uses multi-exponentiation techniques, extra interaction and Toom-Cook 4 to find values E_i, in this case m =16 or 64
    52  	num[5] = 3;
    53  	//# Actual number of ciphertext used in the shuffle protocol
    54  	num[0] = m_in * n_in;
    55  	//# Dimension of the m x n matrix used in the protocol. First line corresponds to number of rows m,
    56  	//# second line corresponds to number of columns n
    57  	num[1] = m_in;
    58  	num[2] = n_in;
    59  
    60  	//# Window size for the sliding window multi-exponentiation technique; default value is 5 for q 160 bits else 6
    61  	num[4] = 6;
    62  	//# Window size of the multi-exponentiation technique by Lim and Lee; default value is 5
    63  	num[7] = 5;
    64  	//# Window size of the multi-exponentiation technique by Brickels et al.; default value is 7 (derek: 3-5 seem like good values in practice)
    65  	num[3] = 4;
    66  
    67  	//# Types of groups uses.
    68  	//#  0 the same modular group G is used for the commitments and the encryption
    69  	//# 1 the commitments are calculated in G subset Z_p_1 with order q and the encryption in H subset Z_p_2 with order q
    70  	num[6] = 0;
    71  }
    72  
    73  void Functions::read_config(const string &name, vector<long> &num, ZZ &genq)
    74  {
    75  	ifstream ist, ist1;
    76  	string line;
    77  	vector<string> lines;
    78  	long i;
    79  
    80  	ist.open(name.c_str());
    81  	if (!ist1)
    82  		cout << "Can't open " << name.c_str();
    83  
    84  	for (i = 1; i < 12; i++)
    85  	{
    86  		getline(ist, line);
    87  	}
    88  	getline(ist, line);
    89  	num[5] = tolong(line);
    90  
    91  	for (i = 1; i <= 2; i++)
    92  	{
    93  		getline(ist, line);
    94  	}
    95  	getline(ist, line);
    96  	num[0] = tolong(line);
    97  
    98  	for (i = 1; i <= 3; i++)
    99  	{
   100  		getline(ist, line);
   101  	}
   102  	getline(ist, line);
   103  	num[1] = tolong(line);
   104  	getline(ist, line);
   105  	num[2] = tolong(line);
   106  
   107  	for (i = 1; i <= 2; i++)
   108  	{
   109  		getline(ist, line);
   110  	}
   111  	getline(ist, line);
   112  	num[4] = tolong(line);
   113  
   114  	for (i = 1; i <= 2; i++)
   115  	{
   116  		getline(ist, line);
   117  	}
   118  	getline(ist, line);
   119  	num[7] = tolong(line);
   120  
   121  	for (i = 1; i <= 2; i++)
   122  	{
   123  		getline(ist, line);
   124  	}
   125  	getline(ist, line);
   126  	num[3] = tolong(line);
   127  
   128  	for (i = 1; i <= 4; i++)
   129  	{
   130  		getline(ist, line);
   131  	}
   132  	getline(ist, line);
   133  	num[6] = tolong(line);
   134  
   135  	for (i = 1; i <= 5; i++)
   136  	{
   137  		getline(ist, line);
   138  	}
   139  	getline(ist, line);
   140  	if (line != "0")
   141  	{
   142  		ist.close();
   143  	}
   144  	else
   145  	{
   146  	}
   147  }
   148  
   149  long Functions::tolong(string s)
   150  {
   151  	//using namespace std;
   152  	long n;
   153  	stringstream ss(s); // Could of course also have done ss("1234") directly.
   154  
   155  	if ((ss >> n).fail())
   156  	{
   157  		//error
   158  	}
   159  
   160  	return n;
   161  }
   162  
   163  string Functions::tostring(long n)
   164  {
   165  
   166  	stringstream ss;
   167  	ss << n;
   168  	return ss.str();
   169  }
   170  
   171  //ygi:THIS IS IT PARAL
   172  void Functions::createCipher(vector<vector<ZZ>> *secrets, int m, int n, int N, vector<vector<Cipher_elg> *> *C, vector<vector<Mod_p> *> *elements, ElGammal *enc_key)
   173  {
   174  	ZZ ord = H.get_ord();
   175  	atomic<std::int32_t> count(1);
   176  
   177  	for (long i = 0; i < m; i++)
   178  	{
   179  		C->push_back(new vector<Cipher_elg>(n));
   180  		elements->push_back(new vector<Mod_p>(n));
   181  	}
   182  
   183  //PARALLELIZE
   184  #pragma omp parallel for collapse(2) num_threads(num_threads) if (parallel)
   185  	for (long i = 0; i < m; i++)
   186  	{
   187  		for (long j = 0; j < n; j++)
   188  		{
   189  			ZZ ran_2 = RandomBnd(ord);
   190  			Cipher_elg temp;
   191  			Mod_p ran_1;
   192  			if (count.fetch_add(1) <= N)
   193  			{
   194  				ran_1 = H.map_to_group_element(secrets->at(i).at(j));
   195  				temp = enc_key->encrypt(ran_1, ran_2);
   196  			}
   197  			else
   198  			{
   199  				ZZ x(RandomBnd(ord));
   200  				ran_1 = H.map_to_group_element(x);
   201  				temp = enc_key->encrypt(ran_1, ran_2);
   202  			}
   203  			C->at(i)->at(j) = temp;
   204  			elements->at(i)->at(j) = ran_1;
   205  		}
   206  	}
   207  }
   208  
   209  void Functions::createCipherWithProof(vector<vector<ZZ>> *secrets, int m, int n, int N, vector<vector<Cipher_elg> *> *C, vector<vector<Mod_p> *> *elements, char *proofs, ElGammal *enc_key)
   210  {
   211  	ZZ ord = H.get_ord();
   212  	atomic<std::int32_t> count(1);
   213  
   214  	for (long i = 0; i < m; i++)
   215  	{
   216  		C->push_back(new vector<Cipher_elg>(n));
   217  		elements->push_back(new vector<Mod_p>(n));
   218  	}
   219  
   220  //PARALLELIZE
   221  #pragma omp parallel for collapse(2) num_threads(num_threads) if (parallel)
   222  	for (long i = 0; i < m; i++)
   223  	{
   224  		for (long j = 0; j < n; j++)
   225  		{
   226  			ZZ ran_2 = RandomBnd(ord);
   227  			Cipher_elg temp;
   228  			Mod_p ran_1;
   229  			if (count.fetch_add(1) <= N)
   230  			{
   231  				ran_1 = H.map_to_group_element(secrets->at(i).at(j));
   232  				temp = enc_key->encrypt(ran_1, ran_2);
   233  			}
   234  			else
   235  			{
   236  				ZZ x(RandomBnd(ord));
   237  				ran_1 = H.map_to_group_element(x);
   238  				temp = enc_key->encrypt(ran_1, ran_2);
   239  			}
   240  			C->at(i)->at(j) = temp;
   241  			elements->at(i)->at(j) = ran_1;
   242  
   243  			SchnorrProof pf = SchnorrProof(ran_2);
   244  			int k = SchnorrProof::bytesize * (i * n + j);
   245  			pf.serialize(&proofs[k]);
   246  		}
   247  	}
   248  }
   249  
   250  void Functions::randomEl(vector<vector<ZZ> *> *R, int m, int n)
   251  {
   252  	vector<ZZ> *r = 0;
   253  	ZZ ord;
   254  	long i, j;
   255  	ord = H.get_ord();
   256  
   257  	for (i = 0; i < m; i++)
   258  	{
   259  		r = new vector<ZZ>(n);
   260  
   261  		for (j = 0; j < n; j++)
   262  		{
   263  			r->at(j) = RandomBnd(ord);
   264  		}
   265  
   266  		R->at(i) = r;
   267  	}
   268  }
   269  
   270  vector<long> permutation2d_to_vector(vector<vector<vector<long> *> *> *pi, int m, int n)
   271  {
   272  	vector<long> reversed_perm(m * n);
   273  	int max = 0;
   274  	for (long i = 0; i < m; i++)
   275  	{
   276  		for (long j = 0; j < n; j++)
   277  		{
   278  			reversed_perm.at(n * i + j) = n * pi->at(i)->at(j)->at(0) + pi->at(i)->at(j)->at(1);
   279  			if (reversed_perm.at(n * i + j) > max)
   280  			{
   281  				max = reversed_perm.at(n * i + j);
   282  			}
   283  		}
   284  	}
   285  
   286  	cout << "The max: " << max << endl;
   287  	return reversed_perm;
   288  }
   289  
   290  bool test_perm(const vector<vector<vector<long> *> *> *pi,
   291  			   const vector<vector<vector<long>> *> *reversed, int m, int n)
   292  {
   293  	cout << "testing the reverse" << endl;
   294  	for (long i = 0; i < m; i++)
   295  	{
   296  		for (long j = 0; j < n; j++)
   297  		{
   298  			int row = pi->at(i)->at(j)->at(0);
   299  			int col = pi->at(i)->at(j)->at(1);
   300  
   301  			int r_row = reversed->at(row)->at(col).at(0);
   302  			int r_col = reversed->at(row)->at(col).at(1);
   303  			if ((r_row != i) || (r_col != j))
   304  			{
   305  				cout << "reversed permutation error! row " << row << " -> " << r_row << endl;
   306  				cout << "reversed permutation error! col " << col << " -> " << r_col << endl;
   307  				return false;
   308  			}
   309  		}
   310  	}
   311  	return true;
   312  }
   313  
   314  vector<long> Functions::permutation2d_to_vector(vector<vector<vector<long> *> *> *pi,
   315  												long m, long n)
   316  {
   317  	vector<long> perm(m * n);
   318  	for (long i = 0; i < m; i++)
   319  	{
   320  		for (long j = 0; j < n; j++)
   321  		{
   322  			perm.at(n * i + j) = n * pi->at(i)->at(j)->at(0) + pi->at(i)->at(j)->at(1);
   323  		}
   324  	}
   325  	return perm;
   326  }
   327  
   328  void Functions::reencryptCipher(vector<vector<Cipher_elg> *> *C,
   329  								vector<vector<Cipher_elg> *> *e, vector<vector<vector<long> *> *> *pi,
   330  								vector<vector<ZZ> *> *R, int m, int n, ElGammal *reenc_pub_key)
   331  {
   332  	for (long i = 0; i < m; i++)
   333  	{
   334  		C->at(i) = new vector<Cipher_elg>(n);
   335  	}
   336  //PARALLELIZE
   337  #pragma omp parallel for collapse(2) num_threads(num_threads) if (parallel)
   338  	for (long i = 0; i < m; i++)
   339  	{
   340  		for (long j = 0; j < n; j++)
   341  		{
   342  			long row, col;
   343  			row = pi->at(i)->at(j)->at(0);
   344  			col = pi->at(i)->at(j)->at(1);
   345  			Cipher_elg temp = reenc_pub_key->encrypt(curve_zeropoint(), R->at(row)->at(col));
   346  			Cipher_elg::mult(C->at(i)->at(j), temp, e->at(row)->at(col));
   347  		}
   348  	}
   349  }
   350  
   351  //Returns the Hadamard product of x and y
   352  void Functions::Hadamard(vector<ZZ> *ret, vector<ZZ> *x, vector<ZZ> *y)
   353  {
   354  
   355  	long n, m, i;
   356  	ZZ ord = H.get_ord();
   357  	n = x->size();
   358  	m = y->size();
   359  
   360  	if (m != n)
   361  	{
   362  		cout << "Not possible" << endl;
   363  	}
   364  	else
   365  	{
   366  		for (i = 0; i < n; i++)
   367  		{
   368  			MulMod(ret->at(i), x->at(i), y->at(i), ord);
   369  		}
   370  	}
   371  }
   372  
   373  //returns the bilinear map of x and y, defined as x(y¡t)^T
   374  ZZ Functions::bilinearMap(vector<ZZ> *x, vector<ZZ> *y, vector<ZZ> *t)
   375  {
   376  	long i, l;
   377  	ZZ result, ord, tem;
   378  
   379  	vector<ZZ> *temp = new vector<ZZ>(x->size());
   380  
   381  	ord = H.get_ord();
   382  	Hadamard(temp, y, t);
   383  	l = x->size();
   384  	result = 0;
   385  	for (i = 0; i < l; i++)
   386  	{
   387  		MulMod(tem, x->at(i), temp->at(i), ord);
   388  		AddMod(result, result, tem, ord);
   389  	}
   390  	delete temp;
   391  	return result;
   392  }
   393  
   394  //help functions to delete matrices
   395  void Functions::delete_vector(vector<vector<ZZ> *> *v)
   396  {
   397  	if (v == NULL)
   398  		return;
   399  	long i;
   400  	long l = v->size();
   401  
   402  	for (i = 0; i < l; i++)
   403  	{
   404  		delete v->at(i);
   405  		v->at(i) = 0;
   406  	}
   407  	delete v;
   408  }
   409  
   410  void Functions::delete_vector(vector<vector<long> *> *v)
   411  {
   412  	if (v == NULL)
   413  		return;
   414  	long i;
   415  	long l = v->size();
   416  
   417  	for (i = 0; i < l; i++)
   418  	{
   419  		delete v->at(i);
   420  		v->at(i) = 0;
   421  	}
   422  	delete v;
   423  }
   424  void Functions::delete_vector(vector<vector<Cipher_elg> *> *v)
   425  {
   426  	if (v == NULL)
   427  		return;
   428  	long i;
   429  	long l = v->size();
   430  
   431  	for (i = 0; i < l; i++)
   432  	{
   433  		delete v->at(i);
   434  		v->at(i) = 0;
   435  	}
   436  	delete v;
   437  }
   438  
   439  void Functions::delete_vector(vector<vector<vector<long> *> *> *v)
   440  {
   441  	if (v == NULL)
   442  		return;
   443  	long i;
   444  	long l = v->size();
   445  
   446  	for (i = 0; i < l; i++)
   447  	{
   448  		delete_vector(v->at(i));
   449  	}
   450  	delete v;
   451  }
   452  
   453  void Functions::delete_vector(vector<vector<vector<ZZ> *> *> *v)
   454  {
   455  	if (v == NULL)
   456  		return;
   457  	long i;
   458  	long l = v->size();
   459  
   460  	for (i = 0; i < l; i++)
   461  	{
   462  		delete_vector(v->at(i));
   463  	}
   464  	delete v;
   465  }
   466  
   467  //picks random value r and commits to the vector a,
   468  void Functions::commit_op(vector<ZZ> *a, ZZ &r, Mod_p &com, Pedersen &ped)
   469  {
   470  	ZZ ord = H.get_ord();
   471  
   472  	r = RandomBnd(ord);
   473  	com = ped.commit_opt(a, r);
   474  }
   475  
   476  //picks random values r and commits to the rows of the matrix a, a,r,com are variables of Prover
   477  void Functions::commit_op(vector<vector<ZZ> *> *a_in, vector<ZZ> *r, vector<Mod_p> *com, Pedersen &ped)
   478  {
   479  	long i, l;
   480  	ZZ ord = H.get_ord();
   481  
   482  	l = a_in->size();
   483  
   484  	{
   485  //PARALLELIZE
   486  #pragma omp parallel for num_threads(num_threads) if (parallel)
   487  		for (i = 0; i < l; i++)
   488  		{
   489  			r->at(i) = RandomBnd(ord);
   490  		}
   491  	}
   492  
   493  	{
   494  //PARALLELIZE
   495  #pragma omp parallel for num_threads(num_threads) if (parallel)
   496  		for (i = 0; i < l; i++)
   497  		{
   498  			com->at(i) = ped.commit_opt(a_in->at(i), r->at(i));
   499  		}
   500  	}
   501  }
   502  
   503  int Functions::get_num_cols(int m, int num_elements)
   504  {
   505  	float converted = num_elements;
   506  	float m_conv = m;
   507  
   508  	int x = ceil(converted / m_conv);
   509  	if (x < 4)
   510  		x = 4;
   511  	return x;
   512  }
   513  
   514  void Functions::parse_ciphers(string &s, long m, vector<vector<Cipher_elg> *> &C, ElGammal *elgammal)
   515  {
   516  	string line;
   517  	//cout << "parse_cipher m = " << m << endl;
   518  	ZZ ran_2, ord;
   519  	Cipher_elg temp;
   520  	vector<Cipher_elg> parsed;
   521  	ord = H.get_ord();
   522  	//vector<vector<Cipher_elg>* >* C=new vector<vector<Cipher_elg>* >(m);
   523  #if USE_REAL_POINTS
   524  	for (unsigned int i = 0; i < s.size() / (CurvePoint::bytesize); i++)
   525  	{
   526  		CurvePoint u;
   527  		u.deserialize(s.c_str() + i * CurvePoint::bytesize);
   528  		Cipher_elg ciph = Cipher_elg(u, H.get_mod());
   529  		parsed.push_back(ciph);
   530  	}
   531  #else
   532  	istringstream f(s);
   533  	while (std::getline(f, line))
   534  	{
   535  		if (line == "***")
   536  			break;
   537  		istringstream cipher_stream(line);
   538  		Cipher_elg ciph;
   539  		cipher_stream >> ciph;
   540  		parsed.push_back(ciph);
   541  	}
   542  #endif
   543  	unsigned long cols = get_num_cols(m, parsed.size());
   544  	vector<Cipher_elg> *r = 0;
   545  	int count = 0;
   546  	//cout << "m = " << m << ", cols = " << cols << ", parsed size = " << parsed.size() << endl;
   547  	for (unsigned int i = 0; i < m; i++)
   548  	{
   549  		r = new vector<Cipher_elg>(cols);
   550  		for (unsigned int j = 0; j < cols; j++)
   551  		{
   552  			if (cols * i + j < parsed.size())
   553  			{
   554  				r->at(j) = parsed[cols * i + j];
   555  			}
   556  			else
   557  			{
   558  				//this part of code should not be used
   559  				//cout << "parse_ciphers 111111111111111" << endl;
   560  				ran_2 = RandomBnd(H.get_ord());
   561  				r->at(j) = elgammal->encrypt(curve_zeropoint(), ran_2);
   562  			}
   563  			count++;
   564  		}
   565  
   566  		C.push_back(r);
   567  		//C->at(i)=r;
   568  	}
   569  }
   570  
   571  unsigned int element_encode_size(vector<vector<Cipher_elg> *> *ciphers,
   572  								 unsigned int &total_ciphers)
   573  {
   574  	unsigned int max = 0;
   575  	total_ciphers = 0;
   576  	for (unsigned int i = 0; i < ciphers->size(); i++)
   577  	{
   578  		for (unsigned int j = 0; j < ciphers->at(i)->size(); j++)
   579  		{
   580  #if USE_REAL_POINTS
   581  			max = CurvePoint::bytesize;
   582  #else
   583  			stringstream buffer;
   584  			buffer << ciphers->at(i)->at(j);
   585  			if (buffer.str().size() > max)
   586  			{
   587  				max = buffer.str().size();
   588  			}
   589  #endif
   590  			total_ciphers++;
   591  		}
   592  	}
   593  	return max;
   594  }
   595  
   596  void write_cipher_to_char_arr(char *outbuf, Cipher_elg &cipher, unsigned int len)
   597  {
   598  #if USE_REAL_POINTS
   599  	cipher.get_u().serialize(outbuf);
   600  	//   cipher.get_v().serialize(outbuf + CurvePoint::bytesize);
   601  #else
   602  	stringstream buffer;
   603  	buffer << cipher;
   604  	memcpy(outbuf, buffer.str().c_str(), buffer.str().size());
   605  	for (unsigned int i = buffer.str().size(); i < len; i++)
   606  	{
   607  		outbuf[i] = ' ';
   608  	}
   609  	outbuf[len] = '\n';
   610  #endif
   611  }
   612  
   613  string Functions::ciphers_to_str(vector<vector<Cipher_elg> *> *ciphers)
   614  {
   615  	unsigned int total_ciphers = 0;
   616  	unsigned int pad_length = element_encode_size(ciphers, total_ciphers);
   617  	if (ciphers->size() == 0)
   618  		return string();
   619  
   620  	unsigned int m = ciphers->size();
   621  	unsigned int n = ciphers->at(0)->size();
   622  
   623  	//cout << "number of ciphers " << total_ciphers << " and m*n = "
   624  	//	 << m * n << "pad_length = " << pad_length << ",m = " << m << ",n = " << n << endl;
   625  
   626  #if USE_REAL_POINTS
   627  	unsigned int total_length = total_ciphers * pad_length;
   628  #else
   629  	unsigned int total_length = total_ciphers + total_ciphers * pad_length;
   630  #endif
   631  	char *output = new char[total_length];
   632  
   633  //PARALLELIZE
   634  #pragma omp parallel for collapse(2) num_threads(num_threads) if (parallel)
   635  	for (unsigned int i = 0; i < m; i++)
   636  	{
   637  		for (unsigned int j = 0; j < n; j++)
   638  		{
   639  			unsigned int index = i * n + j;
   640  #if USE_REAL_POINTS
   641  			write_cipher_to_char_arr(output + index * pad_length, ciphers->at(i)->at(j), pad_length);
   642  #else
   643  			write_cipher_to_char_arr(output + index * (pad_length + 1), ciphers->at(i)->at(j), pad_length);
   644  #endif
   645  		}
   646  	}
   647  
   648  	//output[total_length - 1] = '\0';
   649  	string ret(output, total_length);
   650  	delete[] output;
   651  	return ret;
   652  }
   653  
   654  string Functions::parse_response(std::basic_streambuf<char> *in)
   655  {
   656  	std::ostringstream ss;
   657  	ss << in;
   658  	return ss.str();
   659  }
   660  
   661  void Functions::write_to_file(const string &filename, double output)
   662  {
   663  	while (true)
   664  	{
   665  		ofstream myfile(filename, ios::app);
   666  		if (myfile.is_open())
   667  		{
   668  			myfile << output << "\n";
   669  			myfile.close();
   670  			break;
   671  		}
   672  		usleep(100 * (rand() % 100));
   673  	}
   674  }
   675  
   676  void Functions::sha256(string input, unsigned char *md)
   677  {
   678  	SHA256_CTX context;
   679  	sha256_init(&context);
   680  	sha256_update(&context, (unsigned char *)input.c_str(), input.size());
   681  	sha256_final(&context, md);
   682  }