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