aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/test_crypto_elligator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/test_crypto_elligator.c')
-rw-r--r--src/lib/util/test_crypto_elligator.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/lib/util/test_crypto_elligator.c b/src/lib/util/test_crypto_elligator.c
new file mode 100644
index 000000000..2e178b7b1
--- /dev/null
+++ b/src/lib/util/test_crypto_elligator.c
@@ -0,0 +1,302 @@
1#include "gnunet_util_lib.h"
2#include <gcrypt.h>
3#include <stdio.h>
4#include <sodium.h>
5
6#define ITER 25
7
8
9// Test vector from https://github.com/Kleshni/Elligator-2/blob/master/test-vectors.c
10// Using Decoding as a wrapper around direct_map
11static int
12testDirectMap (void)
13{
14 int ok = GNUNET_OK;
15
16 uint8_t repr1[32] = {
17 0x95, 0xa1, 0x60, 0x19, 0x04, 0x1d, 0xbe, 0xfe,
18 0xd9, 0x83, 0x20, 0x48, 0xed, 0xe1, 0x19, 0x28,
19 0xd9, 0x03, 0x65, 0xf2, 0x4a, 0x38, 0xaa, 0x7a,
20 0xef, 0x1b, 0x97, 0xe2, 0x39, 0x54, 0x10, 0x1b
21 };
22
23 uint8_t point1[32] = {
24 0x79, 0x4f, 0x05, 0xba, 0x3e, 0x3a, 0x72, 0x95,
25 0x80, 0x22, 0x46, 0x8c, 0x88, 0x98, 0x1e, 0x0b,
26 0xe5, 0x78, 0x2b, 0xe1, 0xe1, 0x14, 0x5c, 0xe2,
27 0xc3, 0xc6, 0xfd, 0xe1, 0x6d, 0xed, 0x53, 0x63
28 };
29
30 struct GNUNET_CRYPTO_EcdhePublicKey pointResult = {0};
31 struct GNUNET_CRYPTO_ElligatorRepresentative representative = {0};
32 memcpy (&representative.r, &repr1, sizeof(repr1));
33
34 bool highYResult;
35
36 GNUNET_CRYPTO_ecdhe_elligator_decoding (
37 &pointResult,
38 &highYResult,
39 &representative);
40
41 if (memcmp (point1, pointResult.q_y, sizeof(point1)) != 0)
42 {
43 ok = GNUNET_SYSERR;
44 }
45
46 return ok;
47}
48
49
50// Test vector from https://github.com/Kleshni/Elligator-2/blob/master/test-vectors.c
51static int
52testInverseMap (void)
53{
54 int ok = GNUNET_OK;
55 uint8_t point1[32] = {
56 0x33, 0x95, 0x19, 0x64, 0x00, 0x3c, 0x94, 0x08,
57 0x78, 0x06, 0x3c, 0xcf, 0xd0, 0x34, 0x8a, 0xf4,
58 0x21, 0x50, 0xca, 0x16, 0xd2, 0x64, 0x6f, 0x2c,
59 0x58, 0x56, 0xe8, 0x33, 0x83, 0x77, 0xd8, 0x00
60 };
61
62 uint8_t repr1[32] = {
63 0x99, 0x9b, 0x59, 0x1b, 0x66, 0x97, 0xd0, 0x74,
64 0xf2, 0x66, 0x19, 0x22, 0x77, 0xd5, 0x54, 0xde,
65 0xc3, 0xc2, 0x4c, 0x2e, 0xf6, 0x10, 0x81, 0x01,
66 0xf6, 0x3d, 0x94, 0xf7, 0xff, 0xf3, 0xa0, 0x13
67 };
68
69 // uint8_t reprResult1[32];
70 struct GNUNET_CRYPTO_ElligatorRepresentative r = {0};
71 struct GNUNET_CRYPTO_EcdhePublicKey pub = {0};
72 memcpy (&pub.q_y,&point1,sizeof(point1));
73 bool yHigh1 = false;
74
75 bool success = GNUNET_CRYPTO_ecdhe_elligator_encoding (&r,
76 &pub,
77 yHigh1);
78 if (success == false)
79 {
80 ok = GNUNET_SYSERR;
81 }
82 if (memcmp (&repr1,&r.r,sizeof(repr1)) != 0)
83 {
84 ok = GNUNET_SYSERR;
85 }
86
87 return ok;
88}
89
90
91/*
92* Test description: GNUNET_CRYPTO_ecdhe_elligator_generate_public_key() projects a point from the prime subgroup to the whole curve.
93* Both, the original point and the projectes point, should result in the same point when multiplied with a clamped scalar.
94*/
95static int
96testGeneratePkScalarMult (void)
97{
98 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
99 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
100 &pk,
101 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
102
103 struct GNUNET_CRYPTO_EcdhePublicKey pubWholeCurve = {0};
104 unsigned char pubPrimeCurve[crypto_scalarmult_SCALARBYTES];
105
106 if (GNUNET_CRYPTO_ecdhe_elligator_generate_public_key (&pubWholeCurve,
107 &pk) == -1)
108 {
109 return GNUNET_SYSERR;
110 }
111 crypto_scalarmult_base (pubPrimeCurve, pk.d);
112
113 struct GNUNET_CRYPTO_EcdsaPrivateKey clampedPk;
114 GNUNET_CRYPTO_ecdsa_key_create (&clampedPk);
115 crypto_scalarmult_base (pubWholeCurve.q_y, clampedPk.d);
116 crypto_scalarmult_base (pubPrimeCurve, clampedPk.d);
117 if (memcmp (pubWholeCurve.q_y, pubPrimeCurve, sizeof(pubWholeCurve)) != 0)
118 {
119 return GNUNET_SYSERR;
120 }
121 return GNUNET_OK;
122}
123
124
125/*
126* Test Description: After generating a valid private key and the corresponding representative with
127* GNUNET_CRYPTO_ecdhe_elligator_key_create(), check if using the direct map results in the corresponding public key.
128*/
129static int
130testInverseDirect (void)
131{
132 struct GNUNET_CRYPTO_ElligatorRepresentative repr;
133 struct GNUNET_CRYPTO_EcdhePublicKey point;
134 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
135 GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr, &pk);
136
137 struct GNUNET_CRYPTO_EcdhePublicKey pub = {0};
138 if (GNUNET_CRYPTO_ecdhe_elligator_generate_public_key (&pub, &pk) == -1)
139 {
140 return GNUNET_SYSERR;
141 }
142
143 GNUNET_CRYPTO_ecdhe_elligator_decoding (&point, NULL, &repr);
144
145 if (memcmp (pub.q_y, point.q_y, sizeof(point.q_y)) != 0)
146 {
147 return GNUNET_SYSERR;
148 }
149
150 return GNUNET_OK;
151}
152
153
154/*
155* Test Description: Measuring the time it takes to generate 25 key pairs (pk, representative).
156* Time value can vary because GNUNET_CRYPTO_ecdhe_elligator_key_create generates internally random
157* public keys which are just valid 50% of the time for elligators inverse map.
158* GNUNET_CRYPTO_ecdhe_elligator_key_create will therefore generate as many public keys needed
159* till a valid public key is generated.
160*/
161static int
162testTimeKeyGenerate (void)
163{
164 struct GNUNET_CRYPTO_ElligatorRepresentative repr;
165 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
166 struct GNUNET_TIME_Absolute start;
167 int ok = GNUNET_OK;
168
169 fprintf (stderr, "%s", "W");
170 start = GNUNET_TIME_absolute_get ();
171
172 for (unsigned int i = 0; i < ITER; i++)
173 {
174 fprintf (stderr, "%s", ".");
175 fflush (stderr);
176 GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr, &pk);
177 }
178 printf ("%d encoded public keys generated in %s\n",
179 ITER,
180 GNUNET_STRINGS_relative_time_to_string (
181 GNUNET_TIME_absolute_get_duration (start),
182 GNUNET_YES));
183 return ok;
184}
185
186
187static int
188testTimeDecoding (void)
189{
190 struct GNUNET_CRYPTO_EcdhePublicKey point;
191 struct GNUNET_CRYPTO_ElligatorRepresentative repr[ITER];
192 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
193 struct GNUNET_TIME_Absolute start;
194 int ok = GNUNET_OK;
195
196 for (unsigned int i = 0; i < ITER; i++)
197 {
198 GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr[i], &pk);
199 }
200
201 fprintf (stderr, "%s", "W");
202 start = GNUNET_TIME_absolute_get ();
203
204 for (unsigned int i = 0; i < ITER; i++)
205 {
206 fprintf (stderr, "%s", ".");
207 fflush (stderr);
208 GNUNET_CRYPTO_ecdhe_elligator_decoding (&point, NULL, &repr[i]);
209
210 }
211
212 printf ("%d decoded public keys generated in %s\n",
213 ITER,
214 GNUNET_STRINGS_relative_time_to_string (
215 GNUNET_TIME_absolute_get_duration (start),
216 GNUNET_YES));
217 return ok;
218}
219
220
221static int
222elligatorKEM ()
223{
224 struct GNUNET_CRYPTO_EddsaPrivateKey pk_receiver;
225 struct GNUNET_CRYPTO_EddsaPublicKey pub_receiver;
226 GNUNET_CRYPTO_eddsa_key_create (&pk_receiver);
227 GNUNET_CRYPTO_eddsa_key_get_public (&pk_receiver, &pub_receiver);
228
229 struct GNUNET_CRYPTO_ElligatorRepresentative r_sender;
230
231 // Sender side
232 struct GNUNET_HashCode key_material_encaps;
233 GNUNET_CRYPTO_eddsa_elligator_kem_encaps (&pub_receiver, &r_sender,
234 &key_material_encaps);
235
236 // Receiving side
237 struct GNUNET_HashCode key_material_decaps;
238 GNUNET_CRYPTO_eddsa_elligator_kem_decaps (&pk_receiver, &r_sender,
239 &key_material_decaps);
240
241 if (memcmp (&(key_material_encaps.bits),&(key_material_decaps.bits),
242 sizeof(key_material_encaps.bits)) != 0)
243 {
244 return GNUNET_SYSERR;
245 }
246
247 return GNUNET_OK;
248}
249
250
251int
252main (int argc, char *argv[])
253{
254
255 int failure_count = 0;
256
257 if (GNUNET_OK != testInverseMap ())
258 {
259 printf ("inverse failed!");
260 failure_count++;
261 }
262 if (GNUNET_OK != testDirectMap ())
263 {
264 printf ("direct failed!");
265 failure_count++;
266 }
267 if (GNUNET_OK != testGeneratePkScalarMult ())
268 {
269 printf ("generate PK failed!");
270 failure_count++;
271 }
272 if (GNUNET_OK != testInverseDirect ())
273 {
274 printf ("Inverse and direct map failed!");
275 failure_count++;
276 }
277 if (GNUNET_OK != testTimeKeyGenerate ())
278 {
279 printf ("Time measurement of key generation failed!");
280 failure_count++;
281 }
282 if (GNUNET_OK != testTimeDecoding ())
283 {
284 printf ("Time measurement of decoding failed!");
285 failure_count++;
286 }
287
288 if (GNUNET_OK != elligatorKEM ())
289 {
290 printf ("Elligator KEM failed!");
291 failure_count++;
292 }
293
294 if (0 != failure_count)
295 {
296 fprintf (stderr,
297 "\n\n%d TESTS FAILED!\n\n",
298 failure_count);
299 return -1;
300 }
301 return 0;
302}