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 }