aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/test_crypto_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/test_crypto_cs.c')
-rw-r--r--src/lib/util/test_crypto_cs.c610
1 files changed, 610 insertions, 0 deletions
diff --git a/src/lib/util/test_crypto_cs.c b/src/lib/util/test_crypto_cs.c
new file mode 100644
index 000000000..6fd2361fb
--- /dev/null
+++ b/src/lib/util/test_crypto_cs.c
@@ -0,0 +1,610 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021,2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/test_crypto_cs.c
23 * @brief testcase for utility functions for clause blind schnorr signature scheme cryptography
24 * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
25 * @author Gian Demarmels <gian@demarmels.org>
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <sodium.h>
31
32#define ITER 25
33
34static void
35test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
36{
37 /* TEST 1
38 * Check that privkey is set
39 */
40 struct GNUNET_CRYPTO_CsPrivateKey other_priv;
41
42 other_priv = *priv;
43 GNUNET_CRYPTO_cs_private_key_generate (priv);
44 GNUNET_assert (0 !=
45 GNUNET_memcmp (&other_priv.scalar,
46 &priv->scalar));
47}
48
49
50static void
51test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
52 struct GNUNET_CRYPTO_CsPublicKey *pub)
53{
54 /* TEST 1
55 * Check that pubkey is set
56 */
57 struct GNUNET_CRYPTO_CsPublicKey other_pub;
58
59 other_pub = *pub;
60 GNUNET_CRYPTO_cs_private_key_get_public (priv,
61 pub);
62 GNUNET_assert (0 !=
63 GNUNET_memcmp (&other_pub.point,
64 &pub->point));
65
66 /* TEST 2
67 * Check that pubkey is a valid point
68 */
69 GNUNET_assert (1 ==
70 crypto_core_ed25519_is_valid_point (pub->point.y));
71
72 /* TEST 3
73 * Check if function gives the same result for the same output
74 */
75 other_pub = *pub;
76 for (unsigned int i = 0; i<ITER; i++)
77 {
78 GNUNET_CRYPTO_cs_private_key_get_public (priv,
79 pub);
80 GNUNET_assert (0 ==
81 GNUNET_memcmp (&other_pub.point,
82 &pub->point));
83 }
84}
85
86
87static void
88test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce,
89 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
90 struct GNUNET_CRYPTO_CsRSecret r[2])
91{
92 /* TEST 1
93 * Check that r are set
94 */
95 struct GNUNET_CRYPTO_CsPrivateKey other_r[2];
96
97 memcpy (other_r,
98 r,
99 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
100 GNUNET_CRYPTO_cs_r_derive (nonce,
101 "nw",
102 priv,
103 r);
104 GNUNET_assert (0 !=
105 memcmp (&other_r[0],
106 &r[0],
107 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
108
109 /* TEST 2
110 * Check if function gives the same result for the same input.
111 * This test ensures that the derivation is deterministic.
112 */
113 memcpy (other_r,
114 r,
115 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
116 for (unsigned int i = 0; i<ITER; i++)
117 {
118 GNUNET_CRYPTO_cs_r_derive (nonce,
119 "nw",
120 priv,
121 r);
122 GNUNET_assert (0 ==
123 memcmp (other_r,
124 r,
125 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
126 }
127}
128
129
130static void
131test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
132 struct GNUNET_CRYPTO_CsRPublic *r_pub)
133{
134 /* TEST 1
135 * Check that r_pub is set
136 */
137 struct GNUNET_CRYPTO_CsRPublic other_r_pub;
138
139 other_r_pub = *r_pub;
140 GNUNET_CRYPTO_cs_r_get_public (r_priv,
141 r_pub);
142 GNUNET_assert (0 !=
143 GNUNET_memcmp (&other_r_pub.point,
144 &r_pub->point));
145 /* TEST 2
146 * Check that r_pub is a valid point
147 */
148 GNUNET_assert (1 ==
149 crypto_core_ed25519_is_valid_point (r_pub->point.y));
150
151 /* TEST 3
152 * Check if function gives the same result for the same output
153 */
154 other_r_pub.point = r_pub->point;
155 for (int i = 0; i<ITER; i++)
156 {
157 GNUNET_CRYPTO_cs_r_get_public (r_priv,
158 r_pub);
159 GNUNET_assert (0 ==
160 GNUNET_memcmp (&other_r_pub.point,
161 &r_pub->point));
162 }
163}
164
165
166static void
167test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
168 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
169{
170 /* TEST 1
171 * Check that blinding secrets are set
172 */
173 struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2];
174
175 memcpy (other_bs,
176 bs,
177 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
178
179 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
180
181 GNUNET_assert (0 !=
182 memcmp (other_bs,
183 bs,
184 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
185 * 2));
186
187 /* TEST 2
188 * Check if function gives the same result for the same input.
189 * This test ensures that the derivation is deterministic.
190 */
191 memcpy (other_bs,
192 bs,
193 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
194 for (unsigned int i = 0; i<ITER; i++)
195 {
196 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
197 GNUNET_assert (0 == memcmp (&other_bs[0],
198 &bs[0],
199 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
200 * 2));
201 }
202}
203
204
205static void
206test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
207 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
208 const struct GNUNET_CRYPTO_CsPublicKey *pub,
209 const void *msg,
210 size_t msg_len,
211 struct GNUNET_CRYPTO_CsC blinded_cs[2],
212 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
213{
214 /* TEST 1
215 * Check that the blinded c's and blinded r's
216 */
217 struct GNUNET_CRYPTO_CsC other_blinded_c[2];
218
219 memcpy (&other_blinded_c[0],
220 &blinded_cs[0],
221 sizeof(struct GNUNET_CRYPTO_CsC) * 2);
222
223 struct GNUNET_CRYPTO_CsRPublic other_blinded_r_pub[2];
224 memcpy (&other_blinded_r_pub[0],
225 &blinded_r_pub[0],
226 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
227
228 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
229 r_pub,
230 pub,
231 msg,
232 msg_len,
233 blinded_cs,
234 blinded_r_pub);
235
236 GNUNET_assert (0 != memcmp (&other_blinded_c[0],
237 &blinded_cs[0],
238 sizeof(struct GNUNET_CRYPTO_CsC) * 2));
239 GNUNET_assert (0 != memcmp (&other_blinded_r_pub[0],
240 &blinded_r_pub[0],
241 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
242
243 /* TEST 2
244 * Check if R' - aG -bX = R for b = 0
245 * This test does the opposite operations and checks whether the equation is still correct.
246 */
247 for (unsigned int b = 0; b <= 1; b++)
248 {
249 struct GNUNET_CRYPTO_Cs25519Point aG;
250 struct GNUNET_CRYPTO_Cs25519Point bX;
251 struct GNUNET_CRYPTO_Cs25519Point r_min_aG;
252 struct GNUNET_CRYPTO_CsRPublic res;
253
254 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
255 aG.y,
256 bs[b].alpha.d));
257
258 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (
259 bX.y,
260 bs[b].beta.d,
261 pub->point.y));
262
263 GNUNET_assert (0 == crypto_core_ed25519_sub (
264 r_min_aG.y,
265 blinded_r_pub[b].point.y,
266 aG.y));
267
268 GNUNET_assert (0 == crypto_core_ed25519_sub (
269 res.point.y,
270 r_min_aG.y,
271 bX.y));
272
273 GNUNET_assert (0 == memcmp (&res, &r_pub[b], sizeof(struct
274 GNUNET_CRYPTO_CsRPublic)));
275 }
276
277
278 /* TEST 3
279 * Check that the blinded r_pubs' are valid points
280 */
281 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
282 blinded_r_pub[0].point.y));
283 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
284 blinded_r_pub[1].point.y));
285
286 /* TEST 4
287 * Check if function gives the same result for the same input.
288 */
289 memcpy (&other_blinded_c[0],
290 &blinded_cs[0],
291 sizeof(struct GNUNET_CRYPTO_CsC) * 2);
292 memcpy (&other_blinded_r_pub[0],
293 &blinded_r_pub[0],
294 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
295
296 for (unsigned int i = 0; i<ITER; i++)
297 {
298 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
299 r_pub,
300 pub,
301 msg,
302 msg_len,
303 blinded_cs,
304 blinded_r_pub);
305 GNUNET_assert (0 == memcmp (&other_blinded_c[0],
306 &blinded_cs[0],
307 sizeof(struct GNUNET_CRYPTO_CsC) * 2));
308 GNUNET_assert (0 == memcmp (&other_blinded_r_pub[0],
309 &blinded_r_pub[0],
310 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
311 }
312}
313
314
315static void
316test_blind_sign (unsigned int *b,
317 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
318 const struct GNUNET_CRYPTO_CsRSecret r[2],
319 const struct GNUNET_CRYPTO_CsC c[2],
320 const struct GNUNET_CRYPTO_CsNonce *nonce,
321 struct GNUNET_CRYPTO_CsBlindS *blinded_s)
322{
323 /* TEST 1
324 * Check that blinded_s is set
325 */
326 struct GNUNET_CRYPTO_CsC other_blinded_s;
327 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
328
329 *b = GNUNET_CRYPTO_cs_sign_derive (priv,
330 r,
331 c,
332 nonce,
333 blinded_s);
334
335 GNUNET_assert (0 == *b || 1 == *b);
336 GNUNET_assert (0 != memcmp (&other_blinded_s,
337 blinded_s,
338 sizeof(struct GNUNET_CRYPTO_CsBlindS)));
339
340 /* TEST 2
341 * Check if s := rb + cbX
342 * This test does the opposite operations and checks whether the equation is still correct.
343 */
344 struct GNUNET_CRYPTO_Cs25519Scalar cb_mul_x;
345 struct GNUNET_CRYPTO_Cs25519Scalar s_min_rb;
346
347 crypto_core_ed25519_scalar_mul (cb_mul_x.d,
348 c[*b].scalar.d,
349 priv->scalar.d);
350
351 crypto_core_ed25519_scalar_sub (s_min_rb.d,
352 blinded_s->scalar.d,
353 r[*b].scalar.d);
354
355 GNUNET_assert (0 == memcmp (&s_min_rb, &cb_mul_x, sizeof(struct
356 GNUNET_CRYPTO_Cs25519Scalar)));
357
358 /* TEST 3
359 * Check if function gives the same result for the same input.
360 */
361 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
362 for (unsigned int i = 0; i<ITER; i++)
363 {
364 unsigned int other_b;
365
366 other_b = GNUNET_CRYPTO_cs_sign_derive (priv, r, c, nonce, blinded_s);
367
368 GNUNET_assert (other_b == *b);
369 GNUNET_assert (0 == memcmp (&other_blinded_s,
370 blinded_s,
371 sizeof(struct GNUNET_CRYPTO_CsBlindS)));
372 }
373}
374
375
376static void
377test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
378 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
379 struct GNUNET_CRYPTO_CsS *signature_scalar)
380{
381 /* TEST 1
382 * Check that signature_scalar is set
383 */
384 struct GNUNET_CRYPTO_CsS other_signature_scalar;
385 memcpy (&other_signature_scalar,
386 signature_scalar,
387 sizeof(struct GNUNET_CRYPTO_CsS));
388
389 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
390
391 GNUNET_assert (0 != memcmp (&other_signature_scalar,
392 signature_scalar,
393 sizeof(struct GNUNET_CRYPTO_CsS)));
394
395 /* TEST 2
396 * Check if s' := s + a mod p
397 * This test does the opposite operations and checks whether the equation is still correct.
398 */
399 struct GNUNET_CRYPTO_Cs25519Scalar s_min_a;
400
401 crypto_core_ed25519_scalar_sub (s_min_a.d,
402 signature_scalar->scalar.d,
403 bs->alpha.d);
404
405 GNUNET_assert (0 == memcmp (&s_min_a, &blinded_signature_scalar->scalar,
406 sizeof(struct
407 GNUNET_CRYPTO_Cs25519Scalar)));
408
409 /* TEST 3
410 * Check if function gives the same result for the same input.
411 */
412 memcpy (&other_signature_scalar, signature_scalar,
413 sizeof(struct GNUNET_CRYPTO_CsS));
414
415 for (unsigned int i = 0; i<ITER; i++)
416 {
417 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
418 GNUNET_assert (0 == memcmp (&other_signature_scalar,
419 signature_scalar,
420 sizeof(struct GNUNET_CRYPTO_CsS)));
421 }
422}
423
424
425static void
426test_blind_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
427 const struct GNUNET_CRYPTO_CsPublicKey *pub,
428 const struct GNUNET_CRYPTO_CsC *c)
429{
430 /* TEST 1
431 * Test verifies the blinded signature sG == Rb + cbX
432 */
433 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
434 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
435 sig_scal_mul_base.y,
436 sig->s_scalar.scalar.d));
437
438 struct GNUNET_CRYPTO_Cs25519Point c_mul_pub;
439 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_mul_pub.y,
440 c->scalar.d,
441 pub->point.y));
442
443 struct GNUNET_CRYPTO_Cs25519Point r_add_c_mul_pub;
444 GNUNET_assert (0 == crypto_core_ed25519_add (r_add_c_mul_pub.y,
445 sig->r_point.point.y,
446 c_mul_pub.y));
447
448 GNUNET_assert (0 == memcmp (sig_scal_mul_base.y,
449 r_add_c_mul_pub.y,
450 sizeof(struct GNUNET_CRYPTO_Cs25519Point)));
451}
452
453
454static void
455test_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
456 const struct GNUNET_CRYPTO_CsPublicKey *pub,
457 const void *msg,
458 size_t msg_len)
459{
460 /* TEST 1
461 * Test simple verification
462 */
463 GNUNET_assert (GNUNET_YES ==
464 GNUNET_CRYPTO_cs_verify (sig,
465 pub,
466 msg,
467 msg_len));
468 /* TEST 2
469 * Test verification of "wrong" message
470 */
471 char other_msg[] = "test massege";
472 size_t other_msg_len = strlen ("test massege");
473 GNUNET_assert (GNUNET_SYSERR ==
474 GNUNET_CRYPTO_cs_verify (sig,
475 pub,
476 other_msg,
477 other_msg_len));
478}
479
480
481int
482main (int argc,
483 char *argv[])
484{
485 printf ("Test started\n");
486
487 // ---------- actions performed by signer
488 char message[] = "test message";
489 size_t message_len = strlen ("test message");
490
491 struct GNUNET_CRYPTO_CsPrivateKey priv;
492
493 memset (&priv,
494 42,
495 sizeof (priv));
496 test_create_priv (&priv);
497
498 struct GNUNET_CRYPTO_CsPublicKey pub;
499
500 memset (&pub,
501 42,
502 sizeof (pub));
503 test_generate_pub (&priv,
504 &pub);
505
506 // derive nonce
507 struct GNUNET_CRYPTO_CsNonce nonce;
508 GNUNET_assert (GNUNET_YES ==
509 GNUNET_CRYPTO_kdf (nonce.nonce,
510 sizeof(nonce.nonce),
511 "nonce",
512 strlen ("nonce"),
513 "nonce_secret",
514 strlen ("nonce_secret"),
515 NULL,
516 0));
517
518 // generate r, R
519 struct GNUNET_CRYPTO_CsRSecret r_secrets[2];
520
521 memset (r_secrets,
522 42,
523 sizeof (r_secrets));
524 test_derive_rsecret (&nonce,
525 &priv,
526 r_secrets);
527
528 struct GNUNET_CRYPTO_CsRPublic r_publics[2];
529
530 memset (r_publics,
531 42,
532 sizeof (r_publics));
533 test_generate_rpublic (&r_secrets[0],
534 &r_publics[0]);
535 test_generate_rpublic (&r_secrets[1],
536 &r_publics[1]);
537
538 // ---------- actions performed by user
539
540 // generate blinding secrets
541 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2];
542
543 memset (blindingsecrets,
544 42,
545 sizeof (blindingsecrets));
546 test_derive_blindingsecrets (&nonce,
547 blindingsecrets);
548
549 // calculate blinded c's
550 struct GNUNET_CRYPTO_CsC blinded_cs[2];
551 struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2];
552
553 memset (blinded_cs,
554 42,
555 sizeof (blinded_cs));
556 memset (blinded_r_pubs,
557 42,
558 sizeof (blinded_r_pubs));
559 test_calc_blindedc (blindingsecrets,
560 r_publics,
561 &pub,
562 message,
563 message_len,
564 blinded_cs,
565 blinded_r_pubs);
566
567 // ---------- actions performed by signer
568 // sign blinded c's and get b and s in return
569 unsigned int b;
570 struct GNUNET_CRYPTO_CsBlindS blinded_s;
571
572 memset (&blinded_s,
573 42,
574 sizeof (blinded_s));
575 test_blind_sign (&b,
576 &priv,
577 r_secrets,
578 blinded_cs,
579 &nonce,
580 &blinded_s);
581
582 // verify blinded signature
583 struct GNUNET_CRYPTO_CsSignature blinded_signature;
584
585 blinded_signature.r_point = r_publics[b];
586 blinded_signature.s_scalar.scalar = blinded_s.scalar;
587 test_blind_verify (&blinded_signature,
588 &pub,
589 &blinded_cs[b]);
590
591 // ---------- actions performed by user
592 struct GNUNET_CRYPTO_CsS sig_scalar;
593
594 memset (&sig_scalar,
595 42,
596 sizeof (sig_scalar));
597 test_unblinds (&blinded_s,
598 &blindingsecrets[b],
599 &sig_scalar);
600
601 // verify unblinded signature
602 struct GNUNET_CRYPTO_CsSignature signature;
603 signature.r_point = blinded_r_pubs[b];
604 signature.s_scalar = sig_scalar;
605 test_verify (&signature,
606 &pub,
607 message,
608 message_len);
609 return 0;
610}