Browse Source

Have the verifenc gadget compute the s and y values itself

Ian Goldberg 4 years ago
parent
commit
4d459722f0
1 changed files with 94 additions and 14 deletions
  1. 94 14
      verifenc.cpp

+ 94 - 14
verifenc.cpp

@@ -25,6 +25,7 @@ private:
   pb_variable_array<FieldT> kbits, rbits;
   pb_variable<FieldT> elgx, elgy;
   pb_linear_combination<FieldT> x;
+  pb_variable<FieldT> s, y;
   vector<packing_gadget<FieldT> > packers;
   vector<ec_constant_scalarmul_vec_gadget<FieldT> > constmuls;
   vector<ec_scalarmul_vec_gadget<FieldT> > muls;
@@ -35,7 +36,7 @@ public:
   const pb_variable<FieldT> C1x, C1y, C2x, C2y, Kx, Ky;
   const pb_variable<FieldT> Px, Py;
   const pb_variable_array<FieldT> Ptable;
-  const pb_variable<FieldT> k, s, y;
+  const pb_variable<FieldT> k;
 
   verified_encryption_gadget(protoboard<FieldT> &pb,
               Mode mode,
@@ -48,9 +49,7 @@ public:
               const pb_variable<FieldT> &Px,
               const pb_variable<FieldT> &Py,
               const pb_variable_array<FieldT> &Ptable,
-              const pb_variable<FieldT> &k,
-              const pb_variable<FieldT> &s,
-              const pb_variable<FieldT> &y) :
+              const pb_variable<FieldT> &k) :
     gadget<FieldT>(pb, "verified_encryption_gadget"),
     // Curve parameters and generators
     numbits(FieldT::num_bits),
@@ -58,9 +57,10 @@ public:
     Gx(0), Gy("11977228949870389393715360594190192321220966033310912010610740966317727761886"),
     Hx(1), Hy("21803877843449984883423225223478944275188924769286999517937427649571474907279"),
     mode(mode), C1x(C1x), C1y(C1y), C2x(C2x), C2y(C2y),
-    Kx(Kx), Ky(Ky), Px(Px), Py(Py), Ptable(Ptable),
-    k(k), s(s), y(y)
+    Kx(Kx), Ky(Ky), Px(Px), Py(Py), Ptable(Ptable), k(k)
   {
+    s.allocate(pb, "s");
+    y.allocate(pb, "y");
     r.allocate(pb, "r");
     xsquared.allocate(pb, "xsquared");
     ysquared.allocate(pb, "ysquared");
@@ -115,8 +115,73 @@ public:
     }
   }
 
+  void find_s_y(const FieldT &kval, FieldT &sval, FieldT &yval)
+  {
+    // A modification of the Tonelli-Shanks implementation from libff
+    // to catch the case when you encounter a nonresidue
+
+    const FieldT one = FieldT::one();
+
+    size_t v = FieldT::s;
+    FieldT z = FieldT::nqr_to_t;
+
+    FieldT s_candidate = 0;
+    bool found = false;
+    while (!found) {
+        FieldT x_candidate = kval*256+s_candidate;
+        FieldT ysq_candidate = (x_candidate.squared() - 3)*x_candidate + curve_b;
+
+        FieldT w = ysq_candidate^FieldT::t_minus_1_over_2;
+        FieldT x = ysq_candidate * w;
+        FieldT b = x * w; // b = ysq_candidate^t
+
+        bool nonresidue = false;
+        while (b != one && !nonresidue)
+        {
+            size_t m = 0;
+            FieldT b2m = b;
+            while (b2m != one)
+            {
+                /* invariant: b2m = b^(2^m) after entering this loop */
+                b2m = b2m.squared();
+                m += 1;
+            }
+            if (m == v) {
+                // Not a quadratic residue
+                s_candidate += 1;
+                nonresidue = true;
+                break;
+            }
+
+            int j = v-m-1;
+            w = z;
+            while (j > 0)
+            {
+                w = w.squared();
+                --j;
+            } // w = z^2^(v-m-1)
+
+            z = w.squared();
+            b = b * z;
+            x = x * w;
+            v = m;
+        }
+        if (!nonresidue) {
+            found = true;
+            yval = x;
+            sval = s_candidate;
+        }
+    }
+  }
+
   void generate_r1cs_witness()
   {
+    // Find an s and y such that x^3 - 3*x + b = y^2, where x = 256*k + s
+    FieldT sval, yval;
+    find_s_y(this->pb.val(k), sval, yval);
+    this->pb.val(s) = sval;
+    this->pb.val(y) = yval;
+
     this->pb.val(r) = FieldT::random_element();
     this->pb.val(xsquared) = (this->pb.val(k) * 256 + this->pb.val(s)).squared();
     this->pb.val(ysquared) = this->pb.val(y).squared();
@@ -184,7 +249,7 @@ int main(int argc, char **argv)
   pb_variable<FieldT> Kx[numverifencs], Ky[numverifencs];
   pb_variable<FieldT> Px[numverifencs], Py[numverifencs];
   pb_variable_array<FieldT> Ptable[numverifencs];
-  pb_variable<FieldT> k[numverifencs], s[numverifencs], y[numverifencs];
+  pb_variable<FieldT> k[numverifencs];
 
   const size_t numbits = FieldT::num_bits;
 
@@ -225,9 +290,6 @@ int main(int argc, char **argv)
       // Private inputs:
       // k is a 246-bit random number
       k[i].allocate(pb, "k");
-      // s and y are such that M = (256*k+s,y) is a point on the curve
-      s[i].allocate(pb, "s");
-      y[i].allocate(pb, "y");
   }
 
   // This sets up the protoboard variables so that the first n of them
