1 /*******************************************************************************
2    This file is part of LibTMCG.
3 
4  Copyright (C) 2004, 2005, 2016, 2017, 2018  Heiko Stamer <HeikoStamer@gmx.net>
5 
6      [BR95] Mihir Bellare, Phillip Rogaway: 'Random Oracles are Practical:
7              A Paradigm for Designing Efficient Protocols',
8             Proceedings First Annual Conference on Computer and
9              Communications Security, ACM, 1993.
10 
11    LibTMCG is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15 
16    LibTMCG is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19    GNU General Public License for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with LibTMCG; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24 *******************************************************************************/
25 
26 // include headers
27 #ifdef HAVE_CONFIG_H
28 	#include "libTMCG_config.h"
29 #endif
30 #include "mpz_shash.hh"
31 
32 // emulate SHA-3 by public domain code from https://github.com/brainhub/SHA3IUF
33 #include "sha3.c"
sha3(unsigned char * output,const unsigned char * input,const size_t size,int algo)34 void sha3
35 	(unsigned char *output,
36 	const unsigned char *input, const size_t size, int algo)
37 {
38 	sha3_context c;
39 	const uint8_t *hash;
40 
41 	switch (algo)
42 	{
43 		case GCRY_MD_SHA256:
44 			gcry_md_hash_buffer(algo, output, input, size);
45 			break;
46 		case 313: // SHA-3 256 bit output
47 			sha3_Init256(&c);
48 			sha3_Update(&c, input, size);
49 			hash = sha3_Finalize(&c);
50 			memcpy(output, hash, 32);
51 			break;
52 		case 314: // SHA-3 384 bit output
53 			sha3_Init384(&c);
54 			sha3_Update(&c, input, size);
55 			hash = sha3_Finalize(&c);
56 			memcpy(output, hash, 48);
57 			break;
58 		case 315: // SHA-3 512 bit output
59 			sha3_Init512(&c);
60 			sha3_Update(&c, input, size);
61 			hash = sha3_Finalize(&c);
62 			memcpy(output, hash, 64);
63 			break;
64 		default:
65 			break;
66 	}
67 }
68 
69 /* hash function h() (assumption: collision-resistant cryptographic hash) */
tmcg_h(unsigned char * output,const unsigned char * input,const size_t size,int algo)70 void tmcg_h
71 	(unsigned char *output,
72 	const unsigned char *input, const size_t size, int algo)
73 {
74 	gcry_md_hash_buffer(algo, output, input, size);
75 }
76 
77 /* hash function g() (The design is based on ideas from [BR95].) */
tmcg_g(unsigned char * output,const size_t osize,const unsigned char * input,const size_t isize)78 void tmcg_g
79 	(unsigned char *output, const size_t osize,
80 	const unsigned char *input, const size_t isize)
81 {
82 	bool emulate = false; // emulate GCRY_MD_SHA3_256 (gcry algo constant 313)
83 	int second_algo = (TMCG_GCRY_MD_ALGO != 313) ? 313 : GCRY_MD_SHA256;
84 	if (gcry_md_test_algo(second_algo)) // check for SHA3-256 in libgcrypt
85 		emulate = true;
86 	size_t mdsize = gcry_md_get_algo_dlen(TMCG_GCRY_MD_ALGO);
87 	size_t mdsize2 = emulate ? 32 : gcry_md_get_algo_dlen(second_algo);
88 	// hopefully, size of truncation does not match the border
89 	// of chaining variables in the compression function of h
90 	size_t usesize = (mdsize / 4) + 1;
91 	size_t usesize2 = (mdsize2 / 4) + 1;
92 	size_t times = (osize / usesize) + 1;
93 	size_t times2 = (osize / usesize2) + 1;
94 	unsigned char *out = new unsigned char[(times + 1) * mdsize];
95 	unsigned char *out2 = new unsigned char[(times2 + 1) * mdsize2];
96 	memset(out, 0, (times + 1) * mdsize);
97 	memset(out2, 0, (times2 + 1) * mdsize2);
98 	for (size_t i = 0; i < times; i++)
99 	{
100 		// construct the expanded input y = x || libTMCG<i> || x
101 		size_t dsize = 9 + (2 * isize);
102 		unsigned char *data = new unsigned char[dsize + 1];
103 		memcpy(data, input, isize);
104 		snprintf((char*)data + isize, 10, "libTMCG%02x", (uint8_t)i);
105 		memcpy(data + isize + 9, input, isize);
106 
107 		// using h(y) "in some nonstandard way" with "output truncated" [BR95]
108 		tmcg_h(out + (i * (usesize + 2)), data, dsize);
109 		if (emulate)
110 			sha3(out2 + (i * (usesize2 + 2)), data, dsize, second_algo);
111 		else
112 			tmcg_h(out2 + (i * (usesize2 + 2)), data, dsize, second_algo);
113 		delete [] data;
114 
115 		// using h on parts of the whole result again with "output truncated"
116 		size_t psize2 = ((i + 1) * (mdsize2 - 1));
117 		tmcg_h(out + (i * usesize), out, ((i + 1) * (mdsize - 1)));
118 		if (emulate)
119 			sha3(out2 + (i * usesize2), out2, psize2, second_algo);
120 		else
121 			tmcg_h(out2 + (i * usesize2), out2, psize2, second_algo);
122 	}
123 	// final output is the XOR of both results
124 	for (size_t i = 0; i < osize; i++)
125 		output[i] = out[i] ^ out2[i];
126 	delete [] out;
127 	delete [] out2;
128 }
129 
tmcg_mpz_shash_len()130 size_t tmcg_mpz_shash_len
131 	()
132 {
133 	return gcry_md_get_algo_dlen(TMCG_GCRY_MD_ALGO);
134 }
135 
tmcg_mpz_fhash_len(int algo)136 size_t tmcg_mpz_fhash_len
137 	(int algo)
138 {
139 	return gcry_md_get_algo_dlen(algo);
140 }
141 
tmcg_mpz_fhash(mpz_ptr r,int algo,mpz_srcptr input)142 void tmcg_mpz_fhash
143 	(mpz_ptr r, int algo, mpz_srcptr input)
144 {
145 	size_t input_size = (mpz_sizeinbase(input, 2UL) + 7) / 8;
146 	size_t hash_size = tmcg_mpz_fhash_len(algo);
147 	unsigned char *buffer = new unsigned char[input_size];
148 	unsigned char *digest = new unsigned char[hash_size];
149 	char *hex_digest = new char[(2 * hash_size) + 1];
150 
151 	/* construct and hash the input with default hash function */
152 	memset(buffer, 0, input_size);
153 	mpz_export(buffer, NULL, 1, 1, 1, 0, input);
154 	tmcg_h(digest, buffer, input_size, algo);
155 
156 	/* convert the digest to a hexadecimal encoded string */
157 	for (size_t i = 0; i < hash_size; i++)
158 		snprintf(hex_digest + (2 * i), 3, "%02x", digest[i]);
159 
160 	/* convert the hexadecimal encoded string to an mpz-integer */
161 	mpz_set_str(r, hex_digest, 16);
162 
163 	/* release buffers */
164 	delete [] buffer, delete [] digest, delete [] hex_digest;
165 }
166 
tmcg_mpz_fhash_ggen(mpz_ptr r,int algo,mpz_srcptr input1,const std::string & input2,mpz_srcptr input3,mpz_srcptr input4)167 void tmcg_mpz_fhash_ggen
168 	(mpz_ptr r, int algo,
169 	mpz_srcptr input1, const std::string &input2,
170 	mpz_srcptr input3, mpz_srcptr input4)
171 {
172 	size_t input1_size = ((mpz_sizeinbase(input1, 2UL) + 7) / 8);
173 	size_t input12_size = input1_size + input2.length();
174 	size_t input3_size = ((mpz_sizeinbase(input3, 2UL) + 7) / 8);
175 	size_t input123_size = input12_size + input3_size;
176 	size_t input4_size = ((mpz_sizeinbase(input4, 2UL) + 7) / 8);
177 	size_t input_size = input123_size + input4_size;
178 	size_t hash_size = tmcg_mpz_fhash_len(algo);
179 	unsigned char *buffer = new unsigned char[input_size];
180 	unsigned char *digest = new unsigned char[hash_size];
181 	char *hex_digest = new char[(2 * hash_size) + 1];
182 
183 	/* construct and hash the input with default hash function */
184 	memset(buffer, 0, input_size);
185 	mpz_export(buffer, NULL, 1, 1, 1, 0, input1);
186 	memcpy(buffer + input1_size, input2.c_str(), input2.length());
187 	mpz_export(buffer + input12_size, NULL, 1, 1, 1, 0, input3);
188 	mpz_export(buffer + input123_size, NULL, 1, 1, 1, 0, input4);
189 	tmcg_h(digest, buffer, input_size, algo);
190 
191 	/* convert the digest to a hexadecimal encoded string */
192 	for (size_t i = 0; i < hash_size; i++)
193 		snprintf(hex_digest + (2 * i), 3, "%02x", digest[i]);
194 
195 	/* convert the hexadecimal encoded string to an mpz-integer */
196 	mpz_set_str(r, hex_digest, 16);
197 
198 	/* release buffers */
199 	delete [] buffer, delete [] digest, delete [] hex_digest;
200 }
201 
tmcg_mpz_shash(mpz_ptr r,const std::string & input)202 void tmcg_mpz_shash
203 	(mpz_ptr r, const std::string &input)
204 {
205 	size_t hash_size = tmcg_mpz_shash_len();
206 	unsigned char *digest = new unsigned char[hash_size];
207 	char *hex_digest = new char[(2 * hash_size) + 1];
208 
209 	/* hash the input */
210 	tmcg_g(digest, hash_size, (unsigned char*)input.c_str(), input.length());
211 
212 	/* convert the digest to a hexadecimal encoded string */
213 	for (size_t i = 0; i < hash_size; i++)
214 		snprintf(hex_digest + (2 * i), 3, "%02x", digest[i]);
215 
216 	/* convert the hexadecimal encoded string to an mpz-integer */
217 	mpz_set_str(r, hex_digest, 16);
218 
219 	/* release buffers */
220 	delete [] digest, delete [] hex_digest;
221 }
222 
223 /* Hashing of the public inputs (aka Fiat-Shamir heuristic) with g(),
224    e.g. to make some proofs of knowledge (PoK) non-interactive (NIZK). */
tmcg_mpz_shash(mpz_ptr r,size_t n,...)225 void tmcg_mpz_shash
226 	(mpz_ptr r, size_t n, ...)
227 {
228 	va_list ap;
229 	mpz_srcptr a;
230 	std::string acc;
231 
232 	/* concatenate all the arguments */
233 	va_start(ap, n);
234 	for (size_t i = 0; i < n; i++)
235 	{
236 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
237 		size_t vlen = (2 * mpz_sizeinbase(a, 16)) + 1;
238 		char *vtmp = new char[vlen];
239 		acc += mpz_get_str(vtmp, 16, a);
240 		acc += "|";
241 		delete [] vtmp;
242 	}
243 	va_end(ap);
244 
245 	/* hash arguments */
246 	tmcg_mpz_shash(r, acc);
247 }
248 
tmcg_mpz_shash_1vec(mpz_ptr r,const std::vector<mpz_ptr> & v,size_t n,...)249 void tmcg_mpz_shash_1vec
250 	(mpz_ptr r, const std::vector<mpz_ptr>& v, size_t n, ...)
251 {
252 	va_list ap;
253 	mpz_srcptr a;
254 	std::string acc;
255 
256 	/* concatenate the elements of the vector */
257 	for (size_t i = 0; i < v.size(); i++)
258 	{
259 		char *vtmp = new char[(2 * mpz_sizeinbase(v[i], 16)) + 1];
260 		acc += mpz_get_str(vtmp, 16, v[i]);
261 		acc += "|";
262 		delete [] vtmp;
263 	}
264 
265 	/* concatenate all the remaining arguments */
266 	va_start(ap, n);
267 	for (size_t i = 0; i < n; i++)
268 	{
269 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
270 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
271 		acc += mpz_get_str(vtmp, 16, a);
272 		acc += "|";
273 		delete [] vtmp;
274 	}
275 	va_end(ap);
276 
277 	/* hash arguments */
278 	tmcg_mpz_shash(r, acc);
279 }
280 
tmcg_mpz_shash_2vec(mpz_ptr r,const std::vector<mpz_ptr> & v,const std::vector<mpz_ptr> & w,size_t n,...)281 void tmcg_mpz_shash_2vec
282 	(mpz_ptr r, const std::vector<mpz_ptr>& v,
283 	const std::vector<mpz_ptr>& w, size_t n, ...)
284 {
285 	va_list ap;
286 	mpz_srcptr a;
287 	std::string acc;
288 
289 	/* concatenate the elements of the vectors */
290 	for (size_t i = 0; i < v.size(); i++)
291 	{
292 		char *vtmp = new char[(2 * mpz_sizeinbase(v[i], 16)) + 1];
293 		acc += mpz_get_str(vtmp, 16, v[i]);
294 		acc += "|";
295 		delete [] vtmp;
296 	}
297 	for (size_t i = 0; i < w.size(); i++)
298 	{
299 		char *vtmp = new char[(2 * mpz_sizeinbase(w[i], 16)) + 1];
300 		acc += mpz_get_str(vtmp, 16, w[i]);
301 		acc += "|";
302 		delete [] vtmp;
303 	}
304 
305 	/* concatenate all the remaining arguments */
306 	va_start(ap, n);
307 	for (size_t i = 0; i < n; i++)
308 	{
309 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
310 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
311 		acc += mpz_get_str(vtmp, 16, a);
312 		acc += "|";
313 		delete [] vtmp;
314 	}
315 	va_end(ap);
316 
317 	/* hash arguments */
318 	tmcg_mpz_shash(r, acc);
319 }
320 
tmcg_mpz_shash_4vec(mpz_ptr r,const std::vector<mpz_ptr> & v,const std::vector<mpz_ptr> & w,const std::vector<mpz_ptr> & x,const std::vector<mpz_ptr> & y,size_t n,...)321 void tmcg_mpz_shash_4vec
322 	(mpz_ptr r, const std::vector<mpz_ptr>& v,
323 	const std::vector<mpz_ptr>& w, const std::vector<mpz_ptr>& x,
324 	const std::vector<mpz_ptr>& y, size_t n, ...)
325 {
326 	va_list ap;
327 	mpz_srcptr a;
328 	std::string acc;
329 
330 	/* concatenate the elements of the vectors */
331 	for (size_t i = 0; i < v.size(); i++)
332 	{
333 		char *vtmp = new char[(2 * mpz_sizeinbase(v[i], 16)) + 1];
334 		acc += mpz_get_str(vtmp, 16, v[i]);
335 		acc += "|";
336 		delete [] vtmp;
337 	}
338 	for (size_t i = 0; i < w.size(); i++)
339 	{
340 		char *vtmp = new char[(2 * mpz_sizeinbase(w[i], 16)) + 1];
341 		acc += mpz_get_str(vtmp, 16, w[i]);
342 		acc += "|";
343 		delete [] vtmp;
344 	}
345 	for (size_t i = 0; i < x.size(); i++)
346 	{
347 		char *vtmp = new char[(2 * mpz_sizeinbase(x[i], 16)) + 1];
348 		acc += mpz_get_str(vtmp, 16, x[i]);
349 		acc += "|";
350 		delete [] vtmp;
351 	}
352 	for (size_t i = 0; i < y.size(); i++)
353 	{
354 		char *vtmp = new char[(2 * mpz_sizeinbase(y[i], 16)) + 1];
355 		acc += mpz_get_str(vtmp, 16, y[i]);
356 		acc += "|";
357 		delete [] vtmp;
358 	}
359 
360 	/* concatenate all the remaining arguments */
361 	va_start(ap, n);
362 	for (size_t i = 0; i < n; i++)
363 	{
364 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
365 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
366 		acc += mpz_get_str(vtmp, 16, a);
367 		acc += "|";
368 		delete [] vtmp;
369 	}
370 	va_end(ap);
371 
372 	/* hash arguments */
373 	tmcg_mpz_shash(r, acc);
374 }
375 
tmcg_mpz_shash_2pairvec(mpz_ptr r,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & vp,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & wp,size_t n,...)376 void tmcg_mpz_shash_2pairvec
377 	(mpz_ptr r, const std::vector<std::pair<mpz_ptr, mpz_ptr> >& vp,
378 	const std::vector<std::pair<mpz_ptr, mpz_ptr> >& wp, size_t n, ...)
379 {
380 	va_list ap;
381 	mpz_srcptr a;
382 	std::string acc;
383 
384 	/* concatenate the elements of the pair vectors */
385 	for (size_t i = 0; i < vp.size(); i++)
386 	{
387 		char *vtmp = new char[(2 * mpz_sizeinbase(vp[i].first, 16)) + 1];
388 		acc += mpz_get_str(vtmp, 16, vp[i].first);
389 		acc += "|";
390 		delete [] vtmp;
391 		vtmp = new char[(2 * mpz_sizeinbase(vp[i].second, 16)) + 1];
392 		acc += mpz_get_str(vtmp, 16, vp[i].second);
393 		acc += "|";
394 		delete [] vtmp;
395 
396 	}
397 	for (size_t i = 0; i < wp.size(); i++)
398 	{
399 		char *vtmp = new char[(2 * mpz_sizeinbase(wp[i].first, 16)) + 1];
400 		acc += mpz_get_str(vtmp, 16, wp[i].first);
401 		acc += "|";
402 		delete [] vtmp;
403 		vtmp = new char[(2 * mpz_sizeinbase(wp[i].second, 16)) + 1];
404 		acc += mpz_get_str(vtmp, 16, wp[i].second);
405 		acc += "|";
406 		delete [] vtmp;
407 	}
408 
409 	/* concatenate all the remaining arguments */
410 	va_start(ap, n);
411 	for (size_t i = 0; i < n; i++)
412 	{
413 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
414 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
415 		acc += mpz_get_str(vtmp, 16, a);
416 		acc += "|";
417 		delete [] vtmp;
418 	}
419 	va_end(ap);
420 
421 	/* hash arguments */
422 	tmcg_mpz_shash(r, acc);
423 }
424 
tmcg_mpz_shash_2pairvec2vec(mpz_ptr r,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & vp,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & wp,const std::vector<mpz_ptr> & v,const std::vector<mpz_ptr> & w,size_t n,...)425 void tmcg_mpz_shash_2pairvec2vec
426 	(mpz_ptr r, const std::vector<std::pair<mpz_ptr, mpz_ptr> >& vp,
427 	const std::vector<std::pair<mpz_ptr, mpz_ptr> >& wp,
428 	const std::vector<mpz_ptr>& v, const std::vector<mpz_ptr>& w,
429 	size_t n, ...)
430 {
431 	va_list ap;
432 	mpz_srcptr a;
433 	std::string acc;
434 
435 	/* concatenate the elements of the pair vectors */
436 	for (size_t i = 0; i < vp.size(); i++)
437 	{
438 		char *vtmp = new char[(2 * mpz_sizeinbase(vp[i].first, 16)) + 1];
439 		acc += mpz_get_str(vtmp, 16, vp[i].first);
440 		acc += "|";
441 		delete [] vtmp;
442 		vtmp = new char[(2 * mpz_sizeinbase(vp[i].second, 16)) + 1];
443 		acc += mpz_get_str(vtmp, 16, vp[i].second);
444 		acc += "|";
445 		delete [] vtmp;
446 
447 	}
448 	for (size_t i = 0; i < wp.size(); i++)
449 	{
450 		char *vtmp = new char[(2 * mpz_sizeinbase(wp[i].first, 16)) + 1];
451 		acc += mpz_get_str(vtmp, 16, wp[i].first);
452 		acc += "|";
453 		delete [] vtmp;
454 		vtmp = new char[(2 * mpz_sizeinbase(wp[i].second, 16)) + 1];
455 		acc += mpz_get_str(vtmp, 16, wp[i].second);
456 		acc += "|";
457 		delete [] vtmp;
458 	}
459 
460 	/* concatenate the elements of the vectors */
461 	for (size_t i = 0; i < v.size(); i++)
462 	{
463 		char *vtmp = new char[(2 * mpz_sizeinbase(v[i], 16)) + 1];
464 		acc += mpz_get_str(vtmp, 16, v[i]);
465 		acc += "|";
466 		delete [] vtmp;
467 	}
468 	for (size_t i = 0; i < w.size(); i++)
469 	{
470 		char *vtmp = new char[(2 * mpz_sizeinbase(w[i], 16)) + 1];
471 		acc += mpz_get_str(vtmp, 16, w[i]);
472 		acc += "|";
473 		delete [] vtmp;
474 	}
475 
476 	/* concatenate all the remaining arguments */
477 	va_start(ap, n);
478 	for (size_t i = 0; i < n; i++)
479 	{
480 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
481 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
482 		acc += mpz_get_str(vtmp, 16, a);
483 		acc += "|";
484 		delete [] vtmp;
485 	}
486 	va_end(ap);
487 
488 	/* hash arguments */
489 	tmcg_mpz_shash(r, acc);
490 }
491 
tmcg_mpz_shash_4pairvec2vec(mpz_ptr r,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & vp,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & wp,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & xp,const std::vector<std::pair<mpz_ptr,mpz_ptr>> & yp,const std::vector<mpz_ptr> & v,const std::vector<mpz_ptr> & w,size_t n,...)492 void tmcg_mpz_shash_4pairvec2vec
493 	(mpz_ptr r, const std::vector<std::pair<mpz_ptr, mpz_ptr> >& vp,
494 	const std::vector<std::pair<mpz_ptr, mpz_ptr> >& wp,
495 	const std::vector<std::pair<mpz_ptr, mpz_ptr> >& xp,
496 	const std::vector<std::pair<mpz_ptr, mpz_ptr> >& yp,
497 	const std::vector<mpz_ptr>& v, const std::vector<mpz_ptr>& w,
498 	size_t n, ...)
499 {
500 	va_list ap;
501 	mpz_srcptr a;
502 	std::string acc;
503 
504 	/* concatenate the elements of the pair vectors */
505 	for (size_t i = 0; i < vp.size(); i++)
506 	{
507 		char *vtmp = new char[(2 * mpz_sizeinbase(vp[i].first, 16)) + 1];
508 		acc += mpz_get_str(vtmp, 16, vp[i].first);
509 		acc += "|";
510 		delete [] vtmp;
511 		vtmp = new char[(2 * mpz_sizeinbase(vp[i].second, 16)) + 1];
512 		acc += mpz_get_str(vtmp, 16, vp[i].second);
513 		acc += "|";
514 		delete [] vtmp;
515 
516 	}
517 	for (size_t i = 0; i < wp.size(); i++)
518 	{
519 		char *vtmp = new char[(2 * mpz_sizeinbase(wp[i].first, 16)) + 1];
520 		acc += mpz_get_str(vtmp, 16, wp[i].first);
521 		acc += "|";
522 		delete [] vtmp;
523 		vtmp = new char[(2 * mpz_sizeinbase(wp[i].second, 16)) + 1];
524 		acc += mpz_get_str(vtmp, 16, wp[i].second);
525 		acc += "|";
526 		delete [] vtmp;
527 	}
528 	for (size_t i = 0; i < xp.size(); i++)
529 	{
530 		char *vtmp = new char[(2 * mpz_sizeinbase(xp[i].first, 16)) + 1];
531 		acc += mpz_get_str(vtmp, 16, xp[i].first);
532 		acc += "|";
533 		delete [] vtmp;
534 		vtmp = new char[(2 * mpz_sizeinbase(xp[i].second, 16)) + 1];
535 		acc += mpz_get_str(vtmp, 16, xp[i].second);
536 		acc += "|";
537 		delete [] vtmp;
538 
539 	}
540 	for (size_t i = 0; i < yp.size(); i++)
541 	{
542 		char *vtmp = new char[(2 * mpz_sizeinbase(yp[i].first, 16)) + 1];
543 		acc += mpz_get_str(vtmp, 16, yp[i].first);
544 		acc += "|";
545 		delete [] vtmp;
546 		vtmp = new char[(2 * mpz_sizeinbase(yp[i].second, 16)) + 1];
547 		acc += mpz_get_str(vtmp, 16, yp[i].second);
548 		acc += "|";
549 		delete [] vtmp;
550 	}
551 
552 	/* concatenate the elements of the vectors */
553 	for (size_t i = 0; i < v.size(); i++)
554 	{
555 		char *vtmp = new char[(2 * mpz_sizeinbase(v[i], 16)) + 1];
556 		acc += mpz_get_str(vtmp, 16, v[i]);
557 		acc += "|";
558 		delete [] vtmp;
559 	}
560 	for (size_t i = 0; i < w.size(); i++)
561 	{
562 		char *vtmp = new char[(2 * mpz_sizeinbase(w[i], 16)) + 1];
563 		acc += mpz_get_str(vtmp, 16, w[i]);
564 		acc += "|";
565 		delete [] vtmp;
566 	}
567 
568 	/* concatenate all the remaining arguments */
569 	va_start(ap, n);
570 	for (size_t i = 0; i < n; i++)
571 	{
572 		a = (mpz_srcptr) va_arg(ap, mpz_srcptr);
573 		char *vtmp = new char[(2 * mpz_sizeinbase(a, 16)) + 1];
574 		acc += mpz_get_str(vtmp, 16, a);
575 		acc += "|";
576 		delete [] vtmp;
577 	}
578 	va_end(ap);
579 
580 	/* hash arguments */
581 	tmcg_mpz_shash(r, acc);
582 }
583 
584