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