diff options
Diffstat (limited to 'src/lib/util/test_crypto_elligator.c')
-rw-r--r-- | src/lib/util/test_crypto_elligator.c | 302 |
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 | ||
11 | static int | ||
12 | testDirectMap (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 | ||
51 | static int | ||
52 | testInverseMap (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 | */ | ||
95 | static int | ||
96 | testGeneratePkScalarMult (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 | */ | ||
129 | static int | ||
130 | testInverseDirect (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 | */ | ||
161 | static int | ||
162 | testTimeKeyGenerate (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 | |||
187 | static int | ||
188 | testTimeDecoding (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 | |||
221 | static int | ||
222 | elligatorKEM () | ||
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 | |||
251 | int | ||
252 | main (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 | } | ||