verifenc.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <stdlib.h>
  2. #include <iostream>
  3. #include <fstream>
  4. #include "ecgadget.hpp"
  5. #include "scalarmul.hpp"
  6. using namespace libsnark;
  7. using namespace std;
  8. int main(int argc, char **argv)
  9. {
  10. enum {
  11. MODE_NONE,
  12. MODE_PRIV,
  13. MODE_PUB,
  14. MODE_CONST
  15. } mode = MODE_NONE;
  16. if (argc == 2) {
  17. if (!strcmp(argv[1], "priv")) {
  18. mode = MODE_PRIV;
  19. } else if (!strcmp(argv[1], "pub")) {
  20. mode = MODE_PUB;
  21. } else if (!strcmp(argv[1], "const")) {
  22. mode = MODE_CONST;
  23. }
  24. }
  25. if (mode == MODE_NONE) {
  26. cerr << "Usage: " << argv[0] << " mode" << endl << endl;
  27. cerr << "Where mode is one of:" << endl;
  28. cerr << " priv: use private Ptable" << endl;
  29. cerr << " pub: use public Ptable" << endl;
  30. cerr << " const: use constant public key (no Ptable)" << endl;
  31. exit(1);
  32. }
  33. // Initialize the curve parameters
  34. default_r1cs_gg_ppzksnark_pp::init_public_params();
  35. typedef libff::Fr<default_r1cs_gg_ppzksnark_pp> FieldT;
  36. // Create protoboard
  37. libff::start_profiling();
  38. cout << "Keypair" << endl;
  39. protoboard<FieldT> pb;
  40. pb_variable<FieldT> C1x, C1y, C2x, C2y, Kx, Ky;
  41. pb_variable<FieldT> Px, Py;
  42. pb_variable_array<FieldT> Ptable;
  43. pb_variable<FieldT> k, s, y, r;
  44. // Allocate variables
  45. size_t numbits = FieldT::num_bits;
  46. // Public outputs:
  47. // El Gamal encryption of k under public key P (or H if MODE_CONST)
  48. // C1 = r*G, C2 = r*P + M (where M=(256*k+s,y))
  49. C1x.allocate(pb, "C1x");
  50. C1y.allocate(pb, "C1y");
  51. C2x.allocate(pb, "C2x");
  52. C2y.allocate(pb, "C2y");
  53. // Public key corresponding to private key k
  54. // K = k*G
  55. Kx.allocate(pb, "Kx");
  56. Ky.allocate(pb, "Ky");
  57. // Public inputs:
  58. // The public key P (if not MODE_CONST)
  59. if (mode != MODE_CONST) {
  60. Px.allocate(pb, "Px");
  61. Py.allocate(pb, "Py");
  62. // The Ptable might be public or private, according to the mode
  63. Ptable.allocate(pb, 2*numbits, "Ptable");
  64. }
  65. // Private inputs:
  66. // k is a 246-bit random number
  67. k.allocate(pb, "k");
  68. // s and y are such that M = (256*k+s,y) is a point on the curve
  69. s.allocate(pb, "s");
  70. y.allocate(pb, "y");
  71. // r is the randomness for the El Gamal encryption
  72. r.allocate(pb, "r");
  73. // This sets up the protoboard variables so that the first n of them
  74. // represent the public input and the rest is private input
  75. if (mode == MODE_PRIV) {
  76. pb.set_input_sizes(8);
  77. } else if (mode == MODE_PUB) {
  78. pb.set_input_sizes(8+2*numbits);
  79. } else if (mode == MODE_CONST) {
  80. pb.set_input_sizes(6);
  81. }
  82. // Initialize the gadgets
  83. // Curve parameters and generators
  84. FieldT curve_b("7950939520449436327800262930799465135910802758673292356620796789196167463969");
  85. FieldT Gx(0), Gy("11977228949870389393715360594190192321220966033310912010610740966317727761886");
  86. FieldT Hx(1), Hy("21803877843449984883423225223478944275188924769286999517937427649571474907279");
  87. // Prove (256*k+s,y) is on the curve
  88. pb_variable<FieldT> xsquared, ysquared;
  89. xsquared.allocate(pb, "xsquared");
  90. ysquared.allocate(pb, "ysquared");
  91. pb.add_r1cs_constraint(r1cs_constraint<FieldT>(y, y, ysquared));
  92. pb.add_r1cs_constraint(r1cs_constraint<FieldT>(k * 256 + s, k * 256 + s, xsquared));
  93. pb.add_r1cs_constraint(r1cs_constraint<FieldT>(xsquared - 3, k * 256 + s, ysquared - curve_b));
  94. // The unpacking gadgets to turn k and r into bits
  95. pb_variable_array<FieldT> kbits, rbits;
  96. kbits.allocate(pb, numbits-8, "kbits");
  97. rbits.allocate(pb, numbits, "rbits");
  98. packing_gadget<FieldT> kpacker(pb, kbits, k);
  99. packing_gadget<FieldT> rpacker(pb, rbits, r);
  100. kpacker.generate_r1cs_constraints(true);
  101. rpacker.generate_r1cs_constraints(true);
  102. // The El Gamal first component r*G
  103. ec_constant_scalarmul_vec_gadget<FieldT> C1gadget(pb, C1x, C1y, rbits, Gx, Gy);
  104. C1gadget.generate_r1cs_constraints();
  105. // The El Gamal intermediate value r*P
  106. pb_variable<FieldT> elgx, elgy;
  107. elgx.allocate(pb, "elgx");
  108. elgy.allocate(pb, "elgy");
  109. gadget<FieldT> *ElGgadgetp = NULL;
  110. if (mode == MODE_CONST) {
  111. ElGgadgetp = new ec_constant_scalarmul_vec_gadget<FieldT> (pb, elgx, elgy, rbits, Hx, Hy);
  112. (static_cast<ec_constant_scalarmul_vec_gadget<FieldT>*>(ElGgadgetp))->generate_r1cs_constraints();
  113. } else {
  114. ElGgadgetp = new ec_scalarmul_vec_gadget<FieldT> (pb, elgx, elgy, rbits, Px, Py, Ptable, mode == MODE_PRIV, true);
  115. (static_cast<ec_scalarmul_vec_gadget<FieldT>*>(ElGgadgetp))->generate_r1cs_constraints();
  116. }
  117. // The El Gamal second component r*P + M
  118. pb_linear_combination<FieldT> x;
  119. x.assign(pb, k * 256 + s);
  120. ec_add_gadget<FieldT> ElGfinal(pb, C2x, C2y, elgx, elgy, x, y);
  121. ElGfinal.generate_r1cs_constraints();
  122. // The generated public key k*G
  123. ec_constant_scalarmul_vec_gadget<FieldT> Kgadget(pb, Kx, Ky, kbits, Gx, Gy);
  124. Kgadget.generate_r1cs_constraints();
  125. const r1cs_constraint_system<FieldT> constraint_system = pb.get_constraint_system();
  126. const r1cs_gg_ppzksnark_keypair<default_r1cs_gg_ppzksnark_pp> keypair = r1cs_gg_ppzksnark_generator<default_r1cs_gg_ppzksnark_pp>(constraint_system);
  127. // Add witness values
  128. cout << "Prover" << endl;
  129. if (mode != MODE_CONST) {
  130. // A variable base point P
  131. pb.val(Px) = FieldT("1095194319010475832867263440470707690447963461907735667341232728633587089702");
  132. pb.val(Py) = FieldT("9185463202887631101218413269806857706246311016297504828581985913021301344974");
  133. }
  134. pb.val(k) = FieldT("31329510635628557928212225120518124937732397714111203844965919301557399521");
  135. pb.val(s) = FieldT(1);
  136. pb.val(y) = FieldT("4364798287654239504994818950156019747851405522689486598132350453516910863367");
  137. pb.val(r) = FieldT::random_element();
  138. pb.val(xsquared) = (pb.val(k) * 256 + pb.val(s)).squared();
  139. pb.val(ysquared) = pb.val(y).squared();
  140. kpacker.generate_r1cs_witness_from_packed();
  141. rpacker.generate_r1cs_witness_from_packed();
  142. C1gadget.generate_r1cs_witness();
  143. if (mode == MODE_CONST) {
  144. (static_cast<ec_constant_scalarmul_vec_gadget<FieldT>*>(ElGgadgetp))->generate_r1cs_witness();
  145. } else {
  146. (static_cast<ec_scalarmul_vec_gadget<FieldT>*>(ElGgadgetp))->generate_r1cs_witness();
  147. }
  148. delete ElGgadgetp;
  149. x.evaluate(pb);
  150. ElGfinal.generate_r1cs_witness();
  151. Kgadget.generate_r1cs_witness();
  152. const r1cs_gg_ppzksnark_proof<default_r1cs_gg_ppzksnark_pp> proof = r1cs_gg_ppzksnark_prover<default_r1cs_gg_ppzksnark_pp>(keypair.pk, pb.primary_input(), pb.auxiliary_input());
  153. cout << "Verifier" << endl;
  154. bool verified = r1cs_gg_ppzksnark_verifier_strong_IC<default_r1cs_gg_ppzksnark_pp>(keypair.vk, pb.primary_input(), proof);
  155. cout << "Number of R1CS constraints: " << constraint_system.num_constraints() << endl;
  156. cout << "Primary (public) input length: " << pb.primary_input().size() << endl;
  157. // cout << "Primary (public) input: " << pb.primary_input() << endl;
  158. cout << "Auxiliary (private) input length: " << pb.auxiliary_input().size() << endl;
  159. // cout << "Auxiliary (private) input: " << pb.auxiliary_input() << endl;
  160. cout << "Verification status: " << verified << endl;
  161. ofstream pkfile(string("pk_verifenc_") + argv[1]);
  162. pkfile << keypair.pk;
  163. pkfile.close();
  164. ofstream vkfile(string("vk_verifenc_") + argv[1]);
  165. vkfile << keypair.vk;
  166. vkfile.close();
  167. ofstream pffile(string("proof_verifenc_") + argv[1]);
  168. pffile << proof;
  169. pffile.close();
  170. return 0;
  171. }