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

     1  #include "Utils.h"
     2  
     3  #include "CipherTable.h"
     4  #include "Globals.h"
     5  #include "Functions.h"
     6  #include <string.h>
     7  #include "RemoteShuffler.h"
     8  #include "FakeZZ.h"
     9  #include "SchnorrProof.h"
    10  
    11  #include <cmath>
    12  #include <stdlib.h>
    13  #include <time.h>
    14  #include <map>
    15  #include <stdio.h>
    16  #include <mutex>
    17  using namespace std;
    18  
    19  mutex gInitMutex;
    20  
    21  extern G_q H;
    22  extern G_q G;
    23  
    24  static bool kIsInit = false;
    25  
    26  extern vector<long> num;
    27  
    28  void init_private_key(ElGammal *elgammal, int key_id)
    29  {
    30  	ZZ secret;
    31  	string private_key_file = string("config/keys/priv") + to_string(key_id);
    32  #if USE_REAL_POINTS
    33  	ZZFromBytes(secret, skeys[key_id], 32);
    34  #else
    35  	string line;
    36  	ifstream sist;
    37  	sist.open(private_key_file);
    38  	getline(sist, line);
    39  
    40  	getline(sist, line);
    41  	istringstream secretstr(line);
    42  	secretstr >> secret;
    43  #endif
    44  	elgammal->set_group(G);
    45  	elgammal->set_sk(secret);
    46  }
    47  
    48  void *create_pub_key_use_dero_H()
    49  {
    50  	Mod_p pk;
    51  #if USE_REAL_POINTS
    52  	// private key is
    53  	// {0x50, 0x44, 0x4f, 0x53, 0x0, ...}
    54  	CurvePoint pk_ = raw_curve_pt(deroH);
    55  	// TODO this does not handle garbage collection
    56  	pk = Mod_p(pk_, G.get_mod());
    57  #else
    58  	string fname = string("config/keys/pub") + to_string(key_id);
    59  	ifstream ist;
    60  	ist.open(fname);
    61  	if (ist.fail())
    62  	{
    63  		cout << "cannot open key file " << fname << endl;
    64  		return false; // TODO should probably raise an exception
    65  	}
    66  	string line;
    67  	getline(ist, line);
    68  	istringstream pkstr(line);
    69  	pkstr >> pk;
    70  	ist.close();
    71  #endif
    72  
    73  	ElGammal *ret = new ElGammal();
    74  	ret->set_group(G);
    75  	ret->set_pk(pk);
    76  	return ret;
    77  }
    78  
    79  void *create_pub_key(int key_id)
    80  {
    81  	Mod_p pk;
    82  #if USE_REAL_POINTS
    83  	// private key is
    84  	// {0x50, 0x44, 0x4f, 0x53, 0x0, ...}
    85  	CurvePoint pk_ = raw_curve_pt(pkeys[key_id]);
    86  	// TODO this does not handle garbage collection
    87  	pk = Mod_p(pk_, G.get_mod());
    88  #else
    89  	string fname = string("config/keys/pub") + to_string(key_id);
    90  	ifstream ist;
    91  	ist.open(fname);
    92  	if (ist.fail())
    93  	{
    94  		cout << "cannot open key file " << fname << endl;
    95  		return false; // TODO should probably raise an exception
    96  	}
    97  	string line;
    98  	getline(ist, line);
    99  	istringstream pkstr(line);
   100  	pkstr >> pk;
   101  	ist.close();
   102  #endif
   103  
   104  	ElGammal *ret = new ElGammal();
   105  	ret->set_group(G);
   106  	ret->set_pk(pk);
   107  	return ret;
   108  }
   109  
   110  void *create_decryption_key(int key_id)
   111  {
   112  	ElGammal *elgammal = new ElGammal();
   113  	init_private_key(elgammal, key_id);
   114  	return (void *)elgammal;
   115  }
   116  
   117  void delete_key(void *elgammal)
   118  {
   119  	ElGammal *tmp = (ElGammal *)elgammal;
   120  	delete tmp;
   121  }
   122  
   123  void resetM_N(int m_in, int n_in)
   124  {
   125  	lock_guard<mutex> guard(gInitMutex);
   126  
   127  	Functions::get_config(num, m_in, n_in);
   128  	m = num[1];
   129  }
   130  
   131  void init_public_randoms(int maxN)
   132  {
   133  	ZZ ran(1);
   134  	ZZ mod = G.get_mod();
   135  	stringstream ss;
   136  	Mod_p temp;
   137  
   138  	for (int i = 0; i <= maxN; i++)
   139  	{
   140  		ran = ran + 1;
   141  
   142  #if USE_REAL_POINTS
   143  		CurvePoint x;
   144  		basepoint_scalarmult(x, ran);
   145  		temp = Mod_p(x, mod);
   146  #else
   147  		temp = G.get_gen().expo(to_ZZ(ran));
   148  #endif
   149  		if (G.is_generator(temp))
   150  		{
   151  			ss << temp << endl;
   152  		}
   153  		else
   154  		{
   155  			printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
   156  		}
   157  	}
   158  	publicRandoms = ss.str();
   159  }
   160  
   161  void init()
   162  {
   163  	lock_guard<mutex> guard(gInitMutex);
   164  
   165  	if (kIsInit)
   166  		return;
   167  	Functions::get_config(num, 64, 64);
   168  	//Functions::read_config(kConfigFile, num, genq);
   169  
   170  #if USE_REAL_POINTS
   171  	CurvePoint gen = curve_basepoint();
   172  	ZZ ord = ZZ(NTL::conv<NTL::ZZ>("7237005577332262213973186563042994240857116359379907606001950938285454250989"));
   173  	// ZZ mod = ZZ(NTL::conv<NTL::ZZ>("2093940378184301311653365957372856779274958817946641127345598909177821235333110899157852449358735758089191470831461169154289110965924549400975552759536367817772197222736877807377880197200409316970791234520514702977005806082978079032920444679504632247059010175405894645810064101337094360118559702814823284408560044493630320638017495213077621340331881796467607713650957219938583"));
   174  	ZZ mod = ZZ(NTL::conv<NTL::ZZ>("42"));
   175  #else
   176  	NTL::ZZ gen_sc = NTL::conv<NTL::ZZ>("1929181099559129674691211513194785872536670409492790905276619913671396722443243145931673445424440902236760877484211441680348197072495215150053603001343967365713940597148603897520835948403066356627154482171157913975934174689003578096019980791028264452409955094293631742810957258379488668086855090084223965396993821991583550151470397960480522495500106360092070361350077271147228");
   177  	CurvePoint gen = zz_to_curve_pt(gen_sc);
   178  	ZZ ord = ZZ(NTL::conv<NTL::ZZ>("1257206741114416297422800737364843764556936223541"));
   179  	ZZ mod = ZZ(NTL::conv<NTL::ZZ>("2093940378184301311653365957372856779274958817946641127345598909177821235333110899157852449358735758089191470831461169154289110965924549400975552759536367817772197222736877807377880197200409316970791234520514702977005806082978079032920444679504632247059010175405894645810064101337094360118559702814823284408560044493630320638017495213077621340331881796467607713650957219938583"));
   180  #endif
   181  
   182  	G = G_q(gen, ord, mod);
   183  	H = G_q(gen, ord, mod);
   184  
   185  	m = num[1];
   186  
   187  	init_public_randoms(256);
   188  	//    Pedersen prand(256); // max n
   189  	//    publicRandoms = prand.get_public_vector();
   190  
   191  	kIsInit = true;
   192  }
   193  
   194  string key_index_to_fname(int key_index)
   195  {
   196  	return string("config/keys/pub") + to_string(key_index);
   197  }
   198  
   199  vector<vector<ZZ>> *buildSecretsVector(const unsigned char **secrects, int secretLen, int array_len)
   200  {
   201  	vector<vector<ZZ>> *ret = new vector<vector<ZZ>>(m);
   202  	vector<ZZ> r;
   203  
   204  	int count = 0;
   205  	int num_cols = Functions::get_num_cols(m, array_len);
   206  
   207  	for (int i = 0; i < m; i++)
   208  	{
   209  		r = vector<ZZ>(num_cols);
   210  		for (int j = 0; j < num_cols; j++)
   211  		{
   212  			if (count < array_len)
   213  			{
   214  				r.at(j) = ZZFromBytes(secrects[count], secretLen) % H.get_ord();
   215  			}
   216  			else
   217  			{
   218  				r.at(j) = RandomBnd(H.get_ord());
   219  			}
   220  			count++;
   221  		}
   222  		ret->at(i) = r;
   223  	}
   224  	return ret;
   225  }
   226  
   227  struct ciphertexts_and_proofs
   228  {
   229  	CipherTable *ciphertexts;
   230  	char *proofs;
   231  	int proofs_size;
   232  };
   233  
   234  void *encrypt_with_proof(void **in_secrets, int secretLen, int arrayLen, int keyIndex)
   235  {
   236  	init();
   237  	const unsigned char **secrects = (const unsigned char **)in_secrets;
   238  	ElGammal *elgammal = (ElGammal *)create_pub_key(keyIndex);
   239  	int num_cols = Functions::get_num_cols(m, arrayLen);
   240  	CipherTable *ret = new CipherTable();
   241  	vector<vector<ZZ>> *my_secrets = buildSecretsVector(secrects, secretLen, arrayLen);
   242  
   243  	struct ciphertexts_and_proofs *s = (struct ciphertexts_and_proofs *)malloc(sizeof(struct ciphertexts_and_proofs));
   244  	s->proofs_size = SchnorrProof::bytesize * m * num_cols;
   245  	s->proofs = new char[s->proofs_size];
   246  	Functions::createCipherWithProof(my_secrets, m, num_cols, arrayLen, ret->getCMatrix(), ret->getElementsMatrix(), s->proofs, elgammal);
   247  
   248  	ret->set_dimentions(m, num_cols);
   249  	delete my_secrets;
   250  	delete_key(elgammal);
   251  	s->ciphertexts = ret;
   252  	return s;
   253  }
   254  
   255  void *encrypt_cipher_part(void *cipher_and_proof)
   256  {
   257  	struct ciphertexts_and_proofs *s = (struct ciphertexts_and_proofs *)cipher_and_proof;
   258  	return s->ciphertexts;
   259  }
   260  
   261  void *encrypt_proof_part(void *cipher_and_proof, int *proof_size)
   262  {
   263  	struct ciphertexts_and_proofs *s = (struct ciphertexts_and_proofs *)cipher_and_proof;
   264  	*proof_size = s->proofs_size;
   265  	return s->proofs;
   266  }
   267  
   268  void *delete_ciphers_with_proof(void *x)
   269  {
   270  	struct ciphertexts_and_proofs *s = (struct ciphertexts_and_proofs *)x;
   271  	delete_ciphers(s->ciphertexts);
   272  	delete[] s->proofs;
   273  	free(s);
   274  }
   275  
   276  int verify_encrypt(void *ciphertexts, int ciphertexts_size, void *pfs, int proofs_size)
   277  {
   278  	init();
   279  	int num_elems = proofs_size / SchnorrProof::bytesize;
   280  	int num_cols = num_elems / m;
   281  	CipherTable *ct = (CipherTable *)parse_ciphers(ciphertexts, ciphertexts_size, 0); // TODO check this doesn't segfault
   282  	char *proofs = (char *)pfs;
   283  
   284  	volatile int verified = 1;
   285  #pragma omp parallel for collapse(2) num_threads(num_threads) if (parallel)
   286  	for (int i = 0; i < m; i++)
   287  	{
   288  		for (int j = 0; j < num_cols; j++)
   289  		{
   290  			char *proof = &proofs[(i * num_cols + j) * SchnorrProof::bytesize];
   291  			SchnorrProof pf = SchnorrProof(proof);
   292  			Cipher_elg c = ct->get_elg_cipher(i, j);
   293  			CurvePoint x = c.get_u();
   294  
   295  			if (pf.verify(x) == 0)
   296  			{
   297  				verified = 0;
   298  			}
   299  		}
   300  	}
   301  	delete ct;
   302  
   303  	return verified;
   304  }
   305  
   306  void *encrypt(void **in_secrets, int secretLen, int arrayLen, int keyIndex)
   307  {
   308  	init();
   309  	const unsigned char **secrects = (const unsigned char **)in_secrets;
   310  	ElGammal *elgammal = (ElGammal *)create_pub_key(keyIndex);
   311  	int num_cols = Functions::get_num_cols(m, arrayLen);
   312  	CipherTable *ret = new CipherTable();
   313  	vector<vector<ZZ>> *my_secrets = buildSecretsVector(secrects, secretLen, arrayLen);
   314  	Functions::createCipher(my_secrets, m, num_cols, arrayLen, ret->getCMatrix(), ret->getElementsMatrix(), elgammal);
   315  	ret->set_dimentions(m, num_cols);
   316  	delete my_secrets;
   317  	delete_key(elgammal);
   318  	return ret;
   319  }
   320  
   321  void *get_ciphertexts(void *in_table, void *in_len, void *in_elmenent_size)
   322  {
   323  	int *elmenent_size = (int *)in_elmenent_size;
   324  	int *len = (int *)in_len;
   325  	CipherTable *cipher_table = (CipherTable *)in_table;
   326  	string encoded(cipher_table->encode_all_ciphers());
   327  	*len = encoded.size();
   328  	*elmenent_size = (*len) / (cipher_table->rows() * cipher_table->cols());
   329  	char *out = new char[*len];
   330  	memcpy(out, encoded.c_str(), *len);
   331  	return (void *)out;
   332  }
   333  
   334  void *get_element(void *in_table, int index, void *in_len)
   335  {
   336  	int *len = (int *)in_len;
   337  	CipherTable *cipher_table = (CipherTable *)in_table;
   338  	int i = index / cipher_table->cols();
   339  	int j = index % cipher_table->cols();
   340  
   341  	// use canonical serialization
   342  #if USE_REAL_POINTS
   343  	CurvePoint pt = cipher_table->getElementsMatrix()->at(i)->at(j).get_val();
   344  	*len = 32; // TODO is this correct?
   345  	char *out = new char[*len];
   346  	pt.serialize_canonical(out);
   347  #else
   348  	string encoded(cipher_table->getElement(i, j));
   349  	*len = encoded.size();
   350  	char *out = new char[*len];
   351  	memcpy(out, encoded.c_str(), *len);
   352  #endif
   353  	return (void *)out;
   354  }
   355  
   356  void delete_ciphers(void *in_table)
   357  {
   358  	CipherTable *cipher_table = (CipherTable *)in_table;
   359  	delete cipher_table;
   360  }
   361  
   362  int rows(void *cipher_table)
   363  {
   364  	return ((CipherTable *)cipher_table)->rows();
   365  }
   366  
   367  int cols(void *cipher_table)
   368  {
   369  	return ((CipherTable *)cipher_table)->cols();
   370  }
   371  
   372  void *get_cipher(void *cipher_table, int i, int j, void *in_len)
   373  {
   374  	int *len = (int *)in_len;
   375  	CipherTable *ct = (CipherTable *)cipher_table;
   376  	string cipher(ct->getCipher(i, j));
   377  	*len = cipher.size();
   378  	char *out = new char[*len];
   379  	memcpy(out, cipher.c_str(), *len);
   380  	return (void *)out;
   381  }
   382  
   383  void *parse_ciphers(void *in_ciphers, int len, void *elgammal)
   384  {
   385  	unsigned char *ciphers = (unsigned char *)in_ciphers;
   386  	long m = num[1];
   387  
   388  	string c((char *)ciphers, len);
   389  	return new CipherTable(c, m, (ElGammal *)elgammal);
   390  }
   391  
   392  void *decrypt_cipher(void *in_table, int i, int j, void *in_len, void *elgammal_in)
   393  {
   394  	init();
   395  
   396  	ElGammal *elgammal = (ElGammal *)elgammal_in;
   397  	int *len = (int *)in_len;
   398  	CipherTable *ciphers = (CipherTable *)in_table;
   399  	Mod_p plain = elgammal->decrypt(ciphers->get_elg_cipher(i, j));
   400  
   401  	// use canonical serialization
   402  #if USE_REAL_POINTS
   403  	CurvePoint pt = plain.get_val();
   404  	*len = 32;
   405  	char *out = new char[*len];
   406  	pt.serialize_canonical(out);
   407  #else
   408  	stringstream elm_str;
   409  	elm_str << plain;
   410  	string encoded = elm_str.str();
   411  	*len = encoded.size();
   412  	char *out = new char[*len];
   413  	memcpy(out, encoded.c_str(), *len);
   414  #endif
   415  	return (void *)out;
   416  }
   417  
   418  void delete_str(void *s)
   419  {
   420  	delete[](char *) s;
   421  }
   422  
   423  char **makeCharArray(int size)
   424  {
   425  	return new char *[size];
   426  }
   427  
   428  void setArrayString(char **a, char *s, int index, int src_index, int size)
   429  {
   430  	a[index] = new char[size];
   431  	memcpy(a[index], s + src_index, size);
   432  }
   433  
   434  void freeCharArray(char **a, int size)
   435  {
   436  	int i;
   437  	for (i = 0; i < size; i++)
   438  	{
   439  		delete[] a[i];
   440  	}
   441  	delete[] a;
   442  }
   443  
   444  void test()
   445  {
   446  	init();
   447  
   448  	const int SECRET_SIZE = 1;
   449  
   450  	srand((unsigned int)time(NULL));
   451  
   452  	long m = num[1];
   453  	long n = 65;
   454  	cout << "!shuffling " << n * m << " messages" << endl;
   455  	unsigned char **secrets = new unsigned char *[m * n];
   456  
   457  	for (int i = 0; i < m * n; i++)
   458  	{
   459  		secrets[i] = new unsigned char[SECRET_SIZE];
   460  		for (int j = 0; j < SECRET_SIZE; j++)
   461  		{
   462  			secrets[i][j] = (char)rand();
   463  		}
   464  	}
   465  
   466  	time_t begin = time(NULL);
   467  	CipherTable *ciphers = (CipherTable *)encrypt((void **)secrets, SECRET_SIZE, m * n, 1);
   468  	time_t enc_time = time(NULL);
   469  	cout << "ecryption time: " << enc_time - begin << endl;
   470  	cout << "ciphe table m = " << ciphers->rows() << " ,n = " << ciphers->cols() << endl;
   471  
   472  	time_t parse_start = time(NULL);
   473  	cout << "parsing input" << endl;
   474  	string shuffle_input(ciphers->encode_all_ciphers());
   475  
   476  	char *shuffled_ciphers;
   477  	int shuffled_ciphers_len;
   478  	char *proof;
   479  	int proof_len;
   480  	int *permutation;
   481  	int permutation_len;
   482  	char *public_randoms;
   483  	int public_randoms_len;
   484  
   485  	cout << "shuffle begins!" << endl;
   486  	ElGammal *elgammal = (ElGammal *)create_pub_key(1);
   487  
   488  	CipherTable ct = CipherTable(shuffle_input, m, elgammal);
   489  	cout << "done parsing. " << time(NULL) - parse_start << endl;
   490  
   491  	char *input = (char *)shuffle_input.c_str();
   492  	time_t shuffle_time = time(NULL);
   493  	void *cached_shuffle = shuffle_internal(elgammal, input, shuffle_input.size(), m * n, &shuffled_ciphers, &shuffled_ciphers_len, &permutation, &permutation_len);
   494  	cout << "shuffle is done! In " << time(NULL) - shuffle_time << endl;
   495  	time_t prove_time = time(NULL);
   496  	prove(cached_shuffle, &proof, &proof_len, &public_randoms, &public_randoms_len);
   497  	cout << "proof is done! In " << time(NULL) - prove_time << endl;
   498  
   499  	time_t verify_time = time(NULL);
   500  	int ret = verify(1, proof, proof_len, input, shuffle_input.size(), shuffled_ciphers, shuffled_ciphers_len, public_randoms, public_randoms_len);
   501  	cout << "verification is done! In " << time(NULL) - verify_time << endl;
   502  	cout << "Shuffle + prove + verify = " << time(NULL) - shuffle_time << endl;
   503  	delete ciphers;
   504  
   505  	for (int i = 0; i < m * n; i++)
   506  	{
   507  		delete[] secrets[i];
   508  	}
   509  	delete[] secrets;
   510  
   511  	delete[] shuffled_ciphers;
   512  	delete[] proof;
   513  	delete[] permutation;
   514  
   515  	if (ret)
   516  	{
   517  		cout << "everything passed!" << endl;
   518  	}
   519  	else
   520  	{
   521  		cout << "shuffle failed!" << endl;
   522  	}
   523  }
   524  
   525  void hello()
   526  {
   527  	printf("hello world!\n");
   528  }
   529  
   530  // returns a pointer caching shuffle data
   531  void *shuffle_internal(void *reenc_key, char *ciphers_in, int ciphers_array_len,
   532  					   int number_of_elements, char **shuffled_ciphers, int *shuffled_ciphers_len,
   533  					   int **permutation, int *permutation_len,
   534  					   void *pi_in, void *R_in)
   535  {
   536  
   537  	init();
   538  	int number_of_cols = Functions::get_num_cols(m, number_of_elements);
   539  	string inp(ciphers_in, ciphers_array_len);
   540  
   541  	CipherTable input(inp, m, (ElGammal *)reenc_key);
   542  	//CipherTable *input = (CipherTable*) inputc;
   543  	vector<vector<Cipher_elg> *> *c = input.getCMatrix(); // contains the original input ciphertexts
   544  	//cout << "shuffle_internal 112, c.size = " << (*c)[0]->size() << ", m = " << m << endl;
   545  	// c does not return safely! it's on the stack...so we must make a copy
   546  	vector<vector<Cipher_elg> *> *c_copy = new vector<vector<Cipher_elg> *>(c->size());
   547  	for (unsigned int i = 0; i < c->size(); i++)
   548  	{
   549  		vector<Cipher_elg> *temp = new vector<Cipher_elg>(*(c->at(i)));
   550  		c_copy->at(i) = temp;
   551  	}
   552  	RemoteShuffler *P = new RemoteShuffler(num, c_copy, (ElGammal *)reenc_key, m, number_of_cols,
   553  										   (vector<vector<vector<long> *> *> *)pi_in, (vector<vector<ZZ> *> *)R_in, true);
   554  	CipherTable output(P->getC(), m);
   555  	int element_size;
   556  	*shuffled_ciphers = (char *)get_ciphertexts(&output, shuffled_ciphers_len, &element_size);
   557  
   558  	//cout << " output rows = " << output.rows() << endl;
   559  	//cout << " output cols = " << output.cols() << endl;
   560  	if (permutation != nullptr && permutation_len != nullptr)
   561  	{
   562  		vector<long> reversed;
   563  		P->reverse_permutation(reversed);
   564  		*permutation_len = reversed.size();
   565  		int *out_perm = new int[*permutation_len];
   566  		for (int i = 0; i < *permutation_len; i++)
   567  		{
   568  			out_perm[i] = reversed.at(i);
   569  		}
   570  		*permutation = out_perm;
   571  	}
   572  	return P;
   573  }
   574  
   575  // requires shuffle_internal to be called first and cached data must be passed in
   576  // on exit, deletes cached shuffle data
   577  // TODO cache freeing function may be cleaner interface
   578  void prove(void *cache_data, char **proof_out, int *proof_len, char **public_randoms, int *public_randoms_len)
   579  {
   580  	init();
   581  
   582  	RemoteShuffler *P = (RemoteShuffler *)cache_data;
   583  	string proof = P->create_nizk();
   584  	*proof_len = proof.size();
   585  	*proof_out = new char[*proof_len + 1];
   586  	(*proof_out)[*proof_len] = '\0';
   587  	memcpy(*proof_out, proof.c_str(), *proof_len);
   588  	if (public_randoms != nullptr && public_randoms_len != nullptr)
   589  	{
   590  		string pubv = P->get_public_vector();
   591  		char *rands = new char[pubv.size() + 1];
   592  		rands[pubv.size()] = '\0';
   593  		memcpy(rands, pubv.c_str(), pubv.size());
   594  		*public_randoms_len = pubv.size();
   595  		*public_randoms = rands;
   596  	}
   597  	delete P;
   598  }
   599  
   600  int verify(int key_index, char *proof, int proof_len, char *ciphers_in, int len_in,
   601  		   char *post_shuffle_cipehrs, int post_shuffle_cipehrs_len, char *public_randoms,
   602  		   int public_randoms_len)
   603  {
   604  	init();
   605  	//cout << "verify here 0" << endl;
   606  	ElGammal *elgammal = (ElGammal *)create_pub_key_use_dero_H();
   607  	//cout << "verify here 1" << endl;
   608  	string inp(ciphers_in, len_in);
   609  	string out(post_shuffle_cipehrs, post_shuffle_cipehrs_len);
   610  	CipherTable c(inp, m, elgammal);
   611  	//CipherTable *c = (CipherTable*) cc;
   612  	CipherTable C(out, m, elgammal);
   613  	//cout << "m = " << m << ", c rows = " << c.rows() << ", C rows = " << C.rows() << endl;
   614  	//cout << "c cols = " << c.cols() << ", C cols = " << C.cols() << endl;
   615  	if ((c.rows() != C.rows()) || (c.cols() != C.cols()))
   616  	{
   617  		//	cout << "return here 0" << endl;
   618  		return false;
   619  	}
   620  
   621  	string in_rands(public_randoms, public_randoms_len);
   622  	istringstream respstream(in_rands);
   623  
   624  	VerifierClient V(num, C.rows(), C.cols(), c.getCMatrix(), C.getCMatrix(), elgammal, false, true);
   625  	V.set_public_vector(respstream, c.cols(), num[3], num[7], num[4]);
   626  	string proof_s(proof, proof_len);
   627  	delete[] public_randoms;
   628  	if (V.process_nizk(proof_s))
   629  	{
   630  		delete elgammal;
   631  		return 1;
   632  	}
   633  	//cout << "return here 00" << endl;
   634  	delete elgammal;
   635  	return 0;
   636  }
   637  
   638  void delete_int_arr(int *x)
   639  {
   640  	delete[] x;
   641  }
   642  
   643  int get_int_elem(int *arr, int i)
   644  {
   645  	return arr[i];
   646  }
   647  
   648  long getM()
   649  {
   650  	return m;
   651  }