aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Thomas <nico.thomas@tum.de>2021-12-16 18:13:21 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2021-12-28 22:43:00 +0100
commit88fb1d89ed483576a7f02060cd72be7761b2be3a (patch)
treebcbffd33835229417b27074819c8ae486bde556b
parent7205436569d1b1e0f10485dbdec087f19de865f8 (diff)
downloadgnunet-88fb1d89ed483576a7f02060cd72be7761b2be3a.tar.gz
gnunet-88fb1d89ed483576a7f02060cd72be7761b2be3a.zip
IDENTITY: Expose encryption based on identities on CLI
-rw-r--r--doc/man/gnunet-identity.126
-rw-r--r--src/identity/Makefile.am5
-rw-r--r--src/identity/gnunet-identity.c209
-rw-r--r--src/identity/test_identity.conf3
-rwxr-xr-xsrc/identity/test_identity_messages.sh34
5 files changed, 272 insertions, 5 deletions
diff --git a/doc/man/gnunet-identity.1 b/doc/man/gnunet-identity.1
index 599d3b269..835dfb225 100644
--- a/doc/man/gnunet-identity.1
+++ b/doc/man/gnunet-identity.1
@@ -26,7 +26,7 @@
26.Os 26.Os
27.Sh NAME 27.Sh NAME
28.Nm gnunet-identity 28.Nm gnunet-identity
29.Nd create, delete or list egos 29.Nd maintain (create, delete or list) or perform actions with egos
30.Sh SYNOPSIS 30.Sh SYNOPSIS
31.Nm 31.Nm
32.Op Fl C Ar NAME | Fl -create= Ns Ar NAME 32.Op Fl C Ar NAME | Fl -create= Ns Ar NAME
@@ -34,11 +34,14 @@
34.Op Fl d | -display 34.Op Fl d | -display
35.Op Fl e Ar NAME | Fl -ego= Ns Ar NAME 35.Op Fl e Ar NAME | Fl -ego= Ns Ar NAME
36.Op Fl h | -help 36.Op Fl h | -help
37.Op Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
37.Op Fl m | -monitor 38.Op Fl m | -monitor
38.Op Fl p | -private-keys 39.Op Fl p | -private-keys
39.Op Fl q | -quiet 40.Op Fl q | -quiet
41.Op Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
40.Op Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM 42.Op Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
41.Op Fl V | -verbose 43.Op Fl V | -verbose
44.Op Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
42.Op Fl X | -eddsa 45.Op Fl X | -eddsa
43.Sh DESCRIPTION 46.Sh DESCRIPTION
44.Nm 47.Nm
@@ -51,6 +54,9 @@ created locally, to create new egos, and to delete
51existing egos (the namespace will continue to exist, but it will 54existing egos (the namespace will continue to exist, but it will
52be impossible to add additional data to it). 55be impossible to add additional data to it).
53.Pp 56.Pp
57In addition, it is possible to encrypt and decrypt messages (arbitrary strings)
58using a given public key (for encryption) or ego (for decryption).
59.Pp
54Creating a new ego requires using the 60Creating a new ego requires using the
55.Fl C 61.Fl C
56option together with an identifier (name) that is to be used for 62option together with an identifier (name) that is to be used for
@@ -72,6 +78,11 @@ Perform "set" operation with the respective ego or restrict "display"
72operation to the respective ego. 78operation to the respective ego.
73.It Fl h | -help 79.It Fl h | -help
74Print the help page. 80Print the help page.
81.It Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
82The public key to use for a message recipient. Use together with
83.Fl W .
84The recipient can obtain the desired ego's public key using the "display"
85operation.
75.It Fl m | -monitor 86.It Fl m | -monitor
76Run in monitor mode, listing all ouf our egos until CTRL-C is pressed. 87Run in monitor mode, listing all ouf our egos until CTRL-C is pressed.
77Each ego is listed together with a unique pointer value; if 88Each ego is listed together with a unique pointer value; if
@@ -83,6 +94,12 @@ keys. The second column shows the public key, the third column shows the
83private key. 94private key.
84.It Fl q | -quiet 95.It Fl q | -quiet
85Be quiet, in particular outputs only the public key when listing egos. 96Be quiet, in particular outputs only the public key when listing egos.
97.It Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
98Decrypt (read) a message using the respective ego private key. Use together with
99.Fl e .
100The message consists of an ephemeral key and the ciphertext, separated by a dot.
101Such messages can be created with
102.Fl W .
86.It Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM 103.It Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
87Perform "set" operation for the specified 104Perform "set" operation for the specified
88.Ar SUBSYSTEM 105.Ar SUBSYSTEM
@@ -95,6 +112,13 @@ This will fail if
95does not yet exist. 112does not yet exist.
96.It Fl V | -verbose 113.It Fl V | -verbose
97Be verbose, in particular outputs the public key of freshly created egos. 114Be verbose, in particular outputs the public key of freshly created egos.
115.It Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
116Encrypt (write) the given message for the identity given with
117.Fl k .
118The output contains an ephemeral message public key and the message separated
119by a dot. The entire line needs to be transferred to the recipient, who can use
120.Fl R
121to decrypt the message.
98.It Fl X | -eddsa 122.It Fl X | -eddsa
99Use EdDSA instead of ECDSA. 123Use EdDSA instead of ECDSA.
100.El 124.El
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 59ace6c41..e535c208a 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -71,9 +71,12 @@ check_PROGRAMS = \
71 test_identity \ 71 test_identity \
72 test_identity_defaults 72 test_identity_defaults
73 73
74check_SCRIPTS = \
75 test_identity_messages.sh
76
74if ENABLE_TEST_RUN 77if ENABLE_TEST_RUN
75AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 78AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
76TESTS = $(check_PROGRAMS) 79TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
77endif 80endif
78 81
79 82
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
index d8dc936d3..97dc2ce7e 100644
--- a/src/identity/gnunet-identity.c
+++ b/src/identity/gnunet-identity.c
@@ -71,6 +71,16 @@ static int quiet;
71static int type_eddsa; 71static int type_eddsa;
72 72
73/** 73/**
74 * -W option
75 */
76static char *write_msg;
77
78/**
79 * -R option
80 */
81static char *read_msg;
82
83/**
74 * -C option 84 * -C option
75 */ 85 */
76static char *create_ego; 86static char *create_ego;
@@ -86,6 +96,11 @@ static char *delete_ego;
86static char *privkey_ego; 96static char *privkey_ego;
87 97
88/** 98/**
99 * -k option
100 */
101static char *pubkey_msg;
102
103/**
89 * -s option. 104 * -s option.
90 */ 105 */
91static char *set_ego; 106static char *set_ego;
@@ -164,6 +179,8 @@ test_finished (void)
164 (NULL == delete_op) && 179 (NULL == delete_op) &&
165 (NULL == set_op) && 180 (NULL == set_op) &&
166 (NULL == set_subsystem) && 181 (NULL == set_subsystem) &&
182 (NULL == write_msg) &&
183 (NULL == read_msg) &&
167 (! list) && 184 (! list) &&
168 (! monitor)) 185 (! monitor))
169 { 186 {
@@ -260,6 +277,135 @@ set_done (void *cls, const char *emsg)
260 277
261 278
262/** 279/**
280 * Encrypt a message given with -W, encrypted using public key of
281 * an identity given with -k.
282 */
283static void
284write_encrypted_message (void)
285{
286 struct GNUNET_IDENTITY_PublicKey recipient;
287 if (GNUNET_IDENTITY_public_key_from_string (pubkey_msg, &recipient) !=
288 GNUNET_SYSERR)
289 {
290 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
291 size_t msg_len = strlen (write_msg);
292 ssize_t res = GNUNET_IDENTITY_encrypt (write_msg,
293 msg_len,
294 &recipient,
295 &message_key,
296 write_msg);
297 if (-1 != res)
298 {
299 char *keystr;
300 char *serialized_msg;
301 keystr = GNUNET_STRINGS_data_to_string_alloc (&message_key,
302 sizeof(struct
303 GNUNET_CRYPTO_EcdhePublicKey));
304 serialized_msg = GNUNET_STRINGS_data_to_string_alloc (write_msg,
305 msg_len);
306 fprintf (stdout,
307 "%s.%s\n",
308 keystr, serialized_msg);
309 GNUNET_free (keystr);
310 GNUNET_free (serialized_msg);
311 }
312 else
313 {
314 fprintf (stderr, "Error during encryption.\n");
315 global_ret = 1;
316 }
317 }
318 else
319 {
320 fprintf (stderr, "Invalid recipient public key.\n");
321 global_ret = 1;
322 }
323}
324
325
326/**
327 * Decrypt a message given with -R, encrypted using public key of @c ego
328 * and ephemeral key given with -k.
329 *
330 * @param ego ego whose private key is used for decryption
331 */
332static void
333read_encrypted_message (struct GNUNET_IDENTITY_Ego *ego)
334{
335 // message contains ECDHE key and ciphertext divided by ".", so split up first
336 char delim[2] = ".";
337 char *key_msg = strtok (read_msg, delim);
338 char *cipher;
339 if (NULL == key_msg)
340 {
341 fprintf (stderr, "Invalid message format.\n");
342 global_ret = 1;
343 return;
344 }
345 cipher = strtok (NULL, delim);
346 if (NULL == cipher)
347 {
348 fprintf (stderr, "Invalid message format, text missing.\n");
349 global_ret = 1;
350 return;
351 }
352
353 if (NULL != strtok (NULL, delim))
354 {
355 fprintf (stderr,
356 "Invalid message format, expecting only key and cipher components.\n");
357 global_ret = 1;
358 return;
359 }
360
361 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
362 if (GNUNET_OK == GNUNET_STRINGS_string_to_data (key_msg, strlen (
363 key_msg),
364 &message_key,
365 sizeof(message_key)))
366 {
367 char *deserialized_msg;
368 size_t msg_len;
369 if (GNUNET_OK == GNUNET_STRINGS_string_to_data_alloc (cipher, strlen (
370 cipher),
371 (void **) &
372 deserialized_msg,
373 &msg_len))
374 {
375 ssize_t res = GNUNET_IDENTITY_decrypt (deserialized_msg,
376 msg_len,
377 GNUNET_IDENTITY_ego_get_private_key (
378 ego),
379 &message_key,
380 deserialized_msg);
381 if (-1 != res)
382 {
383 fprintf (stdout,
384 "%s\n",
385 deserialized_msg);
386 }
387 else
388 {
389 fprintf (stderr, "Failed to decrypt message.\n");
390 global_ret = 1;
391 }
392 GNUNET_free (deserialized_msg);
393 }
394 else
395 {
396 fprintf (stderr, "Invalid message format.\n");
397 global_ret = 1;
398 }
399 }
400 else
401 {
402 fprintf (stderr, "Invalid message ephemeral key.\n");
403 global_ret = 1;
404 }
405}
406
407
408/**
263 * If listing is enabled, prints information about the egos. 409 * If listing is enabled, prints information about the egos.
264 * 410 *
265 * This function is initially called for all egos and then again 411 * This function is initially called for all egos and then again
@@ -330,13 +476,25 @@ print_ego (void *cls,
330 GNUNET_free (set_ego); 476 GNUNET_free (set_ego);
331 set_ego = NULL; 477 set_ego = NULL;
332 } 478 }
479 if ( (NULL == ego) &&
480 (NULL != set_ego) &&
481 (NULL != read_msg) )
482 {
483 fprintf (stderr,
484 "Ego `%s' is not known, cannot decrypt message.\n",
485 set_ego);
486 GNUNET_free (read_msg);
487 read_msg = NULL;
488 GNUNET_free (set_ego);
489 set_ego = NULL;
490 }
333 if ((NULL == ego) && (! monitor)) 491 if ((NULL == ego) && (! monitor))
334 { 492 {
335 list = 0; 493 list = 0;
336 test_finished (); 494 test_finished ();
337 return; 495 return;
338 } 496 }
339 if (! (list | monitor)) 497 if (! (list | monitor) && (NULL == read_msg))
340 return; 498 return;
341 if ( (NULL == ego) || 499 if ( (NULL == ego) ||
342 (NULL == identifier) ) 500 (NULL == identifier) )
@@ -349,7 +507,14 @@ print_ego (void *cls,
349 s = GNUNET_IDENTITY_public_key_to_string (&pk); 507 s = GNUNET_IDENTITY_public_key_to_string (&pk);
350 privs = GNUNET_IDENTITY_private_key_to_string ( 508 privs = GNUNET_IDENTITY_private_key_to_string (
351 GNUNET_IDENTITY_ego_get_private_key (ego)); 509 GNUNET_IDENTITY_ego_get_private_key (ego));
352 if ((monitor) || (NULL != identifier)) 510 if ((NULL != read_msg) && (NULL != set_ego))
511 {
512 // due to the check above, set_ego and the identifier are equal
513 read_encrypted_message (ego);
514 GNUNET_free (read_msg);
515 read_msg = NULL;
516 }
517 else if ((monitor) || (NULL != identifier))
353 { 518 {
354 if (quiet) 519 if (quiet)
355 { 520 {
@@ -397,6 +562,19 @@ run (void *cls,
397 fprintf (stderr, "Option -s requires option -e to be specified as well.\n"); 562 fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
398 return; 563 return;
399 } 564 }
565
566 if ((NULL != read_msg) && (NULL == set_ego))
567 {
568 fprintf (stderr,
569 "Option -R requires options -e to be specified as well.\n");
570 return;
571 }
572
573 if ((NULL != write_msg) && (NULL == pubkey_msg))
574 {
575 fprintf (stderr, "Option -W requires option -k to be specified as well.\n");
576 return;
577 }
400 sh = GNUNET_IDENTITY_connect (cfg, 578 sh = GNUNET_IDENTITY_connect (cfg,
401 (monitor | list) || 579 (monitor | list) ||
402 (NULL != set_ego) || 580 (NULL != set_ego) ||
@@ -404,6 +582,13 @@ run (void *cls,
404 ? &print_ego 582 ? &print_ego
405 : NULL, 583 : NULL,
406 NULL); 584 NULL);
585 if (NULL != write_msg)
586 {
587 write_encrypted_message ();
588 GNUNET_free (write_msg);
589 write_msg = NULL;
590 }
591 // read message is handled in ego callback (print_ego)
407 if (NULL != delete_ego) 592 if (NULL != delete_ego)
408 delete_op = 593 delete_op =
409 GNUNET_IDENTITY_delete (sh, 594 GNUNET_IDENTITY_delete (sh,
@@ -471,6 +656,18 @@ main (int argc, char *const *argv)
471 gettext_noop ( 656 gettext_noop (
472 "set the private key for the identity to PRIVATE_KEY (use together with -C)"), 657 "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
473 &privkey_ego), 658 &privkey_ego),
659 GNUNET_GETOPT_option_string ('R',
660 "read",
661 "MESSAGE",
662 gettext_noop (
663 "Read and decrypt message encrypted for the given ego (use together with -e EGO)"),
664 &read_msg),
665 GNUNET_GETOPT_option_string ('W',
666 "write",
667 "MESSAGE",
668 gettext_noop (
669 "Encrypt and write message for recipient identity PULBIC_KEY, (use together with -k RECIPIENT_PUBLIC_KEY)"),
670 &write_msg),
474 GNUNET_GETOPT_option_flag ('X', 671 GNUNET_GETOPT_option_flag ('X',
475 "eddsa", 672 "eddsa",
476 gettext_noop ( 673 gettext_noop (
@@ -489,8 +686,14 @@ main (int argc, char *const *argv)
489 "ego", 686 "ego",
490 "NAME", 687 "NAME",
491 gettext_noop ( 688 gettext_noop (
492 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"), 689 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s), restrict results to NAME (use together with -d) or read and decrypt a message for NAME (use together with -R)"),
493 &set_ego), 690 &set_ego),
691 GNUNET_GETOPT_option_string ('k',
692 "key",
693 "PUBLIC_KEY",
694 gettext_noop (
695 "The public key of the recipient (with -W)"),
696 &pubkey_msg),
494 GNUNET_GETOPT_option_flag ('m', 697 GNUNET_GETOPT_option_flag ('m',
495 "monitor", 698 "monitor",
496 gettext_noop ("run in monitor mode egos"), 699 gettext_noop ("run in monitor mode egos"),
diff --git a/src/identity/test_identity.conf b/src/identity/test_identity.conf
index 9c433da77..14b915732 100644
--- a/src/identity/test_identity.conf
+++ b/src/identity/test_identity.conf
@@ -1,3 +1,6 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-identity-service/
3
1[arm] 4[arm]
2PORT = 12000 5PORT = 12000
3UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock 6UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
diff --git a/src/identity/test_identity_messages.sh b/src/identity/test_identity_messages.sh
new file mode 100755
index 000000000..250c6a6f1
--- /dev/null
+++ b/src/identity/test_identity_messages.sh
@@ -0,0 +1,34 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_identity.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_identity.conf -s PATHS -o GNUNET_HOME -f`
17
18which timeout >/dev/null 2>&1 && DO_TIMEOUT="timeout 30"
19
20TEST_MSG="This is a test message. 123"
21gnunet-arm -s -c test_identity.conf
22gnunet-identity -C recipientego -c test_identity.conf
23RECIPIENT_KEY=$(gnunet-identity -d -e recipientego -q -c test_identity.conf)
24MSG_ENC=$(gnunet-identity -W "$TEST_MSG" -k $RECIPIENT_KEY -c test_identity.conf)
25MSG_DEC=$(gnunet-identity -R "$MSG_ENC" -e recipientego -c test_identity.conf)
26
27if test "$TEST_MSG" != "$MSG_DEC"
28then
29 echo "Failed - $TEST_MSG != $MSG_DEC"
30 exit 1
31fi
32
33gnunet-identity -D recipientego -c test_identity.conf
34gnunet-arm -e -c test_identity.conf