|
@@ -15,6 +15,55 @@ typedef enum {
|
|
|
MODE_CONST
|
|
|
} Mode;
|
|
|
|
|
|
+// If a is a quadratic residue, set sqrt_a to one of its square roots
|
|
|
+// (-sqrt_a will be the other) and return true. Otherwise return false.
|
|
|
+template<typename FieldT>
|
|
|
+bool sqrt_if_possible(FieldT &sqrt_a, const FieldT &a)
|
|
|
+{
|
|
|
+ // 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 w = a^FieldT::t_minus_1_over_2;
|
|
|
+ FieldT x = a * w;
|
|
|
+ FieldT b = x * w; // b = a^t
|
|
|
+
|
|
|
+ while (b != one)
|
|
|
+ {
|
|
|
+ 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
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ sqrt_a = x;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
template<typename FieldT>
|
|
|
class verified_encryption_gadget : public gadget<FieldT> {
|
|
|
private:
|
|
@@ -117,60 +166,17 @@ 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) {
|
|
|
+ while (true) {
|
|
|
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;
|
|
|
+ if (sqrt_if_possible<FieldT>(yval, ysq_candidate)) {
|
|
|
sval = s_candidate;
|
|
|
+ return;
|
|
|
}
|
|
|
+ s_candidate += 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -322,10 +328,17 @@ int main(int argc, char **argv)
|
|
|
cout << "Prover" << endl;
|
|
|
|
|
|
if (mode != MODE_CONST) {
|
|
|
+ FieldT curve_b("7950939520449436327800262930799465135910802758673292356620796789196167463969");
|
|
|
for (size_t i = 0; i < numverifencs; ++i) {
|
|
|
// A variable base point P
|
|
|
- pb.val(Px[i]) = FieldT("1095194319010475832867263440470707690447963461907735667341232728633587089702");
|
|
|
- pb.val(Py[i]) = FieldT("9185463202887631101218413269806857706246311016297504828581985913021301344974");
|
|
|
+ FieldT x, y, ysq;
|
|
|
+ do {
|
|
|
+ x = FieldT::random_element();
|
|
|
+ ysq = (x.squared() - 3)*x + curve_b;
|
|
|
+ } while (!sqrt_if_possible<FieldT>(y, ysq));
|
|
|
+
|
|
|
+ pb.val(Px[i]) = x;
|
|
|
+ pb.val(Py[i]) = y;
|
|
|
}
|
|
|
}
|
|
|
gmp_randstate_t randstate;
|