bool proofOfShuffle(proofStruct &pfStr, const Node &w, const Node &w_prime, const Node &mu, const Node &tau_pos, const Node &sigma_pos) { // Byte trees that will be used in this function Node u; IntLeaf A_prime; IntLeaf C_prime; IntLeaf D_prime; Node F_prime; Node B; Node B_prime; IntLeaf kA; IntLeaf kC; IntLeaf kD; Node kF; Node kB; Node kE; // Save p,q,g for convenience const IntLeaf &p = pfStr.Gq.getIntLeafChild(0); const IntLeaf &q = pfStr.Gq.getIntLeafChild(1); const IntLeaf &g = pfStr.Gq.getIntLeafChild(2); // Step 1 // a) assert that mu is array of Pdersen commitments in pfStr.Gq u = mu; // Loop through all children and make sure each one is // a Pedersen commitment in Gq for(unsigned int i=0; i < pfStr.N; ++i) { try { if(!isPedersenCommitment(pfStr.Gq, u.getIntLeafChild(i))) { // u is not a N-array of Pedersen Commitments return false; } } catch(...) { // u is not a N-array of Pedersen Commitments return false; } } // b) assert that tau_pos is a Node (B, A', B', C', D', F'), where // A',C',D' is in G_q, F' is in Cw and B and B' are arrays of N // elements in Gq try { A_prime = tau_pos.getIntLeafChild(1); C_prime = tau_pos.getIntLeafChild(3); D_prime = tau_pos.getIntLeafChild(4); if(!isElemOfGq(pfStr.Gq, A_prime)) { return false; } if(!isElemOfGq(pfStr.Gq, C_prime)) { return false; } if(!isElemOfGq(pfStr.Gq, D_prime)) { return false; } F_prime = tau_pos.getNodeChild(5); if(pfStr.width == 1) { Node u; Node v; u.addChild(F_prime.getIntLeafChild(0)); v.addChild(F_prime.getIntLeafChild(1)); Node uv; uv.addChild(u); uv.addChild(v); F_prime = uv; } if(!isElemOfCw(pfStr, F_prime)) { return false; } B = tau_pos.getNodeChild(0); B_prime = tau_pos.getNodeChild(2); for(unsigned int i=0; i<pfStr.N; ++i) { if(!isElemOfGq(pfStr.Gq, B.getIntLeafChild(i))) { return false; } if(!isElemOfGq(pfStr.Gq, B_prime.getIntLeafChild(i))) { return false; } } } catch(...) { // tau_pos could not be interpreted as needed return false; } // c) assert that sigma_pos is a Node (kA, kB, kC, kD, kE, kF), // where kA, kC, kD, kF is in Z_q, kB is an array of N elements in // Rw and kE is an array of N elements in G_q try { kA = sigma_pos.getIntLeafChild(0); kC = sigma_pos.getIntLeafChild(2); kD = sigma_pos.getIntLeafChild(3); if(pfStr.width == 1) { kF.addChild(sigma_pos.getNodeChild(5)); } else { kF = sigma_pos.getNodeChild(5); } kB = sigma_pos.getNodeChild(1); kE = sigma_pos.getNodeChild(4); if(!isElemOfZn(q, kA) || !isElemOfZn(q, kC) || !isElemOfZn(q, kD) || !isElemOfRw(pfStr, kF)) { return false; } for(unsigned int i=0; i<pfStr.N; ++i) { if(!isElemOfZn(q, kB.getIntLeafChild(i))) { return false; } if(!isElemOfZn(q, kE.getIntLeafChild(i))) { return false; } } } catch(...) { return false; } // Get random array h - (TODO: could be moved outside of ProofOfShuffle) DataLeaf generators = DataLeaf("generators"); bytevector seed_data = pfStr.rho; bytevector seed_data2 = generators.serialize(); seed_data.insert(seed_data.end(), seed_data2.begin(), seed_data2.end()); RO RO_seed = RO(pfStr.hash, pfStr.nH); IntLeaf s = RO_seed(seed_data); Node h = RandomArray(pfStr.Gq, pfStr.N, pfStr.hash, s.toVector(), pfStr.nR); print_debug("ProofOfShuffle: h", h.serializeString()); // Step 2, compute a seed by creating the node/array Node(g,h,u,pk,w,w') Node seed_gen; // TODO: Fix h-vector // Does not work with correct h-vector either seed_gen.addChild(g); seed_gen.addChild(h); seed_gen.addChild(u); seed_gen.addChild(pfStr.pk); seed_gen.addChild(w); seed_gen.addChild(w_prime); // Concatenate byte representation of rho with seed_gen bytevector gen = pfStr.rho; bytevector gen2 = seed_gen.serialize(); gen.insert(gen.end(), gen2.begin(), gen2.end()); print_debug("ProofOfShuffle: s_hash", gen); // Create a random oracle to be used to generate a seed, seedlen specified RO rs = RO(pfStr.hash, pfStr.nE); // Generate the seed IntLeaf seed = rs(gen); print_debug("ProofOfShuffle: s", seed.toVector()); // Step 3 - TODO: Runda upp nE/8 PRG prg = PRG(pfStr.hash, seed.serialize(), (pfStr.nE/8)*8); Node t; for(unsigned int i=0; i<pfStr.N; ++i) { t.addChild(prg.next()); } // e_i = t_i mod 2^(nE) IntLeaf exp(2); exp.expTo(pfStr.nE); Node e = t.mod(exp); // compute A and F IntLeaf A = u.expMultMod(e, p); Node F; { Node u = w.getNodeChild(0); Node v = w.getNodeChild(1); if(pfStr.width == 1) { F.addChild(u.expMultMod(e, p)); F.addChild(v.expMultMod(e, p)); } else { Node a, b; for(unsigned int i = 0; i < pfStr.width; i++) { a.addChild(u.getNodeChild(i).expMultMod(e, p)); b.addChild(v.getNodeChild(i).expMultMod(e, p)); } F.addChild(a); F.addChild(b); } } print_debug("ProofOfShuffle: A", A.serializeString()); print_debug("ProofOfShuffle: F", F.serializeString()); print_debug("ProofOfShuffle: B", B.serializeString()); print_debug("ProofOfShuffle: Ap", A_prime.serializeString()); print_debug("ProofOfShuffle: Bp", B_prime.serializeString()); print_debug("ProofOfShuffle: Cp", C_prime.serializeString()); print_debug("ProofOfShuffle: Dp", D_prime.serializeString()); print_debug("ProofOfShuffle: Fp", F_prime.serializeString()); // Step 4, compute a challenge // challenge_gen = Node(seed, tau_pos) Node challenge_gen; challenge_gen.addChild(seed); challenge_gen.addChild(tau_pos); // concatenate rho with the Node above gen = pfStr.rho; gen2 = challenge_gen.serialize(); gen.insert(gen.end(), gen2.begin(), gen2.end()); // create a challenge RO RO RO_challenge = RO(pfStr.hash, pfStr.nV); // use the seed above to generate v, interpret v as non-negative integer IntLeaf v = RO_challenge(gen); // Step 5 - Compute C, D and check that equalities hold as specified IntLeaf C = u.prodMod(p).multMod(h.prodMod(p).inverse(p), p); IntLeaf D = B.getIntLeafChild(pfStr.N - 1).multMod(h.getIntLeafChild(0).expMod(e.prodMod(p), p).inverse(p),p); print_debug("ProofOfShuffle: v", v.toVector()); print_debug("ProofOfShuffle: C", C.serializeString()); print_debug("ProofOfShuffle: D", D.serializeString()); print_debug("ProofOfShuffle: k_A", kA.serializeString()); print_debug("ProofOfShuffle: k_B", kB.serializeString()); print_debug("ProofOfShuffle: k_C", kC.serializeString()); print_debug("ProofOfShuffle: k_D", kD.serializeString()); print_debug("ProofOfShuffle: k_F", kF.serializeString()); // Check A^v * A' == g^kA * prod h_i^kE_i IntLeaf left = A.expMod(v, p).multMod(A_prime, p); IntLeaf right = g.expMod(kA, p).multMod(h.expMultMod(kE, p), p); if(A.expMod(v, p).multMod(A_prime, p) != g.expMod(kA, p).multMod(h.expMultMod(kE, p), p)) { return false; } // Check B_i^v * B'_i == g^kB_i * B_{i-1}^kE_i for i = 1,...,N-1 for(unsigned int i=1; i<pfStr.N; ++i) { if(B.getIntLeafChild(i).expMod(v, p).multMod(B_prime.getIntLeafChild(i), p) != g.expMod(kB.getIntLeafChild(i),p).multMod(B.getIntLeafChild(i-1).expMod(kE.getIntLeafChild(i),p), p)) { return false; } } // Handling case: B.getChild(i-1) = h_0, i.e i == 0 if(B.getIntLeafChild(0).expMod(v,p).multMod(B_prime.getIntLeafChild(0), p) != g.expMod(kB.getIntLeafChild(0),p).multMod(h.getIntLeafChild(0).expMod(kE.getIntLeafChild(0),p),p)) { return false; } // Check C^v * C' == g^kC if(C.expMod(v, p).multMod(C_prime,p) != g.expMod(kC, p)) { return false; } // Check D^v * D' == g^kD if(D.expMod(v, p).multMod(D_prime, p) != g.expMod(kD, p)) { return false; } // Check F^v * F' = Enc_pk(1, -kF)* prod (w'_i)^kE_i /*if(pfStr.width == 1) { }*/ //TODO: Fixa denna kodrad /*if(F.expMod(v, p) * F_prime != Enc(pfStr.pk, IntLeaf(1), -kF, p) * w_prime.expMultMod(kE, p)) { return false; }*/ // All equalities holds, return true return true; }
// --------------------------------------------------------------------------------// // MAIN // // --------------------------------------------------------------------------------// int main(int argc, char* argv[]) { // process command-line arguments if (argc<2) { Usage(); exit(1); } char *method = argv[1]; CmdLine *cmdLine = InitCmdLine(method); //--------------------------------------------------------------------------------------// // OPTION -permute: permute rows // //--------------------------------------------------------------------------------------// if (strcmp(method,"-permute")==0) { // read options cmdLine->Read(argv+1,argc-1); MESSAGES(VERBOSE); // initialize random generator unsigned long int seed = RND_SEED+getpid()+time(NULL); gsl_rng *RANDOM_GENERATOR = InitRandomGenerator(seed); // read input long int n_lines; char **L; FILE *fp = LoadStdIn(&n_lines,BUFFER_SIZE); if (n_lines==0) return 0; ALLOCATE1D(L,n_lines,char *); FileBufferText *buffer = new FileBufferText(fp,BUFFER_SIZE); Progress PRG("Reading input rows...",n_lines); for (long int n=0; n<n_lines; n++) { L[n] = StrCopy(buffer->Next()); PRG.Check(); } PRG.Done(); // permute long int *seq; ALLOCATE1D(seq,n_lines,long int); for (long int k=0; k<n_lines; k++) seq[k] = k; gsl_ran_shuffle(RANDOM_GENERATOR,seq,n_lines,sizeof(long int)); // print output Progress PRG1("Printing output rows...",n_lines); for (long int n=0; n<n_lines; n++) { printf("%s\n", L[seq[n]]); PRG1.Check(); } PRG1.Done(); // cleanup FREE1D(seq); delete RANDOM_GENERATOR; delete buffer; } //--------------------------------------------------------------------------------------// // OPTION -resample: resample rows // //--------------------------------------------------------------------------------------// else if (strcmp(method,"-resample")==0) { // read options cmdLine->Read(argv+1,argc-1); MESSAGES(VERBOSE); // initialize random generator unsigned long int seed = (RND_SEED==0)?(getpid()+time(NULL)):RND_SEED; gsl_rng *RANDOM_GENERATOR = InitRandomGenerator(seed); // read input long int n_lines; char **L; FILE *fp = LoadStdIn(&n_lines,BUFFER_SIZE); if (n_lines==0) return 0; ALLOCATE1D(L,n_lines,char *); FileBufferText *buffer = new FileBufferText(fp,BUFFER_SIZE); Progress PRG("Reading input rows...",n_lines); for (long int n=0; n<n_lines; n++) { L[n] = StrCopy(buffer->Next()); PRG.Check(); } PRG.Done(); // print output if (N_SAMPLES<=0) N_SAMPLES = n_lines; Progress PRG1("Printing output rows...",N_SAMPLES); for (long int n=0; n<N_SAMPLES; n++) { long int k = gsl_rng_uniform_int(RANDOM_GENERATOR,n_lines); printf("%s\n", L[k]); PRG1.Check(); } PRG1.Done(); // cleanup delete RANDOM_GENERATOR; delete buffer; } //--------------------------------------------------------------------------------------// // OPTION -number: do row numbering // //--------------------------------------------------------------------------------------// else if (strcmp(method,"-number")==0) { // read options cmdLine->Read(argv+1,argc-1); MESSAGES(VERBOSE); // read input FileBufferText buffer((char*)NULL,BUFFER_SIZE); Progress PRG("Reading input rows...",1); long int id = HEADER?0:1; for (char *inp=buffer.Next(); inp!=NULL; inp=buffer.Next()) { if (id==0) printf("\t"); else printf("%s%012ld\t", PREFIX, id); printf("%s\n", inp); id++; PRG.Check(); } PRG.Done(); } //--------------------------------------------------------------------------------------// // OTHER OPTIONS // //--------------------------------------------------------------------------------------// else { // read options int next_arg = cmdLine->Read(argv,argc); MESSAGES(VERBOSE); // allocate buffer char *BUFFER = (char *) malloc(BUFFER_SIZE*sizeof(char)); if (BUFFER==NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } Sequence rows = strlen(ROW_FILE)==0 ? GetRows(&argv[next_arg],argc-next_arg) : LoadRows(ROW_FILE); // option 1: use period if (PERIOD>0) { int choose = MERGE ? -1 : atoi(argv[next_arg]); //printf("(PERIOD,NEXTARG,CHOOSE) = (%i,%i,%i)\n", PERIOD, next_arg, choose); for (int n=0; ; n++) { if (fgets(BUFFER,BUFFER_SIZE,stdin)==NULL) break; if (BUFFER[strlen(BUFFER)-1]!='\n') { fprintf(stderr, "Error: line was only partially read (max chars=%i)!\n", BUFFER_SIZE); exit(1); } if (BUFFER[strlen(BUFFER)-1]=='\n') BUFFER[strlen(BUFFER)-1] = 0; if (MERGE) printf("%s%s", BUFFER, n%PERIOD==PERIOD-1?"\n":SEPARATOR); else if (n%PERIOD==choose) printf("%s\n", BUFFER); } } // option 2: choose rows else { if (EXCLUDE==true) { for (long int n=0,k=1; k<=rows[0]; n++) { fgets(BUFFER,BUFFER_SIZE,stdin); if (feof(stdin)) break; if (BUFFER[strlen(BUFFER)-1]!='\n') { fprintf(stderr, "Error: line was only partially read (max chars=%i)!\n", BUFFER_SIZE); exit(1); } if (n<rows[k]) printf("%s", BUFFER); else { ++k; if (EMPTY) printf("\n"); } } while (true) { fgets(BUFFER,BUFFER_SIZE,stdin); if (feof(stdin)) break; if (BUFFER[strlen(BUFFER)-1]!='\n') { fprintf(stderr, "Error: line was only partially read (max chars=%i)!\n", BUFFER_SIZE); exit(1); } printf("%s", BUFFER); } } else { for (long int n=0,k=1; k<=rows[0]; n++) { fgets(BUFFER,BUFFER_SIZE,stdin); if (feof(stdin)) break; if (BUFFER[strlen(BUFFER)-1]!='\n') { fprintf(stderr, "Error: line was only partially read (max chars=%i)!\n", BUFFER_SIZE); exit(1); } if (n==rows[k]) { printf("%s", BUFFER); k++; } else if (EMPTY) printf("\n"); } if (EMPTY) { while (true) { fgets(BUFFER,BUFFER_SIZE,stdin); if (feof(stdin)) break; if (BUFFER[strlen(BUFFER)-1]!='\n') { fprintf(stderr, "Error: line was only partially read (max chars=%i)!\n", BUFFER_SIZE); exit(1); } printf("\n"); } } } } // clean up FREE1D(rows); FREE1D(BUFFER); } // clean up delete cmdLine; return 0; }