diff options
Diffstat (limited to 'src/identity/gnunet-identity.c')
-rw-r--r-- | src/identity/gnunet-identity.c | 209 |
1 files changed, 206 insertions, 3 deletions
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"), |