@@ -245,7 +307,7 @@ int main(int argc, char **argv)
   vector<verified_encryption_gadget<FieldT> > vencs;
 
   for (size_t i = 0; i < numverifencs; ++i) {
-      vencs.emplace_back(pb, mode, C1x[i], C1y[i], C2x[i], C2y[i], Kx[i], Ky[i], Px[i], Py[i], Ptable[i], k[i], s[i], y[i]);
+      vencs.emplace_back(pb, mode, C1x[i], C1y[i], C2x[i], C2y[i], Kx[i], Ky[i], Px[i], Py[i], Ptable[i], k[i]);
   }
   for (auto&& gadget : vencs) {
       gadget.generate_r1cs_constraints();
@@ -266,22 +328,40 @@ int main(int argc, char **argv)
         pb.val(Py[i]) = FieldT("9185463202887631101218413269806857706246311016297504828581985913021301344974");
       }
   }
+  gmp_randstate_t randstate;
+  gmp_randinit_default(randstate);
+  FieldT seed = FieldT::random_element();
+  mpz_t seed_mpz;
+  mpz_init(seed_mpz);
+  seed.mont_repr.to_mpz(seed_mpz);
+  gmp_randseed(randstate, seed_mpz);
+  mpz_clear(seed_mpz);
   for (size_t i = 0; i < numverifencs; ++i) {
-      pb.val(k[i]) = FieldT("31329510635628557928212225120518124937732397714111203844965919301557399521");
-      pb.val(s[i]) = FieldT(1);
-      pb.val(y[i]) = FieldT("4364798287654239504994818950156019747851405522689486598132350453516910863367");
+      mpz_t kval;
+      mpz_init(kval);
+      mpz_urandomb(kval, randstate, 246);
+      pb.val(k[i]) = FieldT(kval);
+      mpz_clear(kval);
   }
 
+  libff::enter_block("PROVER TIME");
+
   for (auto&& gadget : vencs) {
       gadget.generate_r1cs_witness();
   }
 
   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());
 
+  libff::leave_block("PROVER TIME");
+
   cout << "Verifier" << endl;
 
+  libff::enter_block("VERIFIER TIME");
+
   bool verified = r1cs_gg_ppzksnark_verifier_strong_IC<default_r1cs_gg_ppzksnark_pp>(keypair.vk, pb.primary_input(), proof);
 
+  libff::leave_block("VERIFIER TIME");
+
   cout << "Number of R1CS constraints: " << constraint_system.num_constraints() << endl;
   cout << "Primary (public) input length: " << pb.primary_input().size() << endl;
 //  cout << "Primary (public) input: " << pb.primary_input() << endl;