summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Thomas <nico.thomas@tum.de>2021-12-16 18:13:21 +0100
committerNico Thomas <nico.thomas@tum.de>2021-12-28 22:04:14 +0100
commit9cd28ce17e03d913a2854e61a481ff985c8d3451 (patch)
treeade8f5ba42c088645e8bc77518ca97fa6b0e99fa
parent88d8a6cec7c63e52cf042db9f384309ccece15b6 (diff)
IDENTITY: Expose encryption based on identities on CLIdev/nithom/identity-enc
-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 @@
.Os
.Sh NAME
.Nm gnunet-identity
-.Nd create, delete or list egos
+.Nd maintain (create, delete or list) or perform actions with egos
.Sh SYNOPSIS
.Nm
.Op Fl C Ar NAME | Fl -create= Ns Ar NAME
@@ -34,11 +34,14 @@
.Op Fl d | -display
.Op Fl e Ar NAME | Fl -ego= Ns Ar NAME
.Op Fl h | -help
+.Op Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
.Op Fl m | -monitor
.Op Fl p | -private-keys
.Op Fl q | -quiet
+.Op Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
.Op Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
.Op Fl V | -verbose
+.Op Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
.Op Fl X | -eddsa
.Sh DESCRIPTION
.Nm
@@ -51,6 +54,9 @@ created locally, to create new egos, and to delete
existing egos (the namespace will continue to exist, but it will
be impossible to add additional data to it).
.Pp
+In addition, it is possible to encrypt and decrypt messages (arbitrary strings)
+using a given public key (for encryption) or ego (for decryption).
+.Pp
Creating a new ego requires using the
.Fl C
option 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"
operation to the respective ego.
.It Fl h | -help
Print the help page.
+.It Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
+The public key to use for a message recipient. Use together with
+.Fl W .
+The recipient can obtain the desired ego's public key using the "display"
+operation.
.It Fl m | -monitor
Run in monitor mode, listing all ouf our egos until CTRL-C is pressed.
Each 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
private key.
.It Fl q | -quiet
Be quiet, in particular outputs only the public key when listing egos.
+.It Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
+Decrypt (read) a message using the respective ego private key. Use together with
+.Fl e .
+The message consists of an ephemeral key and the ciphertext, separated by a dot.
+Such messages can be created with
+.Fl W .
.It Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
Perform "set" operation for the specified
.Ar SUBSYSTEM
@@ -95,6 +112,13 @@ This will fail if
does not yet exist.
.It Fl V | -verbose
Be verbose, in particular outputs the public key of freshly created egos.
+.It Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
+Encrypt (write) the given message for the identity given with
+.Fl k .
+The output contains an ephemeral message public key and the message separated
+by a dot. The entire line needs to be transferred to the recipient, who can use
+.Fl R
+to decrypt the message.
.It Fl X | -eddsa
Use EdDSA instead of ECDSA.
.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 = \
test_identity \
test_identity_defaults
+check_SCRIPTS = \
+ test_identity_messages.sh
+
if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
-TESTS = $(check_PROGRAMS)
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
endif
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;
static int type_eddsa;
/**
+ * -W option
+ */
+static char *write_msg;
+
+/**
+ * -R option
+ */
+static char *read_msg;
+
+/**
* -C option
*/
static char *create_ego;
@@ -86,6 +96,11 @@ static char *delete_ego;
static char *privkey_ego;
/**
+ * -k option
+ */
+static char *pubkey_msg;
+
+/**
* -s option.
*/
static char *set_ego;
@@ -164,6 +179,8 @@ test_finished (void)
(NULL == delete_op) &&
(NULL == set_op) &&
(NULL == set_subsystem) &&
+ (NULL == write_msg) &&
+ (NULL == read_msg) &&
(! list) &&
(! monitor))
{
@@ -260,6 +277,135 @@ set_done (void *cls, const char *emsg)
/**
+ * Encrypt a message given with -W, encrypted using public key of
+ * an identity given with -k.
+ */
+static void
+write_encrypted_message (void)
+{
+ struct GNUNET_IDENTITY_PublicKey recipient;
+ if (GNUNET_IDENTITY_public_key_from_string (pubkey_msg, &recipient) !=
+ GNUNET_SYSERR)
+ {
+ struct GNUNET_CRYPTO_EcdhePublicKey message_key;
+ size_t msg_len = strlen (write_msg);
+ ssize_t res = GNUNET_IDENTITY_encrypt (write_msg,
+ msg_len,
+ &recipient,
+ &message_key,
+ write_msg);
+ if (-1 != res)
+ {
+ char *keystr;
+ char *serialized_msg;
+ keystr = GNUNET_STRINGS_data_to_string_alloc (&message_key,
+ sizeof(struct
+ GNUNET_CRYPTO_EcdhePublicKey));
+ serialized_msg = GNUNET_STRINGS_data_to_string_alloc (write_msg,
+ msg_len);
+ fprintf (stdout,
+ "%s.%s\n",
+ keystr, serialized_msg);
+ GNUNET_free (keystr);
+ GNUNET_free (serialized_msg);
+ }
+ else
+ {
+ fprintf (stderr, "Error during encryption.\n");
+ global_ret = 1;
+ }
+ }
+ else
+ {
+ fprintf (stderr, "Invalid recipient public key.\n");
+ global_ret = 1;
+ }
+}
+
+
+/**
+ * Decrypt a message given with -R, encrypted using public key of @c ego
+ * and ephemeral key given with -k.
+ *
+ * @param ego ego whose private key is used for decryption
+ */
+static void
+read_encrypted_message (struct GNUNET_IDENTITY_Ego *ego)
+{
+ // message contains ECDHE key and ciphertext divided by ".", so split up first
+ char delim[2] = ".";
+ char *key_msg = strtok (read_msg, delim);
+ char *cipher;
+ if (NULL == key_msg)
+ {
+ fprintf (stderr, "Invalid message format.\n");
+ global_ret = 1;
+ return;
+ }
+ cipher = strtok (NULL, delim);
+ if (NULL == cipher)
+ {
+ fprintf (stderr, "Invalid message format, text missing.\n");
+ global_ret = 1;
+ return;
+ }
+
+ if (NULL != strtok (NULL, delim))
+ {
+ fprintf (stderr,
+ "Invalid message format, expecting only key and cipher components.\n");
+ global_ret = 1;
+ return;
+ }
+
+ struct GNUNET_CRYPTO_EcdhePublicKey message_key;
+ if (GNUNET_OK == GNUNET_STRINGS_string_to_data (key_msg, strlen (
+ key_msg),
+ &message_key,
+ sizeof(message_key)))
+ {
+ char *deserialized_msg;
+ size_t msg_len;
+ if (GNUNET_OK == GNUNET_STRINGS_string_to_data_alloc (cipher, strlen (
+ cipher),
+ (void **) &
+ deserialized_msg,
+ &msg_len))
+ {
+ ssize_t res = GNUNET_IDENTITY_decrypt (deserialized_msg,
+ msg_len,
+ GNUNET_IDENTITY_ego_get_private_key (
+ ego),
+ &message_key,
+ deserialized_msg);
+ if (-1 != res)
+ {
+ fprintf (stdout,
+ "%s\n",
+ deserialized_msg);
+ }
+ else
+ {
+ fprintf (stderr, "Failed to decrypt message.\n");
+ global_ret = 1;
+ }
+ GNUNET_free (deserialized_msg);
+ }
+ else
+ {
+ fprintf (stderr, "Invalid message format.\n");
+ global_ret = 1;
+ }
+ }
+ else
+ {
+ fprintf (stderr, "Invalid message ephemeral key.\n");
+ global_ret = 1;
+ }
+}
+
+
+/**
* If listing is enabled, prints information about the egos.
*
* This function is initially called for all egos and then again
@@ -330,13 +476,25 @@ print_ego (void *cls,
GNUNET_free (set_ego);
set_ego = NULL;
}
+ if ( (NULL == ego) &&
+ (NULL != set_ego) &&
+ (NULL != read_msg) )
+ {
+ fprintf (stderr,
+ "Ego `%s' is not known, cannot decrypt message.\n",
+ set_ego);
+ GNUNET_free (read_msg);
+ read_msg = NULL;
+ GNUNET_free (set_ego);
+ set_ego = NULL;
+ }
if ((NULL == ego) && (! monitor))
{
list = 0;
test_finished ();
return;
}
- if (! (list | monitor))
+ if (! (list | monitor) && (NULL == read_msg))
return;
if ( (NULL == ego) ||
(NULL == identifier) )
@@ -349,7 +507,14 @@ print_ego (void *cls,
s = GNUNET_IDENTITY_public_key_to_string (&pk);
privs = GNUNET_IDENTITY_private_key_to_string (
GNUNET_IDENTITY_ego_get_private_key (ego));
- if ((monitor) || (NULL != identifier))
+ if ((NULL != read_msg) && (NULL != set_ego))
+ {
+ // due to the check above, set_ego and the identifier are equal
+ read_encrypted_message (ego);
+ GNUNET_free (read_msg);
+ read_msg = NULL;
+ }
+ else if ((monitor) || (NULL != identifier))
{
if (quiet)
{
@@ -397,6 +562,19 @@ run (void *cls,
fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
return;
}
+
+ if ((NULL != read_msg) && (NULL == set_ego))
+ {
+ fprintf (stderr,
+ "Option -R requires options -e to be specified as well.\n");
+ return;
+ }
+
+ if ((NULL != write_msg) && (NULL == pubkey_msg))
+ {
+ fprintf (stderr, "Option -W requires option -k to be specified as well.\n");
+ return;
+ }
sh = GNUNET_IDENTITY_connect (cfg,
(monitor | list) ||
(NULL != set_ego) ||
@@ -404,6 +582,13 @@ run (void *cls,
? &print_ego
: NULL,
NULL);
+ if (NULL != write_msg)
+ {
+ write_encrypted_message ();
+ GNUNET_free (write_msg);
+ write_msg = NULL;
+ }
+ // read message is handled in ego callback (print_ego)
if (NULL != delete_ego)
delete_op =
GNUNET_IDENTITY_delete (sh,
@@ -471,6 +656,18 @@ main (int argc, char *const *argv)
gettext_noop (
"set the private key for the identity to PRIVATE_KEY (use together with -C)"),
&privkey_ego),
+ GNUNET_GETOPT_option_string ('R',
+ "read",
+ "MESSAGE",
+ gettext_noop (
+ "Read and decrypt message encrypted for the given ego (use together with -e EGO)"),
+ &read_msg),
+ GNUNET_GETOPT_option_string ('W',
+ "write",
+ "MESSAGE",
+ gettext_noop (
+ "Encrypt and write message for recipient identity PULBIC_KEY, (use together with -k RECIPIENT_PUBLIC_KEY)"),
+ &write_msg),
GNUNET_GETOPT_option_flag ('X',
"eddsa",
gettext_noop (
@@ -489,8 +686,14 @@ main (int argc, char *const *argv)
"ego",
"NAME",
gettext_noop (
- "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"),
+ "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)"),
&set_ego),
+ GNUNET_GETOPT_option_string ('k',
+ "key",
+ "PUBLIC_KEY",
+ gettext_noop (
+ "The public key of the recipient (with -W)"),
+ &pubkey_msg),
GNUNET_GETOPT_option_flag ('m',
"monitor",
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 @@
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-identity-service/
+
[arm]
PORT = 12000
UNIXPATH = $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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_identity.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_identity.conf -s PATHS -o GNUNET_HOME -f`
+
+which timeout >/dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+
+TEST_MSG="This is a test message. 123"
+gnunet-arm -s -c test_identity.conf
+gnunet-identity -C recipientego -c test_identity.conf
+RECIPIENT_KEY=$(gnunet-identity -d -e recipientego -q -c test_identity.conf)
+MSG_ENC=$(gnunet-identity -W "$TEST_MSG" -k $RECIPIENT_KEY -c test_identity.conf)
+MSG_DEC=$(gnunet-identity -R "$MSG_ENC" -e recipientego -c test_identity.conf)
+
+if test "$TEST_MSG" != "$MSG_DEC"
+then
+ echo "Failed - $TEST_MSG != $MSG_DEC"
+ exit 1
+fi
+
+gnunet-identity -D recipientego -c test_identity.conf
+gnunet-arm -e -c test_identity.conf