gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 02/02: IDENTITY: Expose encryption based on identities on CLI


From: gnunet
Subject: [gnunet] 02/02: IDENTITY: Expose encryption based on identities on CLI
Date: Tue, 28 Dec 2021 22:43:30 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

commit 88fb1d89ed483576a7f02060cd72be7761b2be3a
Author: Nico Thomas <nico.thomas@tum.de>
AuthorDate: Thu Dec 16 18:13:21 2021 +0100

    IDENTITY: Expose encryption based on identities on CLI
---
 doc/man/gnunet-identity.1              |  26 +++-
 src/identity/Makefile.am               |   5 +-
 src/identity/gnunet-identity.c         | 209 ++++++++++++++++++++++++++++++++-
 src/identity/test_identity.conf        |   3 +
 src/identity/test_identity_messages.sh |  34 ++++++
 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
@@ -70,6 +70,16 @@ static int quiet;
  */
 static int type_eddsa;
 
+/**
+ * -W option
+ */
+static char *write_msg;
+
+/**
+ * -R option
+ */
+static char *read_msg;
+
 /**
  * -C option
  */
@@ -85,6 +95,11 @@ static char *delete_ego;
  */
 static char *privkey_ego;
 
+/**
+ * -k option
+ */
+static char *pubkey_msg;
+
 /**
  * -s option.
  */
@@ -164,6 +179,8 @@ test_finished (void)
        (NULL == delete_op) &&
        (NULL == set_op) &&
        (NULL == set_subsystem) &&
+       (NULL == write_msg) &&
+       (NULL == read_msg) &&
        (! list) &&
        (! monitor))
   {
@@ -259,6 +276,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.
  *
@@ -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

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]