aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/test_crypto_elligator.c
diff options
context:
space:
mode:
authorPedram Fardzadeh <p.fardzadeh@protonmail.com>2023-11-05 22:40:31 +0100
committerPedram Fardzadeh <p.fardzadeh@protonmail.com>2024-02-28 16:13:12 +0100
commit63c366f4428d2ab31d62650febd28caf774805a9 (patch)
treeadff614ef0a7eeebc630c11f3a38b25f64995c42 /src/lib/util/test_crypto_elligator.c
parent93b049ebd15a2658593fdf5d93672719fb51f4dd (diff)
downloadgnunet-63c366f4428d2ab31d62650febd28caf774805a9.tar.gz
gnunet-63c366f4428d2ab31d62650febd28caf774805a9.zip
util: initial elligator implementation
Diffstat (limited to 'src/lib/util/test_crypto_elligator.c')
-rw-r--r--src/lib/util/test_crypto_elligator.c334
1 files changed, 334 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..fc541887d
--- /dev/null
+++ b/src/lib/util/test_crypto_elligator.c
@@ -0,0 +1,334 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include "gnunet_signatures.h"
4#include <gcrypt.h>
5#include <stdio.h>
6#include <sodium.h>
7
8#define ITER 25
9
10// For debugging purposes
11static void
12printLittleEndianHex (const unsigned char *arr, size_t length)
13{
14 for (size_t i = 0; i < length; ++i)
15 {
16 printf ("%02X", arr[i]);
17 }
18 printf ("\n");
19}
20
21
22// Test vector from https://github.com/Kleshni/Elligator-2/blob/master/test-vectors.c
23static int
24testDirectMap (void)
25{
26 int ok = GNUNET_OK;
27
28 uint8_t repr1[32] = {
29 0x17, 0x9f, 0x24, 0x73, 0x0d, 0xed, 0x2c, 0xe3, 0x17, 0x39, 0x08, 0xec,
30 0x61, 0x96, 0x46, 0x53,
31 0xb8, 0x02, 0x7e, 0x38, 0x3f, 0x40, 0x34, 0x6c, 0x1c, 0x9b, 0x4d, 0x2b,
32 0xdb, 0x1d, 0xb7, 0x6c
33 };
34
35 uint8_t point1[32] = {
36 0x10, 0x74, 0x54, 0x97, 0xd3, 0x5c, 0x6e, 0xde, 0x6e, 0xa6, 0xb3, 0x30,
37 0x54, 0x6a, 0x6f, 0xcb,
38 0xf1, 0x5c, 0x90, 0x3a, 0x7b, 0xe2, 0x8a, 0xe6, 0x9b, 0x1c, 0xa1, 0x4e,
39 0x0b, 0xf0, 0x9b, 0x60
40 };
41
42 uint8_t pointResult[32];
43 bool highYResult;
44 bool isLeastSqrRoot = GNUNET_CRYPTO_ecdhe_elligator_direct_map (pointResult,
45 &highYResult,
46 repr1);
47
48 if (isLeastSqrRoot == false)
49 {
50 ok = GNUNET_OK;
51 }
52 if (memcmp (point1,pointResult,sizeof(point1)) != 0)
53 {
54 ok = GNUNET_SYSERR;
55 }
56
57 return ok;
58}
59
60
61// Test vector from https://github.com/Kleshni/Elligator-2/blob/master/test-vectors.c
62static int
63testInverseMap (void)
64{
65 int ok = GNUNET_OK;
66 uint8_t point1[32] = {
67 0x33, 0x95, 0x19, 0x64, 0x00, 0x3c, 0x94, 0x08, 0x78, 0x06, 0x3c, 0xcf,
68 0xd0, 0x34, 0x8a, 0xf4,
69 0x21, 0x50, 0xca, 0x16, 0xd2, 0x64,0x6f, 0x2c, 0x58, 0x56, 0xe8, 0x33, 0x83,
70 0x77, 0xd8, 0x00
71 };
72
73 uint8_t repr1[32] = {
74 0x99, 0x9b, 0x59, 0x1b, 0x66, 0x97, 0xd0, 0x74, 0xf2, 0x66, 0x19, 0x22,0x77,
75 0xd5, 0x54, 0xde,
76 0xc3, 0xc2, 0x4c, 0x2e,0xf6, 0x10, 0x81, 0x01, 0xf6, 0x3d, 0x94, 0xf7, 0xff,
77 0xf3, 0xa0, 0x13
78 };
79
80 uint8_t reprResult1[32];
81 bool yHigh1 = false;
82 bool success = GNUNET_CRYPTO_ecdhe_elligator_inverse_map (reprResult1,
83 point1,
84 yHigh1);
85 if (success == false)
86 {
87 ok = GNUNET_SYSERR;
88 }
89 if (memcmp (repr1,reprResult1,sizeof(repr1)) != 0)
90 {
91 ok = GNUNET_SYSERR;
92 }
93
94 return ok;
95}
96
97
98/*
99* Test description: GNUNET_CRYPTO_ecdhe_elligator_generate_public_key() projects a point from the prime subgroup to the whole curve.
100* Both, the original point and the projectes point, should result in the same point when multiplied with a clamped scalar.
101*/
102static int
103testGeneratePkScalarMult (void)
104{
105 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
106 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
107 &pk,
108 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
109
110 unsigned char pubWholeCurve[crypto_scalarmult_SCALARBYTES];
111 unsigned char pubPrimeCurve[crypto_scalarmult_SCALARBYTES];
112
113 if (GNUNET_CRYPTO_ecdhe_elligator_generate_public_key (pubWholeCurve, &pk) ==
114 -1)
115 {
116 return GNUNET_SYSERR;
117 }
118 crypto_scalarmult_base (pubPrimeCurve, pk.d);
119
120 // printf ("pubWholeCurve\n");
121 // printLittleEndianHex (pubWholeCurve,32);
122 // printf ("pubPrimeCurve\n");
123 // printLittleEndianHex (pubPrimeCurve,32);
124 // TODO: Currently utilizing ecdsa function for ecdhe testing, due to clamping. Clean this part later.
125 struct GNUNET_CRYPTO_EcdsaPrivateKey clampedPk;
126 GNUNET_CRYPTO_ecdsa_key_create (&clampedPk);
127 crypto_scalarmult_base (pubWholeCurve, clampedPk.d);
128 crypto_scalarmult_base (pubPrimeCurve, clampedPk.d);
129 if (memcmp (pubWholeCurve, pubPrimeCurve, sizeof(pubWholeCurve)) != 0)
130 {
131 return GNUNET_SYSERR;
132 }
133 return GNUNET_OK;
134}
135
136
137/*
138* Test Description: Simply testing, if function goes through.
139*/
140static int
141testKeyPairEasy (void)
142{
143 struct GNUNET_CRYPTO_ElligatorRepresentative repr;
144 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
145 int i = GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr, &pk);
146 if (i == GNUNET_SYSERR)
147 {
148 return GNUNET_SYSERR;
149 }
150 return GNUNET_OK;
151}
152
153
154/*
155* Test Description: After generating a valid private key and the corresponding representative with
156* GNUNET_CRYPTO_ecdhe_elligator_key_create(), check if using the direct map results in the corresponding public key.
157*/
158static int
159testInverseDirect (void)
160{
161 struct GNUNET_CRYPTO_ElligatorRepresentative repr;
162 struct GNUNET_CRYPTO_EcdhePublicKey point;
163 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
164 int i = GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr, &pk);
165 if (i == -1)
166 {
167 return GNUNET_SYSERR;
168 }
169
170 unsigned char pub[crypto_scalarmult_SCALARBYTES];
171 bool highY;
172 if (GNUNET_CRYPTO_ecdhe_elligator_generate_public_key (pub, &pk) == -1)
173 {
174 return GNUNET_SYSERR;
175 }
176
177 GNUNET_CRYPTO_ecdhe_elligator_decoding (&point, &highY, &repr);
178
179 if (memcmp (pub, point.q_y, sizeof(point.q_y)) != 0)
180 {
181 return GNUNET_SYSERR;
182 }
183
184 return GNUNET_OK;
185}
186
187
188/*
189* Test Description: Measuring the time it takes to generate 25 key pairs (pk, representative).
190* Time value can vary because GNUNET_CRYPTO_ecdhe_elligator_key_create generates internally random
191* public keys which are just valid 50% of the time for elligators inverse map.
192* GNUNET_CRYPTO_ecdhe_elligator_key_create will therefore generate as many public keys needed
193* till a valid public key is generated.
194*/
195static int
196testTimeKeyGenerate (void)
197{
198 struct GNUNET_CRYPTO_ElligatorRepresentative repr;
199 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
200 struct GNUNET_TIME_Absolute start;
201 int ok = GNUNET_OK;
202
203 fprintf (stderr, "%s", "W");
204 start = GNUNET_TIME_absolute_get ();
205
206 for (unsigned int i = 0; i < ITER; i++)
207 {
208 fprintf (stderr, "%s", ".");
209 fflush (stderr);
210 if (GNUNET_SYSERR ==
211 GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr, &pk))
212 {
213 fprintf (stderr,
214 "GNUNET_CRYPTO_ecdhe_elligator_key_create SYSERR\n");
215 ok = GNUNET_SYSERR;
216 }
217 // printLittleEndianHex(repr.r,32);
218 }
219 printf ("%d encoded public keys generated in %s\n",
220 ITER,
221 GNUNET_STRINGS_relative_time_to_string (
222 GNUNET_TIME_absolute_get_duration (start),
223 GNUNET_YES));
224 return ok;
225}
226
227
228static int
229testTimeDecoding (void)
230{
231 struct GNUNET_CRYPTO_EcdhePublicKey point;
232 struct GNUNET_CRYPTO_ElligatorRepresentative repr[ITER];
233 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
234 bool high_y;
235 struct GNUNET_TIME_Absolute start;
236 int ok = GNUNET_OK;
237
238 for (unsigned int i = 0; i < ITER; i++)
239 {
240 if (GNUNET_SYSERR ==
241 GNUNET_CRYPTO_ecdhe_elligator_key_create (&repr[i], &pk))
242 {
243 fprintf (stderr,
244 "GNUNET_CRYPTO_ecdhe_elligator_key_create SYSERR\n");
245 ok = GNUNET_SYSERR;
246 continue;
247 }
248 }
249
250 fprintf (stderr, "%s", "W");
251 start = GNUNET_TIME_absolute_get ();
252
253 for (unsigned int i = 0; i < ITER; i++)
254 {
255 fprintf (stderr, "%s", ".");
256 fflush (stderr);
257 if (false ==
258 GNUNET_CRYPTO_ecdhe_elligator_decoding (&point, &high_y, &repr[i]))
259 {
260 fprintf (stderr,
261 "GNUNET_CRYPTO_ecdhe_elligator_decoding SYSERR\n");
262 ok = GNUNET_SYSERR;
263 continue;
264 }
265 }
266
267 printf ("%d decoded public keys generated in %s\n",
268 ITER,
269 GNUNET_STRINGS_relative_time_to_string (
270 GNUNET_TIME_absolute_get_duration (start),
271 GNUNET_YES));
272 return ok;
273}
274
275
276/*
277*More tests to implement:
278* Adding more test vectors from different sources for inverse and direct map
279 * check if inverse map rightfully fails for points which are not "encodable"
280*/
281
282
283int
284main (int argc, char *argv[])
285{
286 GNUNET_CRYPTO_ecdhe_elligator_initialize ();
287
288 int failure_count = 0;
289
290 if (GNUNET_OK != testInverseMap ())
291 {
292 printf ("inverse failed!");
293 failure_count++;
294 }
295 if (GNUNET_OK != testDirectMap ())
296 {
297 printf ("direct failed!");
298 failure_count++;
299 }
300 if (GNUNET_OK != testGeneratePkScalarMult ())
301 {
302 printf ("generate PK failed!");
303 failure_count++;
304 }
305 if (GNUNET_OK != testKeyPairEasy ())
306 {
307 printf ("key generation doesn't work!");
308 failure_count++;
309 }
310 if (GNUNET_OK != testInverseDirect ())
311 {
312 printf ("Inverse and direct map failed!");
313 failure_count++;
314 }
315 if (GNUNET_OK != testTimeKeyGenerate ())
316 {
317 printf ("Time measurement of key generation failed!");
318 failure_count++;
319 }
320 if (GNUNET_OK != testTimeDecoding ())
321 {
322 printf ("Time measurement of decoding failed!");
323 failure_count++;
324 }
325
326 if (0 != failure_count)
327 {
328 fprintf (stderr,
329 "\n\n%d TESTS FAILED!\n\n",
330 failure_count);
331 return -1;
332 }
333 return 0;
334}