1 /*******************************************************************************
2 GrothVSSHE.cc, |V|erifiable |S|ecret |S|huffle of |H|omomorphic |E|ncryptions
3
4 [Gr05] Jens Groth: 'A Verifiable Secret Shuffle of Homomorphic Encryptions',
5 Cryptology ePrint Archive, Report 2005/246, 2005.
6
7 This file is part of LibTMCG.
8
9 Copyright (C) 2005, 2006, 2007, 2009,
10 2016, 2017, 2018, 2019 Heiko Stamer <HeikoStamer@gmx.net>
11
12 LibTMCG is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 LibTMCG is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with LibTMCG; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25 *******************************************************************************/
26
27 // include headers
28 #ifdef HAVE_CONFIG_H
29 #include "libTMCG_config.h"
30 #endif
31 #include "GrothVSSHE.hh"
32
33 // additional headers
34 #include <cassert>
35 #include <string>
36 #include <sstream>
37 #include "mpz_srandom.hh"
38 #include "mpz_spowm.hh"
39 #include "mpz_sprime.hh"
40 #include "mpz_helper.hh"
41 #include "mpz_shash.hh"
42
GrothSKC(size_t n,unsigned long int ell_e,unsigned long int fieldsize,unsigned long int subgroupsize)43 GrothSKC::GrothSKC
44 (size_t n,
45 unsigned long int ell_e, unsigned long int fieldsize,
46 unsigned long int subgroupsize):
47 l_e(ell_e), l_e_nizk(ell_e * 2L)
48 {
49 com = new PedersenCommitmentScheme(n, fieldsize, subgroupsize);
50 }
51
GrothSKC(size_t n,std::istream & in,unsigned long int ell_e,unsigned long int fieldsize,unsigned long int subgroupsize)52 GrothSKC::GrothSKC
53 (size_t n, std::istream &in,
54 unsigned long int ell_e, unsigned long int fieldsize,
55 unsigned long int subgroupsize):
56 l_e(ell_e), l_e_nizk(ell_e * 2L)
57 {
58 com = new PedersenCommitmentScheme(n, in, fieldsize, subgroupsize);
59 }
60
SetupGenerators_publiccoin(mpz_srcptr a)61 void GrothSKC::SetupGenerators_publiccoin
62 (mpz_srcptr a)
63 {
64 com->SetupGenerators_publiccoin(a);
65 }
66
SetupGenerators_publiccoin(const size_t whoami,aiounicast * aiou,CachinKursawePetzoldShoupRBC * rbc,JareckiLysyanskayaEDCF * edcf,std::ostream & err)67 bool GrothSKC::SetupGenerators_publiccoin
68 (const size_t whoami, aiounicast *aiou,
69 CachinKursawePetzoldShoupRBC *rbc,
70 JareckiLysyanskayaEDCF *edcf, std::ostream &err)
71 {
72 return com->SetupGenerators_publiccoin(whoami, aiou, rbc, edcf, err);
73 }
74
CheckGroup() const75 bool GrothSKC::CheckGroup
76 () const
77 {
78 return com->CheckGroup();
79 }
80
PublishGroup(std::ostream & out) const81 void GrothSKC::PublishGroup
82 (std::ostream &out) const
83 {
84 com->PublishGroup(out);
85 }
86
Prove_interactive(const std::vector<size_t> & pi,mpz_srcptr r,const std::vector<mpz_ptr> & m,std::istream & in,std::ostream & out) const87 void GrothSKC::Prove_interactive
88 (const std::vector<size_t> &pi, mpz_srcptr r,
89 const std::vector<mpz_ptr> &m,
90 std::istream &in, std::ostream &out) const
91 {
92 assert(com->g.size() >= pi.size());
93 assert(pi.size() == m.size());
94 assert(m.size() >= 2);
95
96 mpz_t x, r_d, r_Delta, r_a, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar;
97 std::vector<mpz_ptr> d, Delta, a, f, f_Delta, lej;
98
99 // initialize
100 mpz_init(x), mpz_init(r_d), mpz_init(r_Delta), mpz_init(r_a), mpz_init(c_d),
101 mpz_init(c_Delta), mpz_init(c_a), mpz_init(e), mpz_init(z),
102 mpz_init(z_Delta), mpz_init(foo), mpz_init(bar);
103 for (size_t i = 0; i < m.size(); i++)
104 {
105 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
106 tmp4 = new mpz_t(), tmp5 = new mpz_t(), tmp6 = new mpz_t();
107 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4),
108 mpz_init(tmp5), mpz_init(tmp6);
109 d.push_back(tmp), Delta.push_back(tmp2), a.push_back(tmp3),
110 f.push_back(tmp4), f_Delta.push_back(tmp5), lej.push_back(tmp6);
111 }
112
113 // prover: first move
114 in >> x; // get $x$ from the verifier
115 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
116 mpz_tdiv_r_2exp(x, x, l_e);
117
118 // prover: second move
119 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
120 tmcg_mpz_srandomm(r_Delta, com->q); // $r_{\Delta} \gets \mathbb{Z}_q$
121 for (size_t i = 0; i < d.size(); i++)
122 tmcg_mpz_srandomm(d[i], com->q); // $d_1,\ldots,d_n \gets \mathbb{Z}_q$
123 mpz_set(Delta[0], d[0]); // $\Delta_1 := d_1$
124 for (size_t i = 1; i < (Delta.size() - 1); i++)
125 tmcg_mpz_srandomm(Delta[i], com->q); // $\Delta_2,\ldots,\Delta_{n-1}
126 // \gets \mathbb{Z}_q$
127 mpz_set_ui(Delta[Delta.size() - 1], 0L); // $\Delta_n := 0$
128 for (size_t i = 0; i < a.size(); i++)
129 {
130 mpz_set_ui(a[i], 1L);
131 // compute $a_i = \prod_{j=1}^i (m_{\pi(j)} - x)$
132 for (size_t j = 0; j <= i; j++)
133 {
134 mpz_sub(foo, m[pi[j]], x);
135 mpz_mod(foo, foo, com->q);
136 mpz_mul(a[i], a[i], foo);
137 mpz_mod(a[i], a[i], com->q);
138 }
139 }
140 tmcg_mpz_srandomm(r_a, com->q); // $r_a \gets \mathbb{Z}_q$
141 // $c_d = \mathrm{com}_{ck}(d_1,\ldots,d_n;r_d)$
142 com->CommitBy(c_d, r_d, d);
143 for (size_t i = 0; i < lej.size(); i++)
144 {
145 if (i < (lej.size() - 1))
146 {
147 mpz_set(foo, Delta[i]);
148 mpz_neg(foo, foo);
149 mpz_mul(lej[i], foo, d[i + 1]);
150 mpz_mod(lej[i], lej[i], com->q);
151 }
152 else
153 mpz_set_ui(lej[i], 0L);
154 }
155 // $c_{\Delta} = \mathrm{com}_{ck}(-\Delta_1 d_2,\ldots,
156 // -\Delta_{n-1} d_n;r_{\Delta})$
157 com->CommitBy(c_Delta, r_Delta, lej);
158 for (size_t i = 0; i < lej.size(); i++)
159 {
160 if (i < (lej.size() - 1))
161 {
162 mpz_set(foo, Delta[i + 1]);
163 mpz_sub(bar, m[pi[i + 1]], x);
164 mpz_mod(bar, bar, com->q);
165 mpz_mul(bar, bar, Delta[i]);
166 mpz_mod(bar, bar, com->q);
167 mpz_sub(foo, foo, bar);
168 mpz_mod(foo, foo, com->q);
169 mpz_mul(bar, a[i], d[i + 1]);
170 mpz_mod(bar, bar, com->q);
171 mpz_sub(foo, foo, bar);
172 mpz_mod(foo, foo, com->q);
173 mpz_set(lej[i], foo);
174 }
175 else
176 mpz_set_ui(lej[i], 0L);
177 }
178 // $c_a = \mathrm{com}_{ck}(\Delta_2 - (m_{\pi(2)} - x)\Delta_1 - a_1 d_2,
179 // \ldots,\Delta_n - (m_{\pi(n)} - x)\Delta_{n-1}
180 // - a_{n-1} d_n;r_a)$
181 com->CommitBy(c_a, r_a, lej);
182 // send $c_d$, $c_\Delta$, and $c_a$ to the verifier
183 out << c_d << std::endl << c_Delta << std::endl << c_a << std::endl;
184
185 // prover: third move
186 in >> e; // get $e$ from the verifier
187 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
188 mpz_tdiv_r_2exp(e, e, l_e);
189
190 // prover: fourth move
191 // compute $f_i = e m_{\pi(i)} + d_i$
192 for (size_t i = 0; i < f.size(); i++)
193 {
194 mpz_mul(f[i], e, m[pi[i]]);
195 mpz_mod(f[i], f[i], com->q);
196 mpz_add(f[i], f[i], d[i]);
197 mpz_mod(f[i], f[i], com->q);
198 }
199 // compute $z = e r + r_d$
200 mpz_mul(z, e, r);
201 mpz_mod(z, z, com->q);
202 mpz_add(z, z, r_d);
203 mpz_mod(z, z, com->q);
204 // compute $f_{\Delta_i} = e (\Delta_{i+1} - (m_{\pi(i+1)} - x)\Delta_i
205 // - a_i d_{i+1}) - \Delta_i d_{i+1}$
206 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
207 {
208 mpz_set(foo, Delta[i + 1]);
209 mpz_sub(bar, m[pi[i + 1]], x);
210 mpz_mod(bar, bar, com->q);
211 mpz_mul(bar, bar, Delta[i]);
212 mpz_mod(bar, bar, com->q);
213 mpz_sub(foo, foo, bar);
214 mpz_mod(foo, foo, com->q);
215 mpz_mul(bar, a[i], d[i + 1]);
216 mpz_mod(bar, bar, com->q);
217 mpz_sub(foo, foo, bar);
218 mpz_mod(foo, foo, com->q);
219 mpz_mul(foo, foo, e);
220 mpz_mod(foo, foo, com->q);
221 mpz_mul(bar, Delta[i], d[i + 1]);
222 mpz_mod(bar, bar, com->q);
223 mpz_sub(foo, foo, bar);
224 mpz_mod(foo, foo, com->q);
225 mpz_set(f_Delta[i], foo);
226 }
227 // compute $z_{\Delta} = e r_a + r_{\Delta}$
228 mpz_mul(z_Delta, e, r_a);
229 mpz_mod(z_Delta, z_Delta, com->q);
230 mpz_add(z_Delta, z_Delta, r_Delta);
231 mpz_mod(z_Delta, z_Delta, com->q);
232 for (size_t i = 0; i < f.size(); i++)
233 out << f[i] << std::endl; // send $f_1,\ldots,f_n$ to the verifier
234 out << z << std::endl; // send $z$ to the verifier
235 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
236 out << f_Delta[i] << std::endl; // send $f_{\Delta_1},\ldots,
237 // f_{\Delta_{n-1}}$ to verifier
238 out << z_Delta << std::endl; // send $z_{\Delta}$ to the verifier
239
240 // release
241 mpz_clear(x), mpz_clear(r_d), mpz_clear(r_Delta), mpz_clear(r_a),
242 mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a), mpz_clear(e),
243 mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo), mpz_clear(bar);
244 for (size_t i = 0; i < m.size(); i++)
245 {
246 mpz_clear(d[i]), mpz_clear(Delta[i]), mpz_clear(a[i]),
247 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
248 delete [] d[i], delete [] Delta[i], delete [] a[i], delete [] f[i],
249 delete [] f_Delta[i], delete [] lej[i];
250 }
251 d.clear(), Delta.clear(), a.clear(), f.clear(), f_Delta.clear(),
252 lej.clear();
253 }
254
Prove_interactive_publiccoin(const std::vector<size_t> & pi,mpz_srcptr r,const std::vector<mpz_ptr> & m,JareckiLysyanskayaEDCF * edcf,std::istream & in,std::ostream & out) const255 void GrothSKC::Prove_interactive_publiccoin
256 (const std::vector<size_t> &pi, mpz_srcptr r,
257 const std::vector<mpz_ptr> &m,
258 JareckiLysyanskayaEDCF *edcf,
259 std::istream &in, std::ostream &out) const
260 {
261 assert(com->g.size() >= pi.size());
262 assert(pi.size() == m.size());
263 assert(m.size() >= 2);
264
265 mpz_t x, r_d, r_Delta, r_a, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar;
266 std::vector<mpz_ptr> d, Delta, a, f, f_Delta, lej;
267
268 // initialize
269 mpz_init(x), mpz_init(r_d), mpz_init(r_Delta), mpz_init(r_a), mpz_init(c_d),
270 mpz_init(c_Delta), mpz_init(c_a), mpz_init(e), mpz_init(z),
271 mpz_init(z_Delta), mpz_init(foo), mpz_init(bar);
272 for (size_t i = 0; i < m.size(); i++)
273 {
274 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
275 tmp4 = new mpz_t(), tmp5 = new mpz_t(), tmp6 = new mpz_t();
276 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4),
277 mpz_init(tmp5), mpz_init(tmp6);
278 d.push_back(tmp), Delta.push_back(tmp2), a.push_back(tmp3),
279 f.push_back(tmp4), f_Delta.push_back(tmp5), lej.push_back(tmp6);
280 }
281
282 // prover: first move
283 std::stringstream err;
284 edcf->Flip_twoparty(0, x, in, out, err); // flip coins with verifier to get $x$
285 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
286 mpz_tdiv_r_2exp(x, x, l_e);
287
288 // prover: second move
289 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
290 tmcg_mpz_srandomm(r_Delta, com->q); // $r_{\Delta} \gets \mathbb{Z}_q$
291 for (size_t i = 0; i < d.size(); i++)
292 tmcg_mpz_srandomm(d[i], com->q); // $d_1,\ldots,d_n \gets \mathbb{Z}_q$
293 mpz_set(Delta[0], d[0]); // $\Delta_1 := d_1$
294 for (size_t i = 1; i < (Delta.size() - 1); i++)
295 tmcg_mpz_srandomm(Delta[i], com->q); // $\Delta_2,\ldots,\Delta_{n-1}
296 // \gets \mathbb{Z}_q$
297 mpz_set_ui(Delta[Delta.size() - 1], 0L); // $\Delta_n := 0$
298 for (size_t i = 0; i < a.size(); i++)
299 {
300 mpz_set_ui(a[i], 1L);
301 // compute $a_i = \prod_{j=1}^i (m_{\pi(j)} - x)$
302 for (size_t j = 0; j <= i; j++)
303 {
304 mpz_sub(foo, m[pi[j]], x);
305 mpz_mod(foo, foo, com->q);
306 mpz_mul(a[i], a[i], foo);
307 mpz_mod(a[i], a[i], com->q);
308 }
309 }
310 tmcg_mpz_srandomm(r_a, com->q); // $r_a \gets \mathbb{Z}_q$
311 // $c_d = \mathrm{com}_{ck}(d_1,\ldots,d_n;r_d)$
312 com->CommitBy(c_d, r_d, d);
313 for (size_t i = 0; i < lej.size(); i++)
314 {
315 if (i < (lej.size() - 1))
316 {
317 mpz_set(foo, Delta[i]);
318 mpz_neg(foo, foo);
319 mpz_mul(lej[i], foo, d[i + 1]);
320 mpz_mod(lej[i], lej[i], com->q);
321 }
322 else
323 mpz_set_ui(lej[i], 0L);
324 }
325 // $c_{\Delta} = \mathrm{com}_{ck}(-\Delta_1 d_2,\ldots,
326 // -\Delta_{n-1} d_n;r_{\Delta})$
327 com->CommitBy(c_Delta, r_Delta, lej);
328 for (size_t i = 0; i < lej.size(); i++)
329 {
330 if (i < (lej.size() - 1))
331 {
332 mpz_set(foo, Delta[i + 1]);
333 mpz_sub(bar, m[pi[i + 1]], x);
334 mpz_mod(bar, bar, com->q);
335 mpz_mul(bar, bar, Delta[i]);
336 mpz_mod(bar, bar, com->q);
337 mpz_sub(foo, foo, bar);
338 mpz_mod(foo, foo, com->q);
339 mpz_mul(bar, a[i], d[i + 1]);
340 mpz_mod(bar, bar, com->q);
341 mpz_sub(foo, foo, bar);
342 mpz_mod(foo, foo, com->q);
343 mpz_set(lej[i], foo);
344 }
345 else
346 mpz_set_ui(lej[i], 0L);
347 }
348 // $c_a = \mathrm{com}_{ck}(\Delta_2 - (m_{\pi(2)} - x)\Delta_1 - a_1 d_2,
349 // \ldots,\Delta_n - (m_{\pi(n)} - x)\Delta_{n-1}
350 // - a_{n-1} d_n;r_a)$
351 com->CommitBy(c_a, r_a, lej);
352 // send $c_d$, $c_\Delta$, and $c_a$ to the verifier
353 out << c_d << std::endl << c_Delta << std::endl << c_a << std::endl;
354
355 // prover: third move
356 edcf->Flip_twoparty(0, e, in, out, err); // flip coins with verifier to get $e$
357 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
358 mpz_tdiv_r_2exp(e, e, l_e);
359
360 // prover: fourth move
361 // compute $f_i = e m_{\pi(i)} + d_i$
362 for (size_t i = 0; i < f.size(); i++)
363 {
364 mpz_mul(f[i], e, m[pi[i]]);
365 mpz_mod(f[i], f[i], com->q);
366 mpz_add(f[i], f[i], d[i]);
367 mpz_mod(f[i], f[i], com->q);
368 }
369 // compute $z = e r + r_d$
370 mpz_mul(z, e, r);
371 mpz_mod(z, z, com->q);
372 mpz_add(z, z, r_d);
373 mpz_mod(z, z, com->q);
374 // compute $f_{\Delta_i} = e (\Delta_{i+1} - (m_{\pi(i+1)} - x)\Delta_i
375 // - a_i d_{i+1}) - \Delta_i d_{i+1}$
376 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
377 {
378 mpz_set(foo, Delta[i + 1]);
379 mpz_sub(bar, m[pi[i + 1]], x);
380 mpz_mod(bar, bar, com->q);
381 mpz_mul(bar, bar, Delta[i]);
382 mpz_mod(bar, bar, com->q);
383 mpz_sub(foo, foo, bar);
384 mpz_mod(foo, foo, com->q);
385 mpz_mul(bar, a[i], d[i + 1]);
386 mpz_mod(bar, bar, com->q);
387 mpz_sub(foo, foo, bar);
388 mpz_mod(foo, foo, com->q);
389 mpz_mul(foo, foo, e);
390 mpz_mod(foo, foo, com->q);
391 mpz_mul(bar, Delta[i], d[i + 1]);
392 mpz_mod(bar, bar, com->q);
393 mpz_sub(foo, foo, bar);
394 mpz_mod(foo, foo, com->q);
395 mpz_set(f_Delta[i], foo);
396 }
397 // compute $z_{\Delta} = e r_a + r_{\Delta}$
398 mpz_mul(z_Delta, e, r_a);
399 mpz_mod(z_Delta, z_Delta, com->q);
400 mpz_add(z_Delta, z_Delta, r_Delta);
401 mpz_mod(z_Delta, z_Delta, com->q);
402 for (size_t i = 0; i < f.size(); i++)
403 out << f[i] << std::endl; // send $f_1,\ldots,f_n$ to the verifier
404 out << z << std::endl; // send $z$ to the verifier
405 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
406 out << f_Delta[i] << std::endl; // send $f_{\Delta_1},\ldots,
407 // f_{\Delta_{n-1}}$ to verifier
408 out << z_Delta << std::endl; // send $z_{\Delta}$ to the verifier
409
410 // release
411 mpz_clear(x), mpz_clear(r_d), mpz_clear(r_Delta), mpz_clear(r_a),
412 mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a), mpz_clear(e),
413 mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo), mpz_clear(bar);
414 for (size_t i = 0; i < m.size(); i++)
415 {
416 mpz_clear(d[i]), mpz_clear(Delta[i]), mpz_clear(a[i]),
417 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
418 delete [] d[i], delete [] Delta[i], delete [] a[i], delete [] f[i],
419 delete [] f_Delta[i], delete [] lej[i];
420 }
421 d.clear(), Delta.clear(), a.clear(), f.clear(), f_Delta.clear(),
422 lej.clear();
423 }
424
Prove_noninteractive(const std::vector<size_t> & pi,mpz_srcptr r,const std::vector<mpz_ptr> & m,std::ostream & out) const425 void GrothSKC::Prove_noninteractive
426 (const std::vector<size_t> &pi, mpz_srcptr r,
427 const std::vector<mpz_ptr> &m, std::ostream &out) const
428 {
429 assert(com->g.size() >= pi.size());
430 assert(pi.size() == m.size());
431 assert(m.size() >= 2);
432
433 mpz_t x, r_d, r_Delta, r_a, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar;
434 std::vector<mpz_ptr> d, Delta, a, f, f_Delta, lej;
435
436 // initialize
437 mpz_init(x), mpz_init(r_d), mpz_init(r_Delta), mpz_init(r_a), mpz_init(c_d),
438 mpz_init(c_Delta), mpz_init(c_a), mpz_init(e), mpz_init(z),
439 mpz_init(z_Delta), mpz_init(foo), mpz_init(bar);
440 for (size_t i = 0; i < m.size(); i++)
441 {
442 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
443 tmp4 = new mpz_t(), tmp5 = new mpz_t(), tmp6 = new mpz_t();
444 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4),
445 mpz_init(tmp5), mpz_init(tmp6);
446 d.push_back(tmp), Delta.push_back(tmp2), a.push_back(tmp3),
447 f.push_back(tmp4), f_Delta.push_back(tmp5), lej.push_back(tmp6);
448 }
449
450 // prover: first move
451 // get $x$ from the 'random oracle', i.e. Fiat-Shamir heuristic
452 tmcg_mpz_shash_2vec(x, com->g, m, 3, com->p, com->q, com->h);
453 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
454 // note that we follow the advice of section 2.5 [Gr05] by increasing the
455 // value of $\ell_e$ for the non-interactive protocol version
456 mpz_tdiv_r_2exp(x, x, l_e_nizk);
457
458 // prover: second move
459 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
460 tmcg_mpz_srandomm(r_Delta, com->q); // $r_{\Delta} \gets \mathbb{Z}_q$
461 for (size_t i = 0; i < d.size(); i++)
462 tmcg_mpz_srandomm(d[i], com->q); // $d_1,\ldots,d_n \gets \mathbb{Z}_q$
463 mpz_set(Delta[0], d[0]); // $\Delta_1 := d_1$
464 for (size_t i = 1; i < (Delta.size() - 1); i++)
465 tmcg_mpz_srandomm(Delta[i], com->q); // $\Delta_2,\ldots,\Delta_{n-1}
466 // \gets \mathbb{Z}_q$
467 mpz_set_ui(Delta[Delta.size() - 1], 0L); // $\Delta_n := 0$
468 for (size_t i = 0; i < a.size(); i++)
469 {
470 mpz_set_ui(a[i], 1L);
471 // compute $a_i = \prod_{j=1}^i (m_{\pi(j)} - x)$
472 for (size_t j = 0; j <= i; j++)
473 {
474 mpz_sub(foo, m[pi[j]], x);
475 mpz_mod(foo, foo, com->q);
476 mpz_mul(a[i], a[i], foo);
477 mpz_mod(a[i], a[i], com->q);
478 }
479 }
480 tmcg_mpz_srandomm(r_a, com->q); // $r_a \gets \mathbb{Z}_q$
481 // $c_d = \mathrm{com}_{ck}(d_1,\ldots,d_n;r_d)$
482 com->CommitBy(c_d, r_d, d);
483 for (size_t i = 0; i < lej.size(); i++)
484 {
485 if (i < (lej.size() - 1))
486 {
487 mpz_set(foo, Delta[i]);
488 mpz_neg(foo, foo);
489 mpz_mul(lej[i], foo, d[i + 1]);
490 mpz_mod(lej[i], lej[i], com->q);
491 }
492 else
493 mpz_set_ui(lej[i], 0L);
494 }
495 // $c_{\Delta} = \mathrm{com}_{ck}(-\Delta_1 d_2,\ldots,
496 // -\Delta_{n-1} d_n;r_{\Delta})$
497 com->CommitBy(c_Delta, r_Delta, lej);
498 for (size_t i = 0; i < lej.size(); i++)
499 {
500 if (i < (lej.size() - 1))
501 {
502 mpz_set(foo, Delta[i + 1]);
503 mpz_sub(bar, m[pi[i + 1]], x);
504 mpz_mod(bar, bar, com->q);
505 mpz_mul(bar, bar, Delta[i]);
506 mpz_mod(bar, bar, com->q);
507 mpz_sub(foo, foo, bar);
508 mpz_mod(foo, foo, com->q);
509 mpz_mul(bar, a[i], d[i + 1]);
510 mpz_mod(bar, bar, com->q);
511 mpz_sub(foo, foo, bar);
512 mpz_mod(foo, foo, com->q);
513 mpz_set(lej[i], foo);
514 }
515 else
516 mpz_set_ui(lej[i], 0L);
517 }
518 // $c_a = \mathrm{com}_{ck}(\Delta_2 - (m_{\pi(2)} - x)\Delta_1 - a_1 d_2,
519 // \ldots,\Delta_n - (m_{\pi(n)} - x)\Delta_{n-1}
520 // - a_{n-1} d_n;r_a)$
521 com->CommitBy(c_a, r_a, lej);
522 // send $c_d$, $c_\Delta$, and $c_a$ to the verifier
523 out << c_d << std::endl << c_Delta << std::endl << c_a << std::endl;
524
525 // prover: third move
526 // get $e$ from the 'random oracle', i.e. Fiat-Shamir heuristic
527 tmcg_mpz_shash_2vec(e, com->g, m, 4, x, c_d, c_Delta, c_a);
528 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
529 // note that we follow the advice of section 2.5 [Gr05] by increasing the
530 // value of $\ell_e$ for the non-interactive protocol version
531 mpz_tdiv_r_2exp(e, e, l_e_nizk);
532
533 // prover: fourth move
534 // compute $f_i = e m_{\pi(i)} + d_i$
535 for (size_t i = 0; i < f.size(); i++)
536 {
537 mpz_mul(f[i], e, m[pi[i]]);
538 mpz_mod(f[i], f[i], com->q);
539 mpz_add(f[i], f[i], d[i]);
540 mpz_mod(f[i], f[i], com->q);
541 }
542 // compute $z = e r + r_d$
543 mpz_mul(z, e, r);
544 mpz_mod(z, z, com->q);
545 mpz_add(z, z, r_d);
546 mpz_mod(z, z, com->q);
547 // compute $f_{\Delta_i} = e (\Delta_{i+1} - (m_{\pi(i+1)} - x)\Delta_i
548 // - a_i d_{i+1}) - \Delta_i d_{i+1}$
549 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
550 {
551 mpz_set(foo, Delta[i + 1]);
552 mpz_sub(bar, m[pi[i + 1]], x);
553 mpz_mod(bar, bar, com->q);
554 mpz_mul(bar, bar, Delta[i]);
555 mpz_mod(bar, bar, com->q);
556 mpz_sub(foo, foo, bar);
557 mpz_mod(foo, foo, com->q);
558 mpz_mul(bar, a[i], d[i + 1]);
559 mpz_mod(bar, bar, com->q);
560 mpz_sub(foo, foo, bar);
561 mpz_mod(foo, foo, com->q);
562 mpz_mul(foo, foo, e);
563 mpz_mod(foo, foo, com->q);
564 mpz_mul(bar, Delta[i], d[i + 1]);
565 mpz_mod(bar, bar, com->q);
566 mpz_sub(foo, foo, bar);
567 mpz_mod(foo, foo, com->q);
568 mpz_set(f_Delta[i], foo);
569 }
570 // compute $z_{\Delta} = e r_a + r_{\Delta}$
571 mpz_mul(z_Delta, e, r_a);
572 mpz_mod(z_Delta, z_Delta, com->q);
573 mpz_add(z_Delta, z_Delta, r_Delta);
574 mpz_mod(z_Delta, z_Delta, com->q);
575 for (size_t i = 0; i < f.size(); i++)
576 out << f[i] << std::endl; // send $f_1,\ldots,f_n$ to the verifier
577 out << z << std::endl; // send $z$ to the verifier
578 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
579 out << f_Delta[i] << std::endl; // send $f_{\Delta_1},\ldots,
580 // f_{\Delta_{n-1}}$ to verifier
581 out << z_Delta << std::endl; // send $z_{\Delta}$ to the verifier
582
583 // release
584 mpz_clear(x), mpz_clear(r_d), mpz_clear(r_Delta), mpz_clear(r_a),
585 mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a), mpz_clear(e),
586 mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo), mpz_clear(bar);
587 for (size_t i = 0; i < m.size(); i++)
588 {
589 mpz_clear(d[i]), mpz_clear(Delta[i]), mpz_clear(a[i]),
590 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
591 delete [] d[i], delete [] Delta[i], delete [] a[i], delete [] f[i],
592 delete [] f_Delta[i], delete [] lej[i];
593 }
594 d.clear(), Delta.clear(), a.clear(), f.clear(), f_Delta.clear(),
595 lej.clear();
596 }
597
Verify_interactive(mpz_srcptr c,const std::vector<mpz_ptr> & m,std::istream & in,std::ostream & out,bool optimizations) const598 bool GrothSKC::Verify_interactive
599 (mpz_srcptr c, const std::vector<mpz_ptr> &m,
600 std::istream &in, std::ostream &out, bool optimizations) const
601 {
602 assert(com->g.size() >= m.size());
603 assert(m.size() >= 2);
604
605 // initialize
606 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
607 std::vector<mpz_ptr> f, f_Delta, lej;
608 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
609 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
610 mpz_init(foo2), mpz_init(bar2);
611 for (size_t i = 0; i < m.size(); i++)
612 {
613 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
614 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
615 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
616 }
617 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
618
619 try
620 {
621 // verifier: first move
622 tmcg_mpz_srandomb(x, l_e);
623 out << x << std::endl; // send $x\in\{0,1\}^{\ell_e}$ to the prover
624
625 // verifier: second move
626 in >> c_d >> c_Delta >> c_a; // get $c_d$, $c_{\Delta}$, and $c_a$ from prover
627 if (!in.good())
628 throw false;
629
630 // verifier: third move
631 do
632 {
633 tmcg_mpz_srandomb(e, l_e);
634 }
635 while (!mpz_cmp_ui(e, 0L)); // ensure that $e$ is invertable mod $q$
636 out << e << std::endl; // send $e\in\{0,1\}^{\ell_e}$ to prover
637
638 // verifier: fourth move
639 for (size_t i = 0; i < f.size(); i++)
640 in >> f[i]; // get $f_1,\ldots,f_n$ from the prover
641 in >> z; // get $z$ from the prover
642 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
643 in >> f_Delta[i]; // get $f_{\Delta_1},\ldots,f_{\Delta_{n-1}}$
644 // from the prover
645 in >> z_Delta; // get $z_{\Delta}$ from the prover
646 if (!in.good())
647 throw false;
648
649 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
650 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
651 com->TestMembership(c_Delta)))
652 throw false;
653
654 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
655 if (!(mpz_cmp(z, com->q) < 0))
656 throw false;
657 for (size_t i = 0; i < f.size(); i++)
658 {
659 if (!(mpz_cmp(f[i], com->q) < 0))
660 throw false;
661 }
662
663 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
664 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
665 if (!(mpz_cmp(z_Delta, com->q) < 0))
666 throw false;
667 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
668 {
669 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
670 throw false;
671 }
672
673 if (optimizations)
674 {
675 // randomization technique from section 6,
676 // paragraph 'Batch verification' [Gr05]
677 mpz_t alpha;
678 mpz_init(alpha);
679 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
680 tmcg_mpz_srandomb(alpha, l_e);
681 // compute $(c^e c_d)^{\alpha}$
682 mpz_powm(foo, c, e, com->p);
683 mpz_mul(foo, foo, c_d);
684 mpz_mod(foo, foo, com->p);
685 mpz_powm(foo, foo, alpha, com->p);
686 // compute $c_a^e c_{\Delta}$
687 mpz_powm(bar, c_a, e, com->p);
688 mpz_mul(bar, bar, c_Delta);
689 mpz_mod(bar, bar, com->p);
690 // compute the product
691 mpz_mul(foo, foo, bar);
692 mpz_mod(foo, foo, com->p);
693 // compute the messages for the commitment
694 for (size_t i = 0; i < f.size(); i++)
695 {
696 mpz_mul(lej[i], alpha, f[i]);
697 mpz_mod(lej[i], lej[i], com->q);
698 mpz_add(lej[i], lej[i], f_Delta[i]);
699 mpz_mod(lej[i], lej[i], com->q);
700 }
701 mpz_mul(bar, alpha, z);
702 mpz_mod(bar, bar, com->q);
703 mpz_add(bar, bar, z_Delta);
704 mpz_mod(bar, bar, com->q);
705 mpz_clear(alpha);
706 // check the randomized commitments
707 if (!com->Verify(foo, bar, lej))
708 throw false;
709 }
710 else
711 {
712 // check whether $c^e c_d = \mathrm{com}_{ck}(f_1,\ldots,f_n; z)$
713 mpz_powm(foo, c, e, com->p);
714 mpz_mul(foo, foo, c_d);
715 mpz_mod(foo, foo, com->p);
716 if (!com->Verify(foo, z, f))
717 throw false;
718 // check whether $c_a^e c_{\Delta} = \mathrm{com}_{ck}
719 // (f_{\Delta_1},\ldots,f_{\Delta_{n-1}}; z_{\Delta})$
720 mpz_powm(foo, c_a, e, com->p);
721 mpz_mul(foo, foo, c_Delta);
722 mpz_mod(foo, foo, com->p);
723 if (!com->Verify(foo, z_Delta, f_Delta))
724 throw false;
725 }
726 // check $F_n = e \prod_{i=1}^n (m_i - x)$
727 mpz_mul(foo, e, x);
728 mpz_mod(foo, foo, com->q);
729 assert(mpz_invert(bar, e, com->q));
730 if (!mpz_invert(bar, e, com->q))
731 mpz_set_ui(bar, 0L); // indicates an error
732 mpz_set_ui(foo2, 1L); // foo2 stores $F_{n-1}$
733 for (size_t i = 0; i < f.size(); i++)
734 { // compute left-hand side $F_n$, for $i = 1, \ldots, n$
735 mpz_sub(bar2, f[i], foo);
736 mpz_mod(bar2, bar2, com->q);
737
738 mpz_mul(bar2, bar2, foo2);
739 mpz_mod(bar2, bar2, com->q);
740 if (i > 0)
741 { // add $f_{\Delta_j}$, for $j = 1, \ldots, n-1$
742 mpz_add(bar2, bar2, f_Delta[i - 1]);
743 mpz_mod(bar2, bar2, com->q);
744
745 mpz_mul(bar2, bar2, bar);
746 mpz_mod(bar2, bar2, com->q);
747 }
748 mpz_set(foo2, bar2);
749 }
750 mpz_set_ui(foo2, 1L); // foo2 is right-hand side here
751 for (size_t i = 0; i < m.size(); i++)
752 {
753 mpz_sub(foo, m[i], x);
754 mpz_mod(foo, foo, com->q);
755 mpz_mul(foo2, foo2, foo);
756 mpz_mod(foo2, foo2, com->q);
757 }
758 mpz_mul(foo2, foo2, e);
759 mpz_mod(foo2, foo2, com->q);
760 if (mpz_cmp(foo2, bar2))
761 throw false;
762
763 throw true;
764 }
765 catch (bool return_value)
766 {
767 // release
768 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
769 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
770 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
771 for (size_t i = 0; i < m.size(); i++)
772 {
773 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
774 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
775 }
776 f.clear(), f_Delta.clear(), lej.clear();
777
778 // return
779 return return_value;
780 }
781 }
782
Verify_interactive_publiccoin(mpz_srcptr c,const std::vector<mpz_ptr> & m,JareckiLysyanskayaEDCF * edcf,std::istream & in,std::ostream & out,bool optimizations) const783 bool GrothSKC::Verify_interactive_publiccoin
784 (mpz_srcptr c, const std::vector<mpz_ptr> &m,
785 JareckiLysyanskayaEDCF *edcf,
786 std::istream &in, std::ostream &out, bool optimizations) const
787 {
788 assert(com->g.size() >= m.size());
789 assert(m.size() >= 2);
790
791 // initialize
792 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
793 std::vector<mpz_ptr> f, f_Delta, lej;
794 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
795 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
796 mpz_init(foo2), mpz_init(bar2);
797 for (size_t i = 0; i < m.size(); i++)
798 {
799 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
800 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
801 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
802 }
803 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
804
805 try
806 {
807 // verifier: first move
808 std::stringstream err;
809 if (!edcf->Flip_twoparty(1, x, in, out, err)) // flip coins with prover to get $x$
810 throw false;
811 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
812 mpz_tdiv_r_2exp(x, x, l_e);
813 // verifier: second move
814 in >> c_d >> c_Delta >> c_a; // get $c_d$, $c_{\Delta}$, and $c_a$ from prover
815 if (!in.good())
816 throw false;
817
818 // verifier: third move
819 if (!edcf->Flip_twoparty(1, e, in, out, err)) // flip coins with prover to get $e$
820 throw false;
821 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
822 mpz_tdiv_r_2exp(e, e, l_e);
823
824 // verifier: fourth move
825 for (size_t i = 0; i < f.size(); i++)
826 in >> f[i]; // get $f_1,\ldots,f_n$ from the prover
827 in >> z; // get $z$ from the prover
828 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
829 in >> f_Delta[i]; // get $f_{\Delta_1},\ldots,f_{\Delta_{n-1}}$
830 // from the prover
831 in >> z_Delta; // get $z_{\Delta}$ from the prover
832 if (!in.good())
833 throw false;
834
835 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
836 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
837 com->TestMembership(c_Delta)))
838 throw false;
839
840 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
841 if (!(mpz_cmp(z, com->q) < 0))
842 throw false;
843 for (size_t i = 0; i < f.size(); i++)
844 {
845 if (!(mpz_cmp(f[i], com->q) < 0))
846 throw false;
847 }
848
849 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
850 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
851 if (!(mpz_cmp(z_Delta, com->q) < 0))
852 throw false;
853 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
854 {
855 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
856 throw false;
857 }
858
859 if (optimizations)
860 {
861 // randomization technique from section 6,
862 // paragraph 'Batch verification' [Gr05]
863 mpz_t alpha;
864 mpz_init(alpha);
865 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
866 tmcg_mpz_srandomb(alpha, l_e);
867 // compute $(c^e c_d)^{\alpha}$
868 mpz_powm(foo, c, e, com->p);
869 mpz_mul(foo, foo, c_d);
870 mpz_mod(foo, foo, com->p);
871 mpz_powm(foo, foo, alpha, com->p);
872 // compute $c_a^e c_{\Delta}$
873 mpz_powm(bar, c_a, e, com->p);
874 mpz_mul(bar, bar, c_Delta);
875 mpz_mod(bar, bar, com->p);
876 // compute the product
877 mpz_mul(foo, foo, bar);
878 mpz_mod(foo, foo, com->p);
879 // compute the messages for the commitment
880 for (size_t i = 0; i < f.size(); i++)
881 {
882 mpz_mul(lej[i], alpha, f[i]);
883 mpz_mod(lej[i], lej[i], com->q);
884 mpz_add(lej[i], lej[i], f_Delta[i]);
885 mpz_mod(lej[i], lej[i], com->q);
886 }
887 mpz_mul(bar, alpha, z);
888 mpz_mod(bar, bar, com->q);
889 mpz_add(bar, bar, z_Delta);
890 mpz_mod(bar, bar, com->q);
891 mpz_clear(alpha);
892 // check the randomized commitments
893 if (!com->Verify(foo, bar, lej))
894 throw false;
895 }
896 else
897 {
898 // check whether $c^e c_d = \mathrm{com}_{ck}(f_1,\ldots,f_n; z)$
899 mpz_powm(foo, c, e, com->p);
900 mpz_mul(foo, foo, c_d);
901 mpz_mod(foo, foo, com->p);
902 if (!com->Verify(foo, z, f))
903 throw false;
904 // check whether $c_a^e c_{\Delta} = \mathrm{com}_{ck}
905 // (f_{\Delta_1},\ldots,f_{\Delta_{n-1}}; z_{\Delta})$
906 mpz_powm(foo, c_a, e, com->p);
907 mpz_mul(foo, foo, c_Delta);
908 mpz_mod(foo, foo, com->p);
909 if (!com->Verify(foo, z_Delta, f_Delta))
910 throw false;
911 }
912 // check $F_n = e \prod_{i=1}^n (m_i - x)$
913 mpz_mul(foo, e, x);
914 mpz_mod(foo, foo, com->q);
915 assert(mpz_invert(bar, e, com->q));
916 if (!mpz_invert(bar, e, com->q))
917 mpz_set_ui(bar, 0L); // indicates an error
918 mpz_set_ui(foo2, 1L); // foo2 stores $F_{n-1}$
919 for (size_t i = 0; i < f.size(); i++)
920 { // compute left-hand side $F_n$, for $i = 1, \ldots, n$
921 mpz_sub(bar2, f[i], foo);
922 mpz_mod(bar2, bar2, com->q);
923
924 mpz_mul(bar2, bar2, foo2);
925 mpz_mod(bar2, bar2, com->q);
926 if (i > 0)
927 { // add $f_{\Delta_j}$, for $j = 1, \ldots, n-1$
928 mpz_add(bar2, bar2, f_Delta[i - 1]);
929 mpz_mod(bar2, bar2, com->q);
930
931 mpz_mul(bar2, bar2, bar);
932 mpz_mod(bar2, bar2, com->q);
933 }
934 mpz_set(foo2, bar2);
935 }
936 mpz_set_ui(foo2, 1L); // foo2 is right-hand side here
937 for (size_t i = 0; i < m.size(); i++)
938 {
939 mpz_sub(foo, m[i], x);
940 mpz_mod(foo, foo, com->q);
941 mpz_mul(foo2, foo2, foo);
942 mpz_mod(foo2, foo2, com->q);
943 }
944 mpz_mul(foo2, foo2, e);
945 mpz_mod(foo2, foo2, com->q);
946 if (mpz_cmp(foo2, bar2))
947 throw false;
948
949 throw true;
950 }
951 catch (bool return_value)
952 {
953 // release
954 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
955 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
956 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
957 for (size_t i = 0; i < m.size(); i++)
958 {
959 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
960 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
961 }
962 f.clear(), f_Delta.clear(), lej.clear();
963
964 // return
965 return return_value;
966 }
967 }
968
Verify_noninteractive(mpz_srcptr c,const std::vector<mpz_ptr> & m,std::istream & in,bool optimizations) const969 bool GrothSKC::Verify_noninteractive
970 (mpz_srcptr c, const std::vector<mpz_ptr> &m,
971 std::istream &in, bool optimizations) const
972 {
973 assert(com->g.size() >= m.size());
974 assert(m.size() >= 2);
975
976 // initialize
977 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
978 std::vector<mpz_ptr> f, f_Delta, lej;
979 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
980 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
981 mpz_init(foo2), mpz_init(bar2);
982 for (size_t i = 0; i < m.size(); i++)
983 {
984 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
985 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
986 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
987 }
988 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
989
990 try
991 {
992 // verifier: first move
993 // get $x$ from the 'random oracle', i.e. Fiat-Shamir heuristic
994 tmcg_mpz_shash_2vec(x, com->g, m, 3, com->p, com->q, com->h);
995 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
996 // note that we follow the advice of section 2.5 [Gr05] by increasing the
997 // value of $\ell_e$ for the non-interactive protocol version
998 mpz_tdiv_r_2exp(x, x, l_e_nizk);
999
1000 // verifier: second move
1001 in >> c_d >> c_Delta >> c_a; // get $c_d$, $c_{\Delta}$, and $c_a$ from prover
1002 if (!in.good())
1003 throw false;
1004
1005 // verifier: third move
1006 // get $e$ from the 'random oracle', i.e. Fiat-Shamir heuristic
1007 tmcg_mpz_shash_2vec(e, com->g, m, 4, x, c_d, c_Delta, c_a);
1008 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
1009 // note that we follow the advice of section 2.5 [Gr05] by increasing the
1010 // value of $\ell_e$ for the non-interactive protocol version
1011 mpz_tdiv_r_2exp(e, e, l_e_nizk);
1012
1013 // verifier: fourth move
1014 for (size_t i = 0; i < f.size(); i++)
1015 in >> f[i]; // get $f_1,\ldots,f_n$ from the prover
1016 in >> z; // get $z$ from the prover
1017 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1018 in >> f_Delta[i]; // get $f_{\Delta_1},\ldots,f_{\Delta_{n-1}}$
1019 // from the prover
1020 in >> z_Delta; // get $z_{\Delta}$ from the prover
1021 if (!in.good())
1022 throw false;
1023
1024 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
1025 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
1026 com->TestMembership(c_Delta)))
1027 throw false;
1028
1029 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
1030 if (!(mpz_cmp(z, com->q) < 0))
1031 throw false;
1032 for (size_t i = 0; i < f.size(); i++)
1033 {
1034 if (!(mpz_cmp(f[i], com->q) < 0))
1035 throw false;
1036 }
1037
1038 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
1039 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
1040 if (!(mpz_cmp(z_Delta, com->q) < 0))
1041 throw false;
1042 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1043 {
1044 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
1045 throw false;
1046 }
1047
1048 if (optimizations)
1049 {
1050 // randomization technique from section 6,
1051 // paragraph 'Batch verification' [Gr05]
1052 mpz_t alpha;
1053 mpz_init(alpha);
1054 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
1055 tmcg_mpz_srandomb(alpha, l_e);
1056 // compute $(c^e c_d)^{\alpha}$
1057 mpz_powm(foo, c, e, com->p);
1058 mpz_mul(foo, foo, c_d);
1059 mpz_mod(foo, foo, com->p);
1060 mpz_powm(foo, foo, alpha, com->p);
1061 // compute $c_a^e c_{\Delta}$
1062 mpz_powm(bar, c_a, e, com->p);
1063 mpz_mul(bar, bar, c_Delta);
1064 mpz_mod(bar, bar, com->p);
1065 // compute the product
1066 mpz_mul(foo, foo, bar);
1067 mpz_mod(foo, foo, com->p);
1068 // compute the messages for the commitment
1069 for (size_t i = 0; i < f.size(); i++)
1070 {
1071 mpz_mul(lej[i], alpha, f[i]);
1072 mpz_mod(lej[i], lej[i], com->q);
1073 mpz_add(lej[i], lej[i], f_Delta[i]);
1074 mpz_mod(lej[i], lej[i], com->q);
1075 }
1076 mpz_mul(bar, alpha, z);
1077 mpz_mod(bar, bar, com->q);
1078 mpz_add(bar, bar, z_Delta);
1079 mpz_mod(bar, bar, com->q);
1080 mpz_clear(alpha);
1081 // check the randomized commitments
1082 if (!com->Verify(foo, bar, lej))
1083 throw false;
1084 }
1085 else
1086 {
1087 // check whether $c^e c_d = \mathrm{com}_{ck}(f_1,\ldots,f_n; z)$
1088 mpz_powm(foo, c, e, com->p);
1089 mpz_mul(foo, foo, c_d);
1090 mpz_mod(foo, foo, com->p);
1091 if (!com->Verify(foo, z, f))
1092 throw false;
1093 // check whether $c_a^e c_{\Delta} = \mathrm{com}_{ck}
1094 // (f_{\Delta_1},\ldots,f_{\Delta_{n-1}}; z_{\Delta})$
1095 mpz_powm(foo, c_a, e, com->p);
1096 mpz_mul(foo, foo, c_Delta);
1097 mpz_mod(foo, foo, com->p);
1098 if (!com->Verify(foo, z_Delta, f_Delta))
1099 throw false;
1100 }
1101 // check $F_n = e \prod_{i=1}^n (m_i - x)$
1102 mpz_mul(foo, e, x);
1103 mpz_mod(foo, foo, com->q);
1104 assert(mpz_invert(bar, e, com->q));
1105 if (!mpz_invert(bar, e, com->q))
1106 mpz_set_ui(bar, 0L); // indicates an error
1107 mpz_set_ui(foo2, 1L); // foo2 stores $F_{n-1}$
1108 for (size_t i = 0; i < f.size(); i++)
1109 { // compute left-hand side $F_n$, for $i = 1, \ldots, n$
1110 mpz_sub(bar2, f[i], foo);
1111 mpz_mod(bar2, bar2, com->q);
1112
1113 mpz_mul(bar2, bar2, foo2);
1114 mpz_mod(bar2, bar2, com->q);
1115 if (i > 0)
1116 { // add $f_{\Delta_j}$, for $j = 1, \ldots, n-1$
1117 mpz_add(bar2, bar2, f_Delta[i - 1]);
1118 mpz_mod(bar2, bar2, com->q);
1119
1120 mpz_mul(bar2, bar2, bar);
1121 mpz_mod(bar2, bar2, com->q);
1122 }
1123 mpz_set(foo2, bar2);
1124 }
1125 mpz_set_ui(foo2, 1L); // foo2 is right-hand side here
1126 for (size_t i = 0; i < m.size(); i++)
1127 {
1128 mpz_sub(foo, m[i], x);
1129 mpz_mod(foo, foo, com->q);
1130 mpz_mul(foo2, foo2, foo);
1131 mpz_mod(foo2, foo2, com->q);
1132 }
1133 mpz_mul(foo2, foo2, e);
1134 mpz_mod(foo2, foo2, com->q);
1135 if (mpz_cmp(foo2, bar2))
1136 throw false;
1137
1138 throw true;
1139 }
1140 catch (bool return_value)
1141 {
1142 // release
1143 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
1144 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
1145 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
1146 for (size_t i = 0; i < m.size(); i++)
1147 {
1148 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
1149 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
1150 }
1151 f.clear(), f_Delta.clear(), lej.clear();
1152
1153 // return
1154 return return_value;
1155 }
1156 }
1157
1158 /* This function uses somehow optimized commitments when called from VSSHE. */
Verify_interactive(mpz_srcptr c,const std::vector<mpz_ptr> & f_prime,const std::vector<mpz_ptr> & m,std::istream & in,std::ostream & out,bool optimizations) const1159 bool GrothSKC::Verify_interactive
1160 (mpz_srcptr c, const std::vector<mpz_ptr> &f_prime,
1161 const std::vector<mpz_ptr> &m,
1162 std::istream &in, std::ostream &out, bool optimizations) const
1163 {
1164 assert(com->g.size() >= m.size());
1165 assert(m.size() == f_prime.size());
1166 assert(m.size() >= 2);
1167
1168 // initialize
1169 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
1170 std::vector<mpz_ptr> f, f_Delta, lej;
1171 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
1172 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
1173 mpz_init(foo2), mpz_init(bar2);
1174 for (size_t i = 0; i < m.size(); i++)
1175 {
1176 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
1177 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
1178 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
1179 }
1180 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
1181
1182 try
1183 {
1184 // verifier: first move
1185 tmcg_mpz_srandomb(x, l_e);
1186 out << x << std::endl;
1187
1188 // verifier: second move
1189 in >> c_d >> c_Delta >> c_a;
1190 if (!in.good())
1191 throw false;
1192
1193 // verifier: third move
1194 do
1195 {
1196 tmcg_mpz_srandomb(e, l_e);
1197 }
1198 while (!mpz_cmp_ui(e, 0L)); // ensure that $e$ is invertable mod $q$
1199 out << e << std::endl;
1200
1201 // verifier: fourth move
1202 for (size_t i = 0; i < f.size(); i++)
1203 in >> f[i];
1204 in >> z;
1205 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1206 in >> f_Delta[i];
1207 in >> z_Delta;
1208 if (!in.good())
1209 throw false;
1210
1211 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
1212 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
1213 com->TestMembership(c_Delta)))
1214 throw false;
1215
1216 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
1217 if (!(mpz_cmp(z, com->q) < 0))
1218 throw false;
1219 for (size_t i = 0; i < f.size(); i++)
1220 {
1221 if (!(mpz_cmp(f[i], com->q) < 0))
1222 throw false;
1223 }
1224
1225 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
1226 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
1227 if (!(mpz_cmp(z_Delta, com->q) < 0))
1228 throw false;
1229 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1230 {
1231 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
1232 throw false;
1233 }
1234
1235 if (optimizations)
1236 {
1237 // randomization technique from section 6,
1238 // paragraph 'Batch verification' [Gr05]
1239 mpz_t alpha;
1240 mpz_init(alpha);
1241 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
1242 tmcg_mpz_srandomb(alpha, l_e);
1243 // compute $(c^e c_d)^{\alpha}$
1244 mpz_powm(foo, c, e, com->p);
1245 mpz_mul(foo, foo, c_d);
1246 mpz_mod(foo, foo, com->p);
1247 mpz_powm(foo, foo, alpha, com->p);
1248 // compute $c_a^e c_{\Delta}$
1249 mpz_powm(bar, c_a, e, com->p);
1250 mpz_mul(bar, bar, c_Delta);
1251 mpz_mod(bar, bar, com->p);
1252 // compute the product
1253 mpz_mul(foo, foo, bar);
1254 mpz_mod(foo, foo, com->p);
1255 // compute the messages for the commitment
1256 for (size_t i = 0; i < f.size(); i++)
1257 {
1258 mpz_mul(lej[i], alpha, f[i]);
1259 mpz_mod(lej[i], lej[i], com->q);
1260 mpz_add(lej[i], lej[i], f_Delta[i]);
1261 mpz_mod(lej[i], lej[i], com->q);
1262
1263 // compute $f'_i e \alpha$ (optimized commitment)
1264 mpz_mul(bar, alpha, f_prime[i]);
1265 mpz_mod(bar, bar, com->q);
1266 mpz_mul(bar, bar, e);
1267 mpz_mod(bar, bar, com->q);
1268 mpz_neg(bar, bar);
1269
1270 mpz_add(lej[i], lej[i], bar);
1271 mpz_mod(lej[i], lej[i], com->q);
1272 }
1273 mpz_mul(bar, alpha, z);
1274 mpz_mod(bar, bar, com->q);
1275 mpz_add(bar, bar, z_Delta);
1276 mpz_mod(bar, bar, com->q);
1277 mpz_clear(alpha);
1278 // check the randomized commitments
1279 if (!com->Verify(foo, bar, lej))
1280 throw false;
1281 }
1282 else
1283 {
1284 // check whether $c^e c_d = \mathrm{com}(f''_1, \ldots, f''_n; z)$
1285 mpz_powm(foo, c, e, com->p);
1286 mpz_mul(foo, foo, c_d);
1287 mpz_mod(foo, foo, com->p);
1288 // compute $f''_i = f_i - f'_i e$
1289 for (size_t i = 0; i < f.size(); i++)
1290 {
1291 mpz_mul(lej[i], f_prime[i], e);
1292 mpz_mod(lej[i], lej[i], com->q);
1293 mpz_neg(lej[i], lej[i]);
1294 mpz_add(lej[i], lej[i], f[i]);
1295 mpz_mod(lej[i], lej[i], com->q);
1296 }
1297 if (!com->Verify(foo, z, lej))
1298 throw false;
1299 // check whether $c_a^e c_{\Delta} = \mathrm{com}(f_{\Delta_1},
1300 // \ldots, f_{\Delta_{n-1}}; z_{\Delta})$
1301 mpz_powm(foo, c_a, e, com->p);
1302 mpz_mul(foo, foo, c_Delta);
1303 mpz_mod(foo, foo, com->p);
1304 if (!com->Verify(foo, z_Delta, f_Delta))
1305 throw false;
1306 }
1307
1308 // check $F_n = e \prod_{i=1}^n (m_i - x)$
1309 mpz_mul(foo, e, x);
1310 mpz_mod(foo, foo, com->q);
1311 assert(mpz_invert(bar, e, com->q));
1312 if (!mpz_invert(bar, e, com->q))
1313 mpz_set_ui(bar, 0L); // indicates an error
1314 mpz_set_ui(foo2, 1L);
1315 for (size_t i = 0; i < f.size(); i++)
1316 {
1317 mpz_sub(bar2, f[i], foo);
1318 mpz_mod(bar2, bar2, com->q);
1319
1320 mpz_mul(bar2, bar2, foo2);
1321 mpz_mod(bar2, bar2, com->q);
1322 if (i > 0)
1323 {
1324 mpz_add(bar2, bar2, f_Delta[i - 1]);
1325 mpz_mod(bar2, bar2, com->q);
1326
1327 mpz_mul(bar2, bar2, bar);
1328 mpz_mod(bar2, bar2, com->q);
1329 }
1330 mpz_set(foo2, bar2);
1331 }
1332 mpz_set_ui(foo2, 1L);
1333 for (size_t i = 0; i < m.size(); i++)
1334 {
1335 mpz_sub(foo, m[i], x);
1336 mpz_mod(foo, foo, com->q);
1337 mpz_mul(foo2, foo2, foo);
1338 mpz_mod(foo2, foo2, com->q);
1339 }
1340 mpz_mul(foo2, foo2, e);
1341 mpz_mod(foo2, foo2, com->q);
1342 if (mpz_cmp(foo2, bar2))
1343 throw false;
1344
1345 throw true;
1346 }
1347 catch (bool return_value)
1348 {
1349 // release
1350 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
1351 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
1352 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
1353 for (size_t i = 0; i < m.size(); i++)
1354 {
1355 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
1356 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
1357 }
1358 f.clear(), f_Delta.clear(), lej.clear();
1359
1360 // return
1361 return return_value;
1362 }
1363 }
1364
1365 /* This function uses somehow optimized commitments when called from VSSHE. */
Verify_interactive_publiccoin(mpz_srcptr c,const std::vector<mpz_ptr> & f_prime,const std::vector<mpz_ptr> & m,JareckiLysyanskayaEDCF * edcf,std::istream & in,std::ostream & out,bool optimizations) const1366 bool GrothSKC::Verify_interactive_publiccoin
1367 (mpz_srcptr c, const std::vector<mpz_ptr> &f_prime,
1368 const std::vector<mpz_ptr> &m,
1369 JareckiLysyanskayaEDCF *edcf,
1370 std::istream &in, std::ostream &out, bool optimizations) const
1371 {
1372 assert(com->g.size() >= m.size());
1373 assert(m.size() == f_prime.size());
1374 assert(m.size() >= 2);
1375
1376 // initialize
1377 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
1378 std::vector<mpz_ptr> f, f_Delta, lej;
1379 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
1380 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
1381 mpz_init(foo2), mpz_init(bar2);
1382 for (size_t i = 0; i < m.size(); i++)
1383 {
1384 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
1385 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
1386 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
1387 }
1388 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
1389
1390 try
1391 {
1392 // verifier: first move
1393 std::stringstream err;
1394 if (!edcf->Flip_twoparty(1, x, in, out, err)) // flip coins with prover to get $x$
1395 throw false;
1396 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
1397 mpz_tdiv_r_2exp(x, x, l_e);
1398
1399 // verifier: second move
1400 in >> c_d >> c_Delta >> c_a;
1401 if (!in.good())
1402 throw false;
1403
1404 // verifier: third move
1405 if (!edcf->Flip_twoparty(1, e, in, out, err)) // flip coins with prover to get $e$
1406 throw false;
1407 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
1408 mpz_tdiv_r_2exp(e, e, l_e);
1409
1410 // verifier: fourth move
1411 for (size_t i = 0; i < f.size(); i++)
1412 in >> f[i];
1413 in >> z;
1414 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1415 in >> f_Delta[i];
1416 in >> z_Delta;
1417 if (!in.good())
1418 throw false;
1419
1420 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
1421 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
1422 com->TestMembership(c_Delta)))
1423 throw false;
1424
1425 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
1426 if (!(mpz_cmp(z, com->q) < 0))
1427 throw false;
1428 for (size_t i = 0; i < f.size(); i++)
1429 {
1430 if (!(mpz_cmp(f[i], com->q) < 0))
1431 throw false;
1432 }
1433
1434 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
1435 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
1436 if (!(mpz_cmp(z_Delta, com->q) < 0))
1437 throw false;
1438 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1439 {
1440 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
1441 throw false;
1442 }
1443
1444 if (optimizations)
1445 {
1446 // randomization technique from section 6,
1447 // paragraph 'Batch verification' [Gr05]
1448 mpz_t alpha;
1449 mpz_init(alpha);
1450 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
1451 tmcg_mpz_srandomb(alpha, l_e);
1452 // compute $(c^e c_d)^{\alpha}$
1453 mpz_powm(foo, c, e, com->p);
1454 mpz_mul(foo, foo, c_d);
1455 mpz_mod(foo, foo, com->p);
1456 mpz_powm(foo, foo, alpha, com->p);
1457 // compute $c_a^e c_{\Delta}$
1458 mpz_powm(bar, c_a, e, com->p);
1459 mpz_mul(bar, bar, c_Delta);
1460 mpz_mod(bar, bar, com->p);
1461 // compute the product
1462 mpz_mul(foo, foo, bar);
1463 mpz_mod(foo, foo, com->p);
1464 // compute the messages for the commitment
1465 for (size_t i = 0; i < f.size(); i++)
1466 {
1467 mpz_mul(lej[i], alpha, f[i]);
1468 mpz_mod(lej[i], lej[i], com->q);
1469 mpz_add(lej[i], lej[i], f_Delta[i]);
1470 mpz_mod(lej[i], lej[i], com->q);
1471
1472 // compute $f'_i e \alpha$ (optimized commitment)
1473 mpz_mul(bar, alpha, f_prime[i]);
1474 mpz_mod(bar, bar, com->q);
1475 mpz_mul(bar, bar, e);
1476 mpz_mod(bar, bar, com->q);
1477 mpz_neg(bar, bar);
1478
1479 mpz_add(lej[i], lej[i], bar);
1480 mpz_mod(lej[i], lej[i], com->q);
1481 }
1482 mpz_mul(bar, alpha, z);
1483 mpz_mod(bar, bar, com->q);
1484 mpz_add(bar, bar, z_Delta);
1485 mpz_mod(bar, bar, com->q);
1486 mpz_clear(alpha);
1487 // check the randomized commitments
1488 if (!com->Verify(foo, bar, lej))
1489 throw false;
1490 }
1491 else
1492 {
1493 // check whether $c^e c_d = \mathrm{com}(f''_1, \ldots, f''_n; z)$
1494 mpz_powm(foo, c, e, com->p);
1495 mpz_mul(foo, foo, c_d);
1496 mpz_mod(foo, foo, com->p);
1497 // compute $f''_i = f_i - f'_i e$
1498 for (size_t i = 0; i < f.size(); i++)
1499 {
1500 mpz_mul(lej[i], f_prime[i], e);
1501 mpz_mod(lej[i], lej[i], com->q);
1502 mpz_neg(lej[i], lej[i]);
1503 mpz_add(lej[i], lej[i], f[i]);
1504 mpz_mod(lej[i], lej[i], com->q);
1505 }
1506 if (!com->Verify(foo, z, lej))
1507 throw false;
1508 // check whether $c_a^e c_{\Delta} = \mathrm{com}(f_{\Delta_1},
1509 // \ldots, f_{\Delta_{n-1}}; z_{\Delta})$
1510 mpz_powm(foo, c_a, e, com->p);
1511 mpz_mul(foo, foo, c_Delta);
1512 mpz_mod(foo, foo, com->p);
1513 if (!com->Verify(foo, z_Delta, f_Delta))
1514 throw false;
1515 }
1516
1517 // check $F_n = e \prod_{i=1}^n (m_i - x)$
1518 mpz_mul(foo, e, x);
1519 mpz_mod(foo, foo, com->q);
1520 assert(mpz_invert(bar, e, com->q));
1521 if (!mpz_invert(bar, e, com->q))
1522 mpz_set_ui(bar, 0L); // indicates an error
1523 mpz_set_ui(foo2, 1L);
1524 for (size_t i = 0; i < f.size(); i++)
1525 {
1526 mpz_sub(bar2, f[i], foo);
1527 mpz_mod(bar2, bar2, com->q);
1528
1529 mpz_mul(bar2, bar2, foo2);
1530 mpz_mod(bar2, bar2, com->q);
1531 if (i > 0)
1532 {
1533 mpz_add(bar2, bar2, f_Delta[i - 1]);
1534 mpz_mod(bar2, bar2, com->q);
1535
1536 mpz_mul(bar2, bar2, bar);
1537 mpz_mod(bar2, bar2, com->q);
1538 }
1539 mpz_set(foo2, bar2);
1540 }
1541 mpz_set_ui(foo2, 1L);
1542 for (size_t i = 0; i < m.size(); i++)
1543 {
1544 mpz_sub(foo, m[i], x);
1545 mpz_mod(foo, foo, com->q);
1546 mpz_mul(foo2, foo2, foo);
1547 mpz_mod(foo2, foo2, com->q);
1548 }
1549 mpz_mul(foo2, foo2, e);
1550 mpz_mod(foo2, foo2, com->q);
1551 if (mpz_cmp(foo2, bar2))
1552 throw false;
1553
1554 throw true;
1555 }
1556 catch (bool return_value)
1557 {
1558 // release
1559 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
1560 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
1561 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
1562 for (size_t i = 0; i < m.size(); i++)
1563 {
1564 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
1565 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
1566 }
1567 f.clear(), f_Delta.clear(), lej.clear();
1568
1569 // return
1570 return return_value;
1571 }
1572 }
1573
1574 /* This function uses somehow optimized commitments when called from VSSHE. */
Verify_noninteractive(mpz_srcptr c,const std::vector<mpz_ptr> & f_prime,const std::vector<mpz_ptr> & m,std::istream & in,bool optimizations) const1575 bool GrothSKC::Verify_noninteractive
1576 (mpz_srcptr c, const std::vector<mpz_ptr> &f_prime,
1577 const std::vector<mpz_ptr> &m,
1578 std::istream &in, bool optimizations) const
1579 {
1580 assert(com->g.size() >= m.size());
1581 assert(m.size() == f_prime.size());
1582 assert(m.size() >= 2);
1583
1584 // initialize
1585 mpz_t x, c_d, c_Delta, c_a, e, z, z_Delta, foo, bar, foo2, bar2;
1586 std::vector<mpz_ptr> f, f_Delta, lej;
1587 mpz_init(x), mpz_init(c_d), mpz_init(c_Delta), mpz_init(c_a), mpz_init(e),
1588 mpz_init(z), mpz_init(z_Delta), mpz_init(foo), mpz_init(bar),
1589 mpz_init(foo2), mpz_init(bar2);
1590 for (size_t i = 0; i < m.size(); i++)
1591 {
1592 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
1593 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
1594 f.push_back(tmp), f_Delta.push_back(tmp2), lej.push_back(tmp3);
1595 }
1596 mpz_set_ui(f_Delta[f_Delta.size() - 1], 0L);
1597
1598 try
1599 {
1600 // verifier: first move
1601 // get $x$ from the 'random oracle', i.e. Fiat-Shamir heuristic
1602 tmcg_mpz_shash_2vec(x, com->g, m, 3, com->p, com->q, com->h);
1603 // reduce such that $x$ is from $\{0, 1\}^{\ell_e}$
1604 // note that we follow the advice of section 2.5 [Gr05] by increasing the
1605 // value of $\ell_e$ for the non-interactive protocol version
1606 mpz_tdiv_r_2exp(x, x, l_e_nizk);
1607
1608 // verifier: second move
1609 in >> c_d >> c_Delta >> c_a;
1610 if (!in.good())
1611 throw false;
1612
1613 // verifier: third move
1614 // get $e$ from the 'random oracle', i.e. Fiat-Shamir heuristic
1615 tmcg_mpz_shash_2vec(e, com->g, m, 4, x, c_d, c_Delta, c_a);
1616 // reduce such that $e$ is from $\{0, 1\}^{\ell_e}$
1617 // note that we follow the advice of section 2.5 [Gr05] by increasing the
1618 // value of $\ell_e$ for the non-interactive protocol version
1619 mpz_tdiv_r_2exp(e, e, l_e_nizk);
1620
1621 // verifier: fourth move
1622 for (size_t i = 0; i < f.size(); i++)
1623 in >> f[i];
1624 in >> z;
1625 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1626 in >> f_Delta[i];
1627 in >> z_Delta;
1628 if (!in.good())
1629 throw false;
1630
1631 // check whether $c_d, c_a, c_{\Delta} \in\mathcal{C}_{ck}$
1632 if (!(com->TestMembership(c_d) && com->TestMembership(c_a) &&
1633 com->TestMembership(c_Delta)))
1634 throw false;
1635
1636 // check whether $f_1, \ldots, f_n, z \in\mathbb{Z}_q$
1637 if (!(mpz_cmp(z, com->q) < 0))
1638 throw false;
1639 for (size_t i = 0; i < f.size(); i++)
1640 {
1641 if (!(mpz_cmp(f[i], com->q) < 0))
1642 throw false;
1643 }
1644
1645 // check whether $f_{\Delta_1}, \ldots, f_{\Delta_{n-1}}$
1646 // and $z_{\Delta}$ are from $\mathbb{Z}_q$
1647 if (!(mpz_cmp(z_Delta, com->q) < 0))
1648 throw false;
1649 for (size_t i = 0; i < (f_Delta.size() - 1); i++)
1650 {
1651 if (!(mpz_cmp(f_Delta[i], com->q) < 0))
1652 throw false;
1653 }
1654
1655 if (optimizations)
1656 {
1657 // randomization technique from section 6,
1658 // paragraph 'Batch verification' [Gr05]
1659 mpz_t alpha;
1660 mpz_init(alpha);
1661 // pick $\alpha\in_R\{0, 1\}^{\ell_e}$ at random
1662 tmcg_mpz_srandomb(alpha, l_e_nizk);
1663 // compute $(c^e c_d)^{\alpha}$
1664 mpz_powm(foo, c, e, com->p);
1665 mpz_mul(foo, foo, c_d);
1666 mpz_mod(foo, foo, com->p);
1667 mpz_powm(foo, foo, alpha, com->p);
1668 // compute $c_a^e c_{\Delta}$
1669 mpz_powm(bar, c_a, e, com->p);
1670 mpz_mul(bar, bar, c_Delta);
1671 mpz_mod(bar, bar, com->p);
1672 // compute the product
1673 mpz_mul(foo, foo, bar);
1674 mpz_mod(foo, foo, com->p);
1675 // compute the messages for the commitment
1676 for (size_t i = 0; i < f.size(); i++)
1677 {
1678 mpz_mul(lej[i], alpha, f[i]);
1679 mpz_mod(lej[i], lej[i], com->q);
1680 mpz_add(lej[i], lej[i], f_Delta[i]);
1681 mpz_mod(lej[i], lej[i], com->q);
1682
1683 // compute $f'_i e \alpha$ (optimized commitment)
1684 mpz_mul(bar, alpha, f_prime[i]);
1685 mpz_mod(bar, bar, com->q);
1686 mpz_mul(bar, bar, e);
1687 mpz_mod(bar, bar, com->q);
1688 mpz_neg(bar, bar);
1689
1690 mpz_add(lej[i], lej[i], bar);
1691 mpz_mod(lej[i], lej[i], com->q);
1692 }
1693 mpz_mul(bar, alpha, z);
1694 mpz_mod(bar, bar, com->q);
1695 mpz_add(bar, bar, z_Delta);
1696 mpz_mod(bar, bar, com->q);
1697 mpz_clear(alpha);
1698 // check the randomized commitments
1699 if (!com->Verify(foo, bar, lej))
1700 throw false;
1701 }
1702 else
1703 {
1704 // check whether $c^e c_d = \mathrm{com}(f''_1, \ldots, f''_n; z)$
1705 mpz_powm(foo, c, e, com->p);
1706 mpz_mul(foo, foo, c_d);
1707 mpz_mod(foo, foo, com->p);
1708 // compute $f''_i = f_i - f'_i e$
1709 for (size_t i = 0; i < f.size(); i++)
1710 {
1711 mpz_mul(lej[i], f_prime[i], e);
1712 mpz_mod(lej[i], lej[i], com->q);
1713 mpz_neg(lej[i], lej[i]);
1714 mpz_add(lej[i], lej[i], f[i]);
1715 mpz_mod(lej[i], lej[i], com->q);
1716 }
1717 if (!com->Verify(foo, z, lej))
1718 throw false;
1719 // check whether $c_a^e c_{\Delta} = \mathrm{com}(f_{\Delta_1},
1720 // \ldots, f_{\Delta_{n-1}}; z_{\Delta})$
1721 mpz_powm(foo, c_a, e, com->p);
1722 mpz_mul(foo, foo, c_Delta);
1723 mpz_mod(foo, foo, com->p);
1724 if (!com->Verify(foo, z_Delta, f_Delta))
1725 throw false;
1726 }
1727
1728 // check $F_n = e \prod_{i=1}^n (m_i - x)$
1729 mpz_mul(foo, e, x);
1730 mpz_mod(foo, foo, com->q);
1731 assert(mpz_invert(bar, e, com->q));
1732 if (!mpz_invert(bar, e, com->q))
1733 mpz_set_ui(bar, 0L); // indicates an error
1734 mpz_set_ui(foo2, 1L);
1735 for (size_t i = 0; i < f.size(); i++)
1736 {
1737 mpz_sub(bar2, f[i], foo);
1738 mpz_mod(bar2, bar2, com->q);
1739
1740 mpz_mul(bar2, bar2, foo2);
1741 mpz_mod(bar2, bar2, com->q);
1742 if (i > 0)
1743 {
1744 mpz_add(bar2, bar2, f_Delta[i - 1]);
1745 mpz_mod(bar2, bar2, com->q);
1746
1747 mpz_mul(bar2, bar2, bar);
1748 mpz_mod(bar2, bar2, com->q);
1749 }
1750 mpz_set(foo2, bar2);
1751 }
1752 mpz_set_ui(foo2, 1L);
1753 for (size_t i = 0; i < m.size(); i++)
1754 {
1755 mpz_sub(foo, m[i], x);
1756 mpz_mod(foo, foo, com->q);
1757 mpz_mul(foo2, foo2, foo);
1758 mpz_mod(foo2, foo2, com->q);
1759 }
1760 mpz_mul(foo2, foo2, e);
1761 mpz_mod(foo2, foo2, com->q);
1762 if (mpz_cmp(foo2, bar2))
1763 throw false;
1764
1765 throw true;
1766 }
1767 catch (bool return_value)
1768 {
1769 // release
1770 mpz_clear(x), mpz_clear(c_d), mpz_clear(c_Delta), mpz_clear(c_a),
1771 mpz_clear(e), mpz_clear(z), mpz_clear(z_Delta), mpz_clear(foo),
1772 mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2);
1773 for (size_t i = 0; i < m.size(); i++)
1774 {
1775 mpz_clear(f[i]), mpz_clear(f_Delta[i]), mpz_clear(lej[i]);
1776 delete [] f[i], delete [] f_Delta[i], delete [] lej[i];
1777 }
1778 f.clear(), f_Delta.clear(), lej.clear();
1779
1780 // return
1781 return return_value;
1782 }
1783 }
1784
~GrothSKC()1785 GrothSKC::~GrothSKC
1786 ()
1787 {
1788 delete com;
1789 }
1790
1791 // =============================================================================
1792
GrothVSSHE(size_t n,mpz_srcptr p_ENC,mpz_srcptr q_ENC,mpz_srcptr k_ENC,mpz_srcptr g_ENC,mpz_srcptr h_ENC,unsigned long int ell_e,unsigned long int fieldsize,unsigned long int subgroupsize)1793 GrothVSSHE::GrothVSSHE
1794 (size_t n,
1795 mpz_srcptr p_ENC, mpz_srcptr q_ENC, mpz_srcptr k_ENC,
1796 mpz_srcptr g_ENC, mpz_srcptr h_ENC,
1797 unsigned long int ell_e, unsigned long int fieldsize,
1798 unsigned long int subgroupsize):
1799 l_e(ell_e), l_e_nizk(ell_e * 2L), F_size(fieldsize), G_size(subgroupsize)
1800 {
1801 std::stringstream lej;
1802
1803 mpz_init_set(p, p_ENC), mpz_init_set(q, q_ENC), mpz_init_set(g, g_ENC),
1804 mpz_init_set(h, h_ENC);
1805
1806 // Initialize the commitment scheme and Groth's SKC argument
1807 com = new PedersenCommitmentScheme(n, p_ENC, q_ENC, k_ENC, h_ENC,
1808 fieldsize, subgroupsize);
1809 com->PublishGroup(lej);
1810 skc = new GrothSKC(n, lej, ell_e, fieldsize, subgroupsize);
1811
1812 // Do the precomputation for the fast exponentiation.
1813 fpowm_table_g = new mpz_t[TMCG_MAX_FPOWM_T]();
1814 fpowm_table_h = new mpz_t[TMCG_MAX_FPOWM_T]();
1815 tmcg_mpz_fpowm_init(fpowm_table_g), tmcg_mpz_fpowm_init(fpowm_table_h);
1816 tmcg_mpz_fpowm_precompute(fpowm_table_g, g, p, mpz_sizeinbase(q, 2L));
1817 tmcg_mpz_fpowm_precompute(fpowm_table_h, h, p, mpz_sizeinbase(q, 2L));
1818 }
1819
GrothVSSHE(size_t n,std::istream & in,unsigned long int ell_e,unsigned long int fieldsize,unsigned long int subgroupsize)1820 GrothVSSHE::GrothVSSHE
1821 (size_t n, std::istream& in,
1822 unsigned long int ell_e, unsigned long int fieldsize,
1823 unsigned long int subgroupsize):
1824 l_e(ell_e), l_e_nizk(ell_e * 2L), F_size(fieldsize), G_size(subgroupsize)
1825 {
1826 std::stringstream lej;
1827
1828 mpz_init(p), mpz_init(q), mpz_init(g), mpz_init(h);
1829 in >> p >> q >> g >> h;
1830
1831 // Initialize the commitment scheme and Groth's SKC argument
1832 com = new PedersenCommitmentScheme(n, in, fieldsize, subgroupsize);
1833 com->PublishGroup(lej);
1834 skc = new GrothSKC(n, lej, ell_e, fieldsize, subgroupsize);
1835
1836 // Do the precomputation for the fast exponentiation.
1837 fpowm_table_g = new mpz_t[TMCG_MAX_FPOWM_T]();
1838 fpowm_table_h = new mpz_t[TMCG_MAX_FPOWM_T]();
1839 tmcg_mpz_fpowm_init(fpowm_table_g), tmcg_mpz_fpowm_init(fpowm_table_h);
1840 tmcg_mpz_fpowm_precompute(fpowm_table_g, g, p, mpz_sizeinbase(q, 2L));
1841 tmcg_mpz_fpowm_precompute(fpowm_table_h, h, p, mpz_sizeinbase(q, 2L));
1842 }
1843
SetupGenerators_publiccoin(mpz_srcptr a)1844 void GrothVSSHE::SetupGenerators_publiccoin
1845 (mpz_srcptr a)
1846 {
1847 com->SetupGenerators_publiccoin(a);
1848 // reinitialization of Groth's SKC argument
1849 std::stringstream lej;
1850 com->PublishGroup(lej);
1851 delete skc;
1852 skc = new GrothSKC(com->g.size(), lej, l_e, F_size, G_size);
1853 }
1854
SetupGenerators_publiccoin(const size_t whoami,aiounicast * aiou,CachinKursawePetzoldShoupRBC * rbc,JareckiLysyanskayaEDCF * edcf,std::ostream & err)1855 bool GrothVSSHE::SetupGenerators_publiccoin
1856 (const size_t whoami, aiounicast *aiou,
1857 CachinKursawePetzoldShoupRBC *rbc,
1858 JareckiLysyanskayaEDCF *edcf, std::ostream &err)
1859 {
1860 if (!com->SetupGenerators_publiccoin(whoami, aiou, rbc, edcf, err))
1861 return false;
1862 // reinitialization of Groth's SKC argument
1863 std::stringstream lej;
1864 com->PublishGroup(lej);
1865 delete skc;
1866 skc = new GrothSKC(com->g.size(), lej, l_e, F_size, G_size);
1867
1868 return true;
1869 }
1870
CheckGroup() const1871 bool GrothVSSHE::CheckGroup
1872 () const
1873 {
1874 // check, whether $|q| > 2^{\ell_e}$ (see proof of Theorem 5 [Gr05])
1875 if ((mpz_sizeinbase(q, 2L) < l_e) || (mpz_sizeinbase(q, 2L) < l_e_nizk))
1876 return false;
1877 // the commitment scheme is checked by the SKC class
1878 return skc->CheckGroup();
1879 }
1880
PublishGroup(std::ostream & out) const1881 void GrothVSSHE::PublishGroup
1882 (std::ostream& out) const
1883 {
1884 out << p << std::endl << q << std::endl << g << std::endl << h << std::endl;
1885 com->PublishGroup(out);
1886 }
1887
Prove_interactive(const std::vector<size_t> & pi,const std::vector<mpz_ptr> & R,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,std::istream & in,std::ostream & out) const1888 void GrothVSSHE::Prove_interactive
1889 (const std::vector<size_t>& pi, const std::vector<mpz_ptr>& R,
1890 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
1891 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
1892 std::istream& in, std::ostream& out) const
1893 {
1894 assert(com->g.size() >= pi.size());
1895 assert(pi.size() == R.size());
1896 assert(R.size() == e.size());
1897 assert(e.size() == E.size());
1898 assert(E.size() >= 2);
1899
1900 // initialize
1901 mpz_t r, R_d, r_d, c, c_d, Z, lambda, rho, foo, bar;
1902 std::pair<mpz_ptr, mpz_ptr> E_d;
1903 std::vector<mpz_ptr> d, f, m, t;
1904 E_d.first = new mpz_t(), E_d.second = new mpz_t();
1905 mpz_init(r), mpz_init(R_d), mpz_init(r_d), mpz_init(c), mpz_init(c_d),
1906 mpz_init(Z), mpz_init(lambda), mpz_init(rho), mpz_init(foo),
1907 mpz_init(bar), mpz_init(E_d.first), mpz_init(E_d.second);
1908 for (size_t i = 0; i < e.size(); i++)
1909 {
1910 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
1911 tmp4 = new mpz_t();
1912 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4);
1913 d.push_back(tmp), f.push_back(tmp2), m.push_back(tmp3),
1914 t.push_back(tmp4);
1915 }
1916
1917 // prover: first move
1918 tmcg_mpz_srandomm(r, com->q); // $r \gets \mathbb{Z}_q$
1919 tmcg_mpz_srandomm(R_d, q); // $R_d \gets \mathcal{R}_{pk}
1920 for (size_t i = 0; i < d.size(); i++)
1921 {
1922 // see note in [Gr05] for omitting $\ell_s$ here
1923 tmcg_mpz_srandomm(d[i], com->q);
1924 // store $d_i$ as negative value for convenience
1925 mpz_neg(d[i], d[i]);
1926 }
1927 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
1928 for (size_t i = 0; i < m.size(); i++)
1929 mpz_set_ui(m[i], pi[i] + 1L); // adjust shifted index
1930 com->CommitBy(c, r, m);
1931 com->CommitBy(c_d, r_d, d);
1932 mpz_set_ui(E_d.first, 1L), mpz_set_ui(E_d.second, 1L);
1933 for (size_t i = 0; i < d.size(); i++)
1934 {
1935 // Compute and multiply $E_i^{-d_i}$
1936 tmcg_mpz_spowm(foo, E[i].first, d[i], p);
1937 mpz_mul(E_d.first, E_d.first, foo);
1938 mpz_mod(E_d.first, E_d.first, p);
1939 tmcg_mpz_spowm(bar, E[i].second, d[i], p);
1940 mpz_mul(E_d.second, E_d.second, bar);
1941 mpz_mod(E_d.second, E_d.second, p);
1942 }
1943 // Compute and multiply $E(1;R_d)$
1944 tmcg_mpz_fspowm(fpowm_table_g, foo, g, R_d, p);
1945 mpz_mul(E_d.first, E_d.first, foo);
1946 mpz_mod(E_d.first, E_d.first, p);
1947 tmcg_mpz_fspowm(fpowm_table_h, bar, h, R_d, p);
1948 mpz_mul(E_d.second, E_d.second, bar);
1949 mpz_mod(E_d.second, E_d.second, p);
1950
1951 out << c << std::endl << c_d << std::endl << E_d.first << std::endl <<
1952 E_d.second << std::endl;
1953
1954 // prover: second move
1955 for (size_t i = 0; i < t.size(); i++)
1956 {
1957 in >> t[i];
1958 // reduce such that $t_i$'s are from $\{0, 1\}^{\ell_e}$
1959 mpz_tdiv_r_2exp(t[i], t[i], l_e);
1960 }
1961
1962 // prover: third move
1963 for (size_t i = 0; i < f.size(); i++)
1964 { // compute $f_i = t_{\pi(i)} + d_i$
1965 mpz_neg(f[i], d[i]); // turn $d_i$ into positive values
1966 mpz_add(f[i], f[i], t[pi[i]]);
1967 mpz_mod(f[i], f[i], com->q);
1968 }
1969 mpz_set_ui(Z, 0L);
1970 for (size_t i = 0; i < t.size(); i++)
1971 { // compute $Z = \sum_{i=1}^n t_{\pi(i)} R_i
1972 mpz_mul(foo, t[pi[i]], R[i]);
1973 mpz_mod(foo, foo, q);
1974 mpz_add(Z, Z, foo);
1975 mpz_mod(Z, Z, q);
1976 }
1977 mpz_add(Z, Z, R_d); // and add $R_d$
1978 mpz_mod(Z, Z, q);
1979
1980 for (size_t i = 0; i < f.size(); i++)
1981 out << f[i] << std::endl;
1982 out << Z << std::endl;
1983
1984 // prover: fourth move
1985 in >> lambda;
1986 // reduce such that $\lambda$ is from $\{0, 1\}^{\ell_e}$
1987 mpz_tdiv_r_2exp(lambda, lambda, l_e);
1988
1989 // prover: fifth to seventh move (Shuffle of Known Content)
1990 // $\rho := \lambda r + r_d \bmod q$
1991 mpz_mul(rho, lambda, r);
1992 mpz_mod(rho, rho, com->q);
1993 mpz_add(rho, rho, r_d);
1994 mpz_mod(rho, rho, com->q);
1995 /* This part is not necessary: see personal communication with Jens Groth or the journal version of the paper, because
1996 $c^{\lambda} c_d \mathrm{com}_{ck}(f_1,\ldots,f_n;0) = \mathrm{com}_{ck}(\lambda\pi(1)+t_i,\ldots,\lambda\pi(n)+t_{\pi(n)})$
1997 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
1998 mpz_set_ui(bar, 0L);
1999 com->CommitBy(foo, bar, f, false);
2000 mpz_mul(foo, foo, c_d);
2001 mpz_mod(foo, foo, com->p);
2002 mpz_powm(bar, c, lambda, com->p);
2003 mpz_mul(foo, foo, bar);
2004 mpz_mod(foo, foo, com->p);
2005 */
2006 // SKC messages $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2007 for (size_t i = 0; i < m.size(); i++)
2008 {
2009 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2010 mpz_mul(m[i], m[i], lambda);
2011 mpz_mod(m[i], m[i], com->q);
2012 mpz_add(m[i], m[i], t[i]);
2013 mpz_mod(m[i], m[i], com->q);
2014 }
2015 skc->Prove_interactive(pi, rho, m, in, out);
2016
2017 // release
2018 mpz_clear(r), mpz_clear(R_d), mpz_clear(r_d), mpz_clear(c), mpz_clear(c_d),
2019 mpz_clear(Z), mpz_clear(lambda), mpz_clear(rho), mpz_clear(foo),
2020 mpz_clear(bar);
2021 mpz_clear(E_d.first), mpz_clear(E_d.second);
2022 delete [] E_d.first, delete [] E_d.second;
2023 for (size_t i = 0; i < e.size(); i++)
2024 {
2025 mpz_clear(d[i]), mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2026 delete [] d[i], delete [] f[i], delete [] m[i], delete [] t[i];
2027 }
2028 d.clear(), f.clear(), m.clear(), t.clear();
2029 }
2030
Prove_interactive_publiccoin(const std::vector<size_t> & pi,const std::vector<mpz_ptr> & R,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,JareckiLysyanskayaEDCF * edcf,std::istream & in,std::ostream & out) const2031 void GrothVSSHE::Prove_interactive_publiccoin
2032 (const std::vector<size_t>& pi, const std::vector<mpz_ptr>& R,
2033 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
2034 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
2035 JareckiLysyanskayaEDCF *edcf,
2036 std::istream& in, std::ostream& out) const
2037 {
2038 assert(com->g.size() >= pi.size());
2039 assert(pi.size() == R.size());
2040 assert(R.size() == e.size());
2041 assert(e.size() == E.size());
2042 assert(E.size() >= 2);
2043
2044 // initialize
2045 mpz_t r, R_d, r_d, c, c_d, Z, lambda, rho, foo, bar;
2046 std::pair<mpz_ptr, mpz_ptr> E_d;
2047 std::vector<mpz_ptr> d, f, m, t;
2048 E_d.first = new mpz_t(), E_d.second = new mpz_t();
2049 mpz_init(r), mpz_init(R_d), mpz_init(r_d), mpz_init(c), mpz_init(c_d),
2050 mpz_init(Z), mpz_init(lambda), mpz_init(rho), mpz_init(foo),
2051 mpz_init(bar), mpz_init(E_d.first), mpz_init(E_d.second);
2052 for (size_t i = 0; i < e.size(); i++)
2053 {
2054 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
2055 tmp4 = new mpz_t();
2056 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4);
2057 d.push_back(tmp), f.push_back(tmp2), m.push_back(tmp3),
2058 t.push_back(tmp4);
2059 }
2060
2061 // prover: first move
2062 tmcg_mpz_srandomm(r, com->q); // $r \gets \mathbb{Z}_q$
2063 tmcg_mpz_srandomm(R_d, q); // $R_d \gets \mathcal{R}_{pk}
2064 for (size_t i = 0; i < d.size(); i++)
2065 {
2066 // see note in [Gr05] for omitting $\ell_s$ here
2067 tmcg_mpz_srandomm(d[i], com->q);
2068 // store $d_i$ as negative value for convenience
2069 mpz_neg(d[i], d[i]);
2070 }
2071 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
2072 for (size_t i = 0; i < m.size(); i++)
2073 mpz_set_ui(m[i], pi[i] + 1L); // adjust shifted index
2074 com->CommitBy(c, r, m);
2075 com->CommitBy(c_d, r_d, d);
2076 mpz_set_ui(E_d.first, 1L), mpz_set_ui(E_d.second, 1L);
2077 for (size_t i = 0; i < d.size(); i++)
2078 {
2079 // Compute and multiply $E_i^{-d_i}$
2080 tmcg_mpz_spowm(foo, E[i].first, d[i], p);
2081 mpz_mul(E_d.first, E_d.first, foo);
2082 mpz_mod(E_d.first, E_d.first, p);
2083 tmcg_mpz_spowm(bar, E[i].second, d[i], p);
2084 mpz_mul(E_d.second, E_d.second, bar);
2085 mpz_mod(E_d.second, E_d.second, p);
2086 }
2087 // Compute and multiply $E(1;R_d)$
2088 tmcg_mpz_fspowm(fpowm_table_g, foo, g, R_d, p);
2089 mpz_mul(E_d.first, E_d.first, foo);
2090 mpz_mod(E_d.first, E_d.first, p);
2091 tmcg_mpz_fspowm(fpowm_table_h, bar, h, R_d, p);
2092 mpz_mul(E_d.second, E_d.second, bar);
2093 mpz_mod(E_d.second, E_d.second, p);
2094
2095 out << c << std::endl << c_d << std::endl << E_d.first << std::endl <<
2096 E_d.second << std::endl;
2097
2098 // prover: second move
2099 std::stringstream err;
2100 for (size_t i = 0; i < t.size(); i++)
2101 {
2102 edcf->Flip_twoparty(0, t[i], in, out, err); // flip coins with verifier to get $t_i$
2103 // reduce such that $t_i$'s are from $\{0, 1\}^{\ell_e}$
2104 mpz_tdiv_r_2exp(t[i], t[i], l_e);
2105 }
2106
2107 // prover: third move
2108 for (size_t i = 0; i < f.size(); i++)
2109 { // compute $f_i = t_{\pi(i)} + d_i$
2110 mpz_neg(f[i], d[i]); // turn $d_i$ into positive values
2111 mpz_add(f[i], f[i], t[pi[i]]);
2112 mpz_mod(f[i], f[i], com->q);
2113 }
2114 mpz_set_ui(Z, 0L);
2115 for (size_t i = 0; i < t.size(); i++)
2116 { // compute $Z = \sum_{i=1}^n t_{\pi(i)} R_i
2117 mpz_mul(foo, t[pi[i]], R[i]);
2118 mpz_mod(foo, foo, q);
2119 mpz_add(Z, Z, foo);
2120 mpz_mod(Z, Z, q);
2121 }
2122 mpz_add(Z, Z, R_d); // and add $R_d$
2123 mpz_mod(Z, Z, q);
2124
2125 for (size_t i = 0; i < f.size(); i++)
2126 out << f[i] << std::endl;
2127 out << Z << std::endl;
2128
2129 // prover: fourth move
2130 edcf->Flip_twoparty(0, lambda, in, out, err); // flip coins with verifier to get $\lambda$
2131 // reduce such that $\lambda$ is from $\{0, 1\}^{\ell_e}$
2132 mpz_tdiv_r_2exp(lambda, lambda, l_e);
2133
2134 // prover: fifth to seventh move (Shuffle of Known Content)
2135 // $\rho := \lambda r + r_d \bmod q$
2136 mpz_mul(rho, lambda, r);
2137 mpz_mod(rho, rho, com->q);
2138 mpz_add(rho, rho, r_d);
2139 mpz_mod(rho, rho, com->q);
2140 /* This part is not necessary: see personal communication with Jens Groth or the journal version of the paper, because
2141 $c^{\lambda} c_d \mathrm{com}_{ck}(f_1,\ldots,f_n;0) = \mathrm{com}_{ck}(\lambda\pi(1)+t_i,\ldots,\lambda\pi(n)+t_{\pi(n)})$
2142 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
2143 mpz_set_ui(bar, 0L);
2144 com->CommitBy(foo, bar, f, false);
2145 mpz_mul(foo, foo, c_d);
2146 mpz_mod(foo, foo, com->p);
2147 mpz_powm(bar, c, lambda, com->p);
2148 mpz_mul(foo, foo, bar);
2149 mpz_mod(foo, foo, com->p);
2150 */
2151 // SKC messages $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2152 for (size_t i = 0; i < m.size(); i++)
2153 {
2154 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2155 mpz_mul(m[i], m[i], lambda);
2156 mpz_mod(m[i], m[i], com->q);
2157 mpz_add(m[i], m[i], t[i]);
2158 mpz_mod(m[i], m[i], com->q);
2159 }
2160 skc->Prove_interactive_publiccoin(pi, rho, m, edcf, in, out);
2161
2162 // release
2163 mpz_clear(r), mpz_clear(R_d), mpz_clear(r_d), mpz_clear(c), mpz_clear(c_d),
2164 mpz_clear(Z), mpz_clear(lambda), mpz_clear(rho), mpz_clear(foo),
2165 mpz_clear(bar);
2166 mpz_clear(E_d.first), mpz_clear(E_d.second);
2167 delete [] E_d.first, delete [] E_d.second;
2168 for (size_t i = 0; i < e.size(); i++)
2169 {
2170 mpz_clear(d[i]), mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2171 delete [] d[i], delete [] f[i], delete [] m[i], delete [] t[i];
2172 }
2173 d.clear(), f.clear(), m.clear(), t.clear();
2174 }
2175
Prove_noninteractive(const std::vector<size_t> & pi,const std::vector<mpz_ptr> & R,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,std::ostream & out) const2176 void GrothVSSHE::Prove_noninteractive
2177 (const std::vector<size_t>& pi, const std::vector<mpz_ptr>& R,
2178 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
2179 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
2180 std::ostream& out) const
2181 {
2182 assert(com->g.size() >= pi.size());
2183 assert(pi.size() == R.size());
2184 assert(R.size() == e.size());
2185 assert(e.size() == E.size());
2186 assert(E.size() >= 2);
2187
2188 // initialize
2189 mpz_t r, R_d, r_d, c, c_d, Z, lambda, rho, foo, bar;
2190 std::pair<mpz_ptr, mpz_ptr> E_d;
2191 std::vector<mpz_ptr> d, f, m, t;
2192 E_d.first = new mpz_t(), E_d.second = new mpz_t();
2193 mpz_init(r), mpz_init(R_d), mpz_init(r_d), mpz_init(c), mpz_init(c_d),
2194 mpz_init(Z), mpz_init(lambda), mpz_init(rho), mpz_init(foo),
2195 mpz_init(bar), mpz_init(E_d.first), mpz_init(E_d.second);
2196 for (size_t i = 0; i < e.size(); i++)
2197 {
2198 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t(),
2199 tmp4 = new mpz_t();
2200 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3), mpz_init(tmp4);
2201 d.push_back(tmp), f.push_back(tmp2), m.push_back(tmp3),
2202 t.push_back(tmp4);
2203 }
2204
2205 // prover: first move
2206 tmcg_mpz_srandomm(r, com->q); // $r \gets \mathbb{Z}_q$
2207 tmcg_mpz_srandomm(R_d, q); // $R_d \gets \mathcal{R}_{pk}
2208 for (size_t i = 0; i < d.size(); i++)
2209 {
2210 // see note in [Gr05] for omitting $\ell_s$ here
2211 tmcg_mpz_srandomm(d[i], com->q);
2212 // store $d_i$ as negative value for convenience
2213 mpz_neg(d[i], d[i]);
2214 }
2215 tmcg_mpz_srandomm(r_d, com->q); // $r_d \gets \mathbb{Z}_q$
2216 for (size_t i = 0; i < m.size(); i++)
2217 mpz_set_ui(m[i], pi[i] + 1L); // adjust shifted index
2218 com->CommitBy(c, r, m);
2219 com->CommitBy(c_d, r_d, d);
2220 mpz_set_ui(E_d.first, 1L), mpz_set_ui(E_d.second, 1L);
2221 for (size_t i = 0; i < d.size(); i++)
2222 {
2223 // Compute and multiply $E_i^{-d_i}$
2224 tmcg_mpz_spowm(foo, E[i].first, d[i], p);
2225 mpz_mul(E_d.first, E_d.first, foo);
2226 mpz_mod(E_d.first, E_d.first, p);
2227 tmcg_mpz_spowm(bar, E[i].second, d[i], p);
2228 mpz_mul(E_d.second, E_d.second, bar);
2229 mpz_mod(E_d.second, E_d.second, p);
2230 }
2231 // Compute and multiply $E(1;R_d)$
2232 tmcg_mpz_fspowm(fpowm_table_g, foo, g, R_d, p);
2233 mpz_mul(E_d.first, E_d.first, foo);
2234 mpz_mod(E_d.first, E_d.first, p);
2235 tmcg_mpz_fspowm(fpowm_table_h, bar, h, R_d, p);
2236 mpz_mul(E_d.second, E_d.second, bar);
2237 mpz_mod(E_d.second, E_d.second, p);
2238
2239 out << c << std::endl << c_d << std::endl << E_d.first << std::endl <<
2240 E_d.second << std::endl;
2241
2242 // prover: second move
2243 for (size_t i = 0; i < t.size(); i++)
2244 {
2245 mpz_set_ui(bar, i);
2246 mpz_set_ui(foo, l_e_nizk);
2247 if (i > 0)
2248 mpz_set(foo, t[i-1]); // make a link to previous element
2249 // get $t_i$ from the 'random oracle', i.e. Fiat-Shamir heuristic
2250 tmcg_mpz_shash_2pairvec(t[i], e, E, 14, p, q, g, h, com->p, com->q,
2251 com->g[i], com->h, c, c_d, E_d.first, E_d.second, foo, bar);
2252 // reduce such that $t_i$'s are from $\{0, 1\}^{\ell_e}$
2253 // note that we follow the advice of section 2.5 [Gr05] by increasing the
2254 // value of $\ell_e$ for the non-interactive protocol version
2255 mpz_tdiv_r_2exp(t[i], t[i], l_e_nizk);
2256 }
2257
2258 // prover: third move
2259 for (size_t i = 0; i < f.size(); i++)
2260 { // compute $f_i = t_{\pi(i)} + d_i$
2261 mpz_neg(f[i], d[i]); // turn $d_i$ into positive values
2262 mpz_add(f[i], f[i], t[pi[i]]);
2263 mpz_mod(f[i], f[i], com->q);
2264 }
2265 mpz_set_ui(Z, 0L);
2266 for (size_t i = 0; i < t.size(); i++)
2267 { // compute $Z = \sum_{i=1}^n t_{\pi(i)} R_i
2268 mpz_mul(foo, t[pi[i]], R[i]);
2269 mpz_mod(foo, foo, q);
2270 mpz_add(Z, Z, foo);
2271 mpz_mod(Z, Z, q);
2272 }
2273 mpz_add(Z, Z, R_d); // and add $R_d$
2274 mpz_mod(Z, Z, q);
2275
2276 for (size_t i = 0; i < f.size(); i++)
2277 out << f[i] << std::endl;
2278 out << Z << std::endl;
2279
2280 // prover: fourth move
2281 // get $\lambda$ from the 'random oracle', i.e. Fiat-Shamir heuristic
2282 tmcg_mpz_shash_2pairvec2vec(lambda, e, E, t, f, 5, g, h, com->q, q, Z);
2283 // reduce such that $\lambda$ is from $\{0, 1\}^{\ell_e}$
2284 // note that we follow the advice of section 2.5 [Gr05] by increasing the
2285 // value of $\ell_e$ for the non-interactive protocol version
2286 mpz_tdiv_r_2exp(lambda, lambda, l_e_nizk);
2287
2288 // prover: fifth to seventh move (Shuffle of Known Content)
2289 // $\rho := \lambda r + r_d \bmod q$
2290 mpz_mul(rho, lambda, r);
2291 mpz_mod(rho, rho, com->q);
2292 mpz_add(rho, rho, r_d);
2293 mpz_mod(rho, rho, com->q);
2294 /* This part is not necessary: see personal communication with Jens Groth or the journal version of the paper, because
2295 $c^{\lambda} c_d \mathrm{com}_{ck}(f_1,\ldots,f_n;0) = \mathrm{com}_{ck}(\lambda\pi(1)+t_i,\ldots,\lambda\pi(n)+t_{\pi(n)})$
2296 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
2297 mpz_set_ui(bar, 0L);
2298 com->CommitBy(foo, bar, f, false);
2299 mpz_mul(foo, foo, c_d);
2300 mpz_mod(foo, foo, com->p);
2301 mpz_powm(bar, c, lambda, com->p);
2302 mpz_mul(foo, foo, bar);
2303 mpz_mod(foo, foo, com->p);
2304 */
2305 // SKC messages $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2306 for (size_t i = 0; i < m.size(); i++)
2307 {
2308 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2309 mpz_mul(m[i], m[i], lambda);
2310 mpz_mod(m[i], m[i], com->q);
2311 mpz_add(m[i], m[i], t[i]);
2312 mpz_mod(m[i], m[i], com->q);
2313 }
2314 skc->Prove_noninteractive(pi, rho, m, out);
2315
2316 // release
2317 mpz_clear(r), mpz_clear(R_d), mpz_clear(r_d), mpz_clear(c), mpz_clear(c_d),
2318 mpz_clear(Z), mpz_clear(lambda), mpz_clear(rho), mpz_clear(foo),
2319 mpz_clear(bar);
2320 mpz_clear(E_d.first), mpz_clear(E_d.second);
2321 delete [] E_d.first, delete [] E_d.second;
2322 for (size_t i = 0; i < e.size(); i++)
2323 {
2324 mpz_clear(d[i]), mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2325 delete [] d[i], delete [] f[i], delete [] m[i], delete [] t[i];
2326 }
2327 d.clear(), f.clear(), m.clear(), t.clear();
2328 }
2329
2330
Verify_interactive(const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,std::istream & in,std::ostream & out) const2331 bool GrothVSSHE::Verify_interactive
2332 (const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
2333 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
2334 std::istream& in, std::ostream& out) const
2335 {
2336 assert(com->g.size() >= e.size());
2337 assert(e.size() == E.size());
2338 assert(E.size() >= 2);
2339
2340 // initialize
2341 mpz_t c, c_d, Z, lambda, foo, bar, foo2, bar2, foo3, bar3;
2342 std::pair<mpz_ptr, mpz_ptr> E_d;
2343 std::vector<mpz_ptr> f, m, t;
2344 E_d.first = new mpz_t(), E_d.second = new mpz_t();
2345 mpz_init(c), mpz_init(c_d), mpz_init_set_ui(Z, 0L), mpz_init(lambda),
2346 mpz_init(foo), mpz_init(bar), mpz_init(foo2), mpz_init(bar2),
2347 mpz_init(foo3), mpz_init(bar3);
2348 mpz_init_set_ui(E_d.first, 1L), mpz_init_set_ui(E_d.second, 1L);
2349 for (size_t i = 0; i < e.size(); i++)
2350 {
2351 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
2352 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
2353 f.push_back(tmp), m.push_back(tmp2), t.push_back(tmp3);
2354 }
2355
2356 try
2357 {
2358 // verifier: first move
2359 in >> c >> c_d >> E_d.first >> E_d.second;
2360 if (!in.good())
2361 throw false;
2362
2363 // verifier: second move
2364 for (size_t i = 0; i < t.size(); i++)
2365 {
2366 tmcg_mpz_srandomb(t[i], l_e);
2367 out << t[i] << std::endl;
2368 }
2369
2370 // verifier: third move
2371 for (size_t i = 0; i < f.size(); i++)
2372 in >> f[i];
2373 in >> Z;
2374 if (!in.good())
2375 throw false;
2376
2377 // verifier: fourth move
2378 tmcg_mpz_srandomb(lambda, l_e);
2379 out << lambda << std::endl;
2380
2381 // verifier: fifth to seventh move (Shuffle of Known Content)
2382 // check whether $c, c_d \in\mathcal{C}_{ck}$
2383 if (!(com->TestMembership(c) && com->TestMembership(c_d)))
2384 throw false;
2385
2386 // check whether $E_d\in\mathcal{C}_{pk}$
2387 mpz_powm(foo, E_d.first, q, p);
2388 mpz_powm(bar, E_d.second, q, p);
2389 if (mpz_cmp_ui(foo, 1L) || mpz_cmp_ui(bar, 1L))
2390 throw false;
2391
2392 // check whether $2^{\ell_e} \le f_1,\ldots,f_n < q$
2393 for (size_t i = 0; i < f.size(); i++)
2394 {
2395 if ((mpz_sizeinbase(f[i], 2L) < l_e) ||
2396 (mpz_cmp(f[i], com->q) >= 0))
2397 throw false;
2398 }
2399
2400 // check whether $Z\in\mathcal{R}_{pk}$
2401 if ((mpz_cmp_ui(Z, 0L) <= 0) || (mpz_cmp(Z, q) >= 0))
2402 throw false;
2403
2404 /* This part is not necessary: see personal communication with Jens Groth and the notes above
2405 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
2406 mpz_set_ui(bar, 0L);
2407 com->CommitBy(foo, bar, f, false);
2408 mpz_mul(foo, foo, c_d);
2409 mpz_mod(foo, foo, com->p);
2410 mpz_powm(bar, c, lambda, com->p);
2411 mpz_mul(foo, foo, bar);
2412 mpz_mod(foo, foo, com->p);*/
2413
2414 // SKC (optimized homomorphic) commitment $c^{\lambda} c_d \bmod p$
2415 mpz_powm(foo, c, lambda, com->p);
2416 mpz_mul(foo, foo, c_d);
2417 mpz_mod(foo, foo, com->p);
2418 // SKC messages
2419 // $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2420 for (size_t i = 0; i < m.size(); i++)
2421 {
2422 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2423 mpz_mul(m[i], m[i], lambda);
2424 mpz_mod(m[i], m[i], com->q);
2425 mpz_add(m[i], m[i], t[i]);
2426 mpz_mod(m[i], m[i], com->q);
2427 }
2428
2429 // perform and verify SKC
2430 if (!skc->Verify_interactive(foo, f, m, in, out))
2431 throw false;
2432
2433 // check whether
2434 // $\prod_{i=1}^n e_i^{-t_i} \prod_{i=1}^n E_i^{f_i} E_d = E(1;Z)$
2435 mpz_set_ui(foo2, 1L), mpz_set_ui(bar2, 1L);
2436 for (size_t i = 0; i < e.size(); i++)
2437 {
2438 mpz_powm(foo, e[i].first, t[i], p);
2439 if (!mpz_invert(foo, foo, p))
2440 throw false;
2441 mpz_mul(foo2, foo2, foo);
2442 mpz_mod(foo2, foo2, p);
2443 mpz_powm(bar, e[i].second, t[i], p);
2444 if (!mpz_invert(bar, bar, p))
2445 throw false;
2446 mpz_mul(bar2, bar2, bar);
2447 mpz_mod(bar2, bar2, p);
2448 }
2449 mpz_set_ui(foo3, 1L), mpz_set_ui(bar3, 1L);
2450 for (size_t i = 0; i < E.size(); i++)
2451 {
2452 mpz_powm(foo, E[i].first, f[i], p);
2453 mpz_mul(foo3, foo3, foo);
2454 mpz_mod(foo3, foo3, p);
2455 mpz_powm(bar, E[i].second, f[i], p);
2456 mpz_mul(bar3, bar3, bar);
2457 mpz_mod(bar3, bar3, p);
2458 }
2459 mpz_mul(foo3, foo3, E_d.first);
2460 mpz_mod(foo3, foo3, p);
2461 mpz_mul(bar3, bar3, E_d.second);
2462 mpz_mod(bar3, bar3, p);
2463 mpz_mul(foo3, foo3, foo2); // LHS, first component
2464 mpz_mod(foo3, foo3, p);
2465 mpz_mul(bar3, bar3, bar2); // LHS, second component
2466 mpz_mod(bar3, bar3, p);
2467 tmcg_mpz_fpowm(fpowm_table_g, foo, g, Z, p); // RHS, first component
2468 tmcg_mpz_fpowm(fpowm_table_h, bar, h, Z, p); // RHS, second component
2469 if (mpz_cmp(foo3, foo) || mpz_cmp(bar3, bar))
2470 throw false;
2471
2472 throw true;
2473 }
2474 catch (bool return_value)
2475 {
2476 // release
2477 mpz_clear(c), mpz_clear(c_d), mpz_clear(Z), mpz_clear(lambda),
2478 mpz_clear(foo), mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2),
2479 mpz_clear(foo3), mpz_clear(bar3);
2480 mpz_clear(E_d.first), mpz_clear(E_d.second);
2481 delete [] E_d.first, delete [] E_d.second;
2482 for (size_t i = 0; i < e.size(); i++)
2483 {
2484 mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2485 delete [] f[i], delete [] m[i], delete [] t[i];
2486 }
2487 f.clear(), m.clear(), t.clear();
2488 // return
2489 return return_value;
2490 }
2491 }
2492
Verify_interactive_publiccoin(const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,JareckiLysyanskayaEDCF * edcf,std::istream & in,std::ostream & out) const2493 bool GrothVSSHE::Verify_interactive_publiccoin
2494 (const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
2495 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
2496 JareckiLysyanskayaEDCF *edcf,
2497 std::istream& in, std::ostream& out) const
2498 {
2499 assert(com->g.size() >= e.size());
2500 assert(e.size() == E.size());
2501 assert(E.size() >= 2);
2502
2503 // initialize
2504 mpz_t c, c_d, Z, lambda, foo, bar, foo2, bar2, foo3, bar3;
2505 std::pair<mpz_ptr, mpz_ptr> E_d;
2506 std::vector<mpz_ptr> f, m, t;
2507 E_d.first = new mpz_t(), E_d.second = new mpz_t();
2508 mpz_init(c), mpz_init(c_d), mpz_init_set_ui(Z, 0L), mpz_init(lambda),
2509 mpz_init(foo), mpz_init(bar), mpz_init(foo2), mpz_init(bar2),
2510 mpz_init(foo3), mpz_init(bar3);
2511 mpz_init_set_ui(E_d.first, 1L), mpz_init_set_ui(E_d.second, 1L);
2512 for (size_t i = 0; i < e.size(); i++)
2513 {
2514 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
2515 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
2516 f.push_back(tmp), m.push_back(tmp2), t.push_back(tmp3);
2517 }
2518
2519 try
2520 {
2521 // verifier: first move
2522 in >> c >> c_d >> E_d.first >> E_d.second;
2523 if (!in.good())
2524 throw false;
2525
2526 // verifier: second move
2527 std::stringstream err;
2528 for (size_t i = 0; i < t.size(); i++)
2529 {
2530 if (!edcf->Flip_twoparty(1, t[i], in, out, err)) // flip coins with prover to get $t_i$
2531 throw false;
2532 // reduce such that $t_i$'s are from $\{0, 1\}^{\ell_e}$
2533 mpz_tdiv_r_2exp(t[i], t[i], l_e);
2534 }
2535
2536 // verifier: third move
2537 for (size_t i = 0; i < f.size(); i++)
2538 in >> f[i];
2539 in >> Z;
2540 if (!in.good())
2541 throw false;
2542
2543 // verifier: fourth move
2544 if (!edcf->Flip_twoparty(1, lambda, in, out, err)) // flip coins with prover to get $\lambda$
2545 throw false;
2546 // reduce such that $\lambda$ is from $\{0, 1\}^{\ell_e}$
2547 mpz_tdiv_r_2exp(lambda, lambda, l_e);
2548
2549 // verifier: fifth to seventh move (Shuffle of Known Content)
2550 // check whether $c, c_d \in\mathcal{C}_{ck}$
2551 if (!(com->TestMembership(c) && com->TestMembership(c_d)))
2552 throw false;
2553
2554 // check whether $E_d\in\mathcal{C}_{pk}$
2555 mpz_powm(foo, E_d.first, q, p);
2556 mpz_powm(bar, E_d.second, q, p);
2557 if (mpz_cmp_ui(foo, 1L) || mpz_cmp_ui(bar, 1L))
2558 throw false;
2559
2560 // check whether $2^{\ell_e} \le f_1,\ldots,f_n < q$
2561 for (size_t i = 0; i < f.size(); i++)
2562 {
2563 if ((mpz_sizeinbase(f[i], 2L) < l_e) ||
2564 (mpz_cmp(f[i], com->q) >= 0))
2565 throw false;
2566 }
2567
2568 // check whether $Z\in\mathcal{R}_{pk}$
2569 if ((mpz_cmp_ui(Z, 0L) <= 0) || (mpz_cmp(Z, q) >= 0))
2570 throw false;
2571
2572 /* This part is not necessary: see personal communication with Jens Groth and the notes above
2573 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
2574 mpz_set_ui(bar, 0L);
2575 com->CommitBy(foo, bar, f, false);
2576 mpz_mul(foo, foo, c_d);
2577 mpz_mod(foo, foo, com->p);
2578 mpz_powm(bar, c, lambda, com->p);
2579 mpz_mul(foo, foo, bar);
2580 mpz_mod(foo, foo, com->p);*/
2581
2582 // SKC (optimized homomorphic) commitment $c^{\lambda} c_d \bmod p$
2583 mpz_powm(foo, c, lambda, com->p);
2584 mpz_mul(foo, foo, c_d);
2585 mpz_mod(foo, foo, com->p);
2586 // SKC messages
2587 // $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2588 for (size_t i = 0; i < m.size(); i++)
2589 {
2590 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2591 mpz_mul(m[i], m[i], lambda);
2592 mpz_mod(m[i], m[i], com->q);
2593 mpz_add(m[i], m[i], t[i]);
2594 mpz_mod(m[i], m[i], com->q);
2595 }
2596
2597 // perform and verify SKC
2598 if (!skc->Verify_interactive_publiccoin(foo, f, m, edcf, in, out))
2599 throw false;
2600
2601 // check whether
2602 // $\prod_{i=1}^n e_i^{-t_i} \prod_{i=1}^n E_i^{f_i} E_d = E(1;Z)$
2603 mpz_set_ui(foo2, 1L), mpz_set_ui(bar2, 1L);
2604 for (size_t i = 0; i < e.size(); i++)
2605 {
2606 mpz_powm(foo, e[i].first, t[i], p);
2607 if (!mpz_invert(foo, foo, p))
2608 throw false;
2609 mpz_mul(foo2, foo2, foo);
2610 mpz_mod(foo2, foo2, p);
2611 mpz_powm(bar, e[i].second, t[i], p);
2612 if (!mpz_invert(bar, bar, p))
2613 throw false;
2614 mpz_mul(bar2, bar2, bar);
2615 mpz_mod(bar2, bar2, p);
2616 }
2617 mpz_set_ui(foo3, 1L), mpz_set_ui(bar3, 1L);
2618 for (size_t i = 0; i < E.size(); i++)
2619 {
2620 mpz_powm(foo, E[i].first, f[i], p);
2621 mpz_mul(foo3, foo3, foo);
2622 mpz_mod(foo3, foo3, p);
2623 mpz_powm(bar, E[i].second, f[i], p);
2624 mpz_mul(bar3, bar3, bar);
2625 mpz_mod(bar3, bar3, p);
2626 }
2627 mpz_mul(foo3, foo3, E_d.first);
2628 mpz_mod(foo3, foo3, p);
2629 mpz_mul(bar3, bar3, E_d.second);
2630 mpz_mod(bar3, bar3, p);
2631 mpz_mul(foo3, foo3, foo2); // LHS, first component
2632 mpz_mod(foo3, foo3, p);
2633 mpz_mul(bar3, bar3, bar2); // LHS, second component
2634 mpz_mod(bar3, bar3, p);
2635 tmcg_mpz_fpowm(fpowm_table_g, foo, g, Z, p); // RHS, first component
2636 tmcg_mpz_fpowm(fpowm_table_h, bar, h, Z, p); // RHS, second component
2637 if (mpz_cmp(foo3, foo) || mpz_cmp(bar3, bar))
2638 throw false;
2639
2640 throw true;
2641 }
2642 catch (bool return_value)
2643 {
2644 // release
2645 mpz_clear(c), mpz_clear(c_d), mpz_clear(Z), mpz_clear(lambda),
2646 mpz_clear(foo), mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2),
2647 mpz_clear(foo3), mpz_clear(bar3);
2648 mpz_clear(E_d.first), mpz_clear(E_d.second);
2649 delete [] E_d.first, delete [] E_d.second;
2650 for (size_t i = 0; i < e.size(); i++)
2651 {
2652 mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2653 delete [] f[i], delete [] m[i], delete [] t[i];
2654 }
2655 f.clear(), m.clear(), t.clear();
2656 // return
2657 return return_value;
2658 }
2659 }
2660
Verify_noninteractive(const std::vector<std::pair<mpz_ptr,mpz_ptr>> & e,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & E,std::istream & in) const2661 bool GrothVSSHE::Verify_noninteractive
2662 (const std::vector<std::pair<mpz_ptr, mpz_ptr> >& e,
2663 const std::vector<std::pair<mpz_ptr, mpz_ptr> >& E,
2664 std::istream& in) const
2665 {
2666 assert(com->g.size() >= e.size());
2667 assert(e.size() == E.size());
2668 assert(E.size() >= 2);
2669
2670 // initialize
2671 mpz_t c, c_d, Z, lambda, foo, bar, foo2, bar2, foo3, bar3;
2672 std::pair<mpz_ptr, mpz_ptr> E_d;
2673 std::vector<mpz_ptr> f, m, t;
2674 E_d.first = new mpz_t(), E_d.second = new mpz_t();
2675 mpz_init(c), mpz_init(c_d), mpz_init_set_ui(Z, 0L), mpz_init(lambda),
2676 mpz_init(foo), mpz_init(bar), mpz_init(foo2), mpz_init(bar2),
2677 mpz_init(foo3), mpz_init(bar3);
2678 mpz_init_set_ui(E_d.first, 1L), mpz_init_set_ui(E_d.second, 1L);
2679 for (size_t i = 0; i < e.size(); i++)
2680 {
2681 mpz_ptr tmp = new mpz_t(), tmp2 = new mpz_t(), tmp3 = new mpz_t();
2682 mpz_init(tmp), mpz_init(tmp2), mpz_init(tmp3);
2683 f.push_back(tmp), m.push_back(tmp2), t.push_back(tmp3);
2684 }
2685
2686 try
2687 {
2688 // verifier: first move
2689 in >> c >> c_d >> E_d.first >> E_d.second;
2690 if (!in.good())
2691 throw false;
2692
2693 // verifier: second move
2694 for (size_t i = 0; i < t.size(); i++)
2695 {
2696 mpz_set_ui(bar, i);
2697 mpz_set_ui(foo, l_e_nizk);
2698 if (i > 0)
2699 mpz_set(foo, t[i-1]);
2700 // get $t_i$ from the 'random oracle', i.e. Fiat-Shamir heuristic
2701 tmcg_mpz_shash_2pairvec(t[i], e, E, 14, p, q, g, h, com->p, com->q,
2702 com->g[i], com->h, c, c_d, E_d.first, E_d.second, foo, bar);
2703 // reduce such that $t_i$'s are from $\{0, 1\}^{\ell_e}$
2704 // note that we follow the advice of section 2.5 [Gr05] by increasing the
2705 // value of $\ell_e$ for the non-interactive protocol version
2706 mpz_tdiv_r_2exp(t[i], t[i], l_e_nizk);
2707 }
2708
2709 // verifier: third move
2710 for (size_t i = 0; i < f.size(); i++)
2711 in >> f[i];
2712 in >> Z;
2713 if (!in.good())
2714 throw false;
2715
2716 // verifier: fourth move
2717 // get $\lambda$ from the 'random oracle', i.e. Fiat-Shamir heuristic
2718 tmcg_mpz_shash_2pairvec2vec(lambda, e, E, t, f, 5, g, h, com->q, q, Z);
2719 // reduce such that $\lambda$ is from $\{0, 1\}^{\ell_e}$
2720 // note that we follow the advice of section 2.5 [Gr05] by increasing the
2721 // value of $\ell_e$ for the non-interactive protocol version
2722 mpz_tdiv_r_2exp(lambda, lambda, l_e_nizk);
2723
2724 // verifier: fifth to seventh move (Shuffle of Known Content)
2725 // check whether $c, c_d \in\mathcal{C}_{ck}$
2726 if (!(com->TestMembership(c) && com->TestMembership(c_d)))
2727 throw false;
2728
2729 // check whether $E_d\in\mathcal{C}_{pk}$
2730 mpz_powm(foo, E_d.first, q, p);
2731 mpz_powm(bar, E_d.second, q, p);
2732 if (mpz_cmp_ui(foo, 1L) || mpz_cmp_ui(bar, 1L))
2733 throw false;
2734
2735 // check whether $2^{\ell_e} \le f_1,\ldots,f_n < q$
2736 for (size_t i = 0; i < f.size(); i++)
2737 {
2738 if ((mpz_sizeinbase(f[i], 2L) < l_e_nizk) ||
2739 (mpz_cmp(f[i], com->q) >= 0))
2740 throw false;
2741 }
2742
2743 // check whether $Z\in\mathcal{R}_{pk}$
2744 if ((mpz_cmp_ui(Z, 0L) <= 0) || (mpz_cmp(Z, q) >= 0))
2745 throw false;
2746
2747 /* This part is not necessary: see personal communication with Jens Groth and the notes above
2748 // SKC commitment $c^{\lambda} c_d \mathrm{com}(f_1,\ldots,f_n;0) \bmod p$
2749 mpz_set_ui(bar, 0L);
2750 com->CommitBy(foo, bar, f, false);
2751 mpz_mul(foo, foo, c_d);
2752 mpz_mod(foo, foo, com->p);
2753 mpz_powm(bar, c, lambda, com->p);
2754 mpz_mul(foo, foo, bar);
2755 mpz_mod(foo, foo, com->p);*/
2756
2757 // SKC (optimized homomorphic) commitment $c^{\lambda} c_d \bmod p$
2758 mpz_powm(foo, c, lambda, com->p);
2759 mpz_mul(foo, foo, c_d);
2760 mpz_mod(foo, foo, com->p);
2761 // SKC messages
2762 // $m_i := i \lambda + t_i \bmod q$, for all $i = 1,\ldots, n$
2763 for (size_t i = 0; i < m.size(); i++)
2764 {
2765 mpz_set_ui(m[i], i + 1L); // adjust shifted index
2766 mpz_mul(m[i], m[i], lambda);
2767 mpz_mod(m[i], m[i], com->q);
2768 mpz_add(m[i], m[i], t[i]);
2769 mpz_mod(m[i], m[i], com->q);
2770 }
2771
2772 // perform and verify SKC
2773 if (!skc->Verify_noninteractive(foo, f, m, in))
2774 throw false;
2775
2776 // check whether
2777 // $\prod_{i=1}^n e_i^{-t_i} \prod_{i=1}^n E_i^{f_i} E_d = E(1;Z)$
2778 mpz_set_ui(foo2, 1L), mpz_set_ui(bar2, 1L);
2779 for (size_t i = 0; i < e.size(); i++)
2780 {
2781 mpz_powm(foo, e[i].first, t[i], p);
2782 if (!mpz_invert(foo, foo, p))
2783 throw false;
2784 mpz_mul(foo2, foo2, foo);
2785 mpz_mod(foo2, foo2, p);
2786 mpz_powm(bar, e[i].second, t[i], p);
2787 if (!mpz_invert(bar, bar, p))
2788 throw false;
2789 mpz_mul(bar2, bar2, bar);
2790 mpz_mod(bar2, bar2, p);
2791 }
2792 mpz_set_ui(foo3, 1L), mpz_set_ui(bar3, 1L);
2793 for (size_t i = 0; i < E.size(); i++)
2794 {
2795 mpz_powm(foo, E[i].first, f[i], p);
2796 mpz_mul(foo3, foo3, foo);
2797 mpz_mod(foo3, foo3, p);
2798 mpz_powm(bar, E[i].second, f[i], p);
2799 mpz_mul(bar3, bar3, bar);
2800 mpz_mod(bar3, bar3, p);
2801 }
2802 mpz_mul(foo3, foo3, E_d.first);
2803 mpz_mod(foo3, foo3, p);
2804 mpz_mul(bar3, bar3, E_d.second);
2805 mpz_mod(bar3, bar3, p);
2806 mpz_mul(foo3, foo3, foo2); // LHS, first component
2807 mpz_mod(foo3, foo3, p);
2808 mpz_mul(bar3, bar3, bar2); // LHS, second component
2809 mpz_mod(bar3, bar3, p);
2810 tmcg_mpz_fpowm(fpowm_table_g, foo, g, Z, p); // RHS, first component
2811 tmcg_mpz_fpowm(fpowm_table_h, bar, h, Z, p); // RHS, second component
2812 if (mpz_cmp(foo3, foo) || mpz_cmp(bar3, bar))
2813 throw false;
2814
2815 throw true;
2816 }
2817 catch (bool return_value)
2818 {
2819 // release
2820 mpz_clear(c), mpz_clear(c_d), mpz_clear(Z), mpz_clear(lambda),
2821 mpz_clear(foo), mpz_clear(bar), mpz_clear(foo2), mpz_clear(bar2),
2822 mpz_clear(foo3), mpz_clear(bar3);
2823 mpz_clear(E_d.first), mpz_clear(E_d.second);
2824 delete [] E_d.first, delete [] E_d.second;
2825 for (size_t i = 0; i < e.size(); i++)
2826 {
2827 mpz_clear(f[i]), mpz_clear(m[i]), mpz_clear(t[i]);
2828 delete [] f[i], delete [] m[i], delete [] t[i];
2829 }
2830 f.clear(), m.clear(), t.clear();
2831 // return
2832 return return_value;
2833 }
2834 }
2835
~GrothVSSHE()2836 GrothVSSHE::~GrothVSSHE
2837 ()
2838 {
2839 mpz_clear(p), mpz_clear(q), mpz_clear(g), mpz_clear(h);
2840 delete com;
2841 delete skc;
2842
2843 tmcg_mpz_fpowm_done(fpowm_table_g), tmcg_mpz_fpowm_done(fpowm_table_h);
2844 delete [] fpowm_table_g, delete [] fpowm_table_h;
2845 }
2846