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 }