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