A GNUPG patch to enable anonymous encrypted messages

Nimrod Zimerman zimerman at forfree.at
Fri Aug 21 18:14:44 CEST 1998


Hello.

Below is a patch to GNUPG that allows removing the keyid from encrypted
packets (such that one can't know who an encrypted packet is destinated
to), and, obviously, allows decrypting such packets (supplying the
appropriate userid on the command line).

Why is this needed? Privacy. When sending an encrypted message via a named
channel (such as 'regular' e-mail), revealing the destination of the
message is something you can't really avoid, and hence the keyid on the
encrypted message doesn't matter. However, when sending a message via an
anonymous channel (through a remailer to a newsgroup, for example), adding
the keyid on the encrypted message is fairly counter productive. It might
not provide potential adversaries the ability to know who can read the
message - but it certainly helps, even if only by aiding in traffic
analysis.

The solution is quite simple - avoid adding the keyid to encrypted messages
(packets in those messages). This is exactly what the patch does, using
the command-line switch '--throw-keyid'.

There is a problem here, though. Adversaries can't know who a message is
destinated to, but the intended recipient can't know it either. If very high
level of anonymity is needed - a solution is to scan all of the encrypted
messages, trying to decrypt every such message with your private key. This
can be very time consuming. If anonymity requirements are lower - marking
the message in some way which isn't all that obvious could be a good
compromise (for example, only try decrypting messages that were supposedly
sent on a Friday).

In order to allow decrypting of messages that don't have a (proper) keyid
field, the '--local-user' (-u) switch was enhanced to also apply when
decrypting messages. As I currently implemented it, only the first name
provided is used.

Note that the patch is quite hackish in nature - especially the way I handle
'--local-user'. Should I not receive any angry replies telling me that this
approach is all wrong, I would rewrite the appropriate sections. Note that
coding style is currently my own, rather than the original coding style in
GNUPG.

Two issues:
1. Is this approach valid? Am I missing something important - such as that
encrypted messages contain the recipient's keyid in some other way?
2. Are there better ways to handle this in GNUPG?

Possible enhancements:
1. Allow for arbitrary keyids, instead of zeroing the keyid out. Why?
More flexible.
2. Allow for multiple local userids - try to decrypt using all keys. Why
not? Highly annoying, if ran manually. Otherwise, multiple executions of gpg
might be a better idea.
3. Allow for manual local userid input (such as when encrypting to remote
users, without specifying on the command line).

Comments are welcomed.


Here is the patch. Apply at source root level ('cd /usr/src/gnupg-0.3.4;
patch -p0 < /location/of/diff/gnupg-0.3.4-throw-keyid.diff', for
example). The patch should apply cleanly on version 0.3.4. You can just read
it here - it is very straight forward.


[----- gnupg-0.3.4-throw-keyid.diff -----]

--- ./g10/g10.c.ORIG	Tue Aug 11 11:20:47 1998
+++ ./g10/g10.c	Thu Aug 20 05:41:02 1998
@@ -169,6 +169,7 @@
     { 536, "marginals-needed", 1, N_("(default is 3)")},
     { 560, "load-extension" ,2, N_("|file|load extension module")},
     { 561, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
+    { 570, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
   #ifdef IS_G10
     { 527, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
     { 529, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
@@ -538,6 +539,11 @@
 	    strcpy(sl->d, pargs.r.ret_str);
 	    sl->next = locusr;
 	    locusr = sl;
+	    if (opt.firstlocusr == NULL)
+	    {
+		opt.firstlocusr = m_alloc (strlen (sl->d) + 1);
+		strcpy (opt.firstlocusr, sl->d);
+	    }
 	    break;
 	  case oCompress: opt.compress = pargs.r.ret_int; break;
 	  case 503: set_cmd( &cmd, aKeygen); break;
@@ -641,6 +647,7 @@
 	    break;
 	  case 568: opt.set_filename = pargs.r.ret_str; break;
 	  case 569: opt.comment_string = pargs.r.ret_str; break;
+	  case 570: opt.throw_keyid = 1; break;
 	  default : errors++; pargs.err = configfp? 1:2; break;
 	}
     }
@@ -1124,6 +1131,8 @@
     /* cleanup */
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
+    if (opt.firstlocusr != NULL)
+       m_free (opt.firstlocusr);
     g10_exit(0);
     return 8; /*NEVER REACHED*/
 }
--- ./g10/mainproc.c.ORIG	Wed Aug  5 12:42:03 1998
+++ ./g10/mainproc.c	Thu Aug 20 05:46:31 1998
@@ -175,6 +175,17 @@
     c->last_was_session_key = 1;
     enc = pkt->pkt.pubkey_enc;
     /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
+
+    if (opt.firstlocusr != NULL)
+    {
+       PKT_secret_key *sk = m_alloc_clear (sizeof *sk);
+       sk->pubkey_algo = enc->pubkey_algo;
+       sk->pubkey_usage = PUBKEY_USAGE_ENC;
+       if (get_seckey_byname (sk, opt.firstlocusr, 0) == 0)
+          keyid_from_sk (sk, enc->keyid);
+       free_secret_key (sk);
+    }
+
     if( is_ELGAMAL(enc->pubkey_algo)
 	|| enc->pubkey_algo == PUBKEY_ALGO_DSA
 	|| is_RSA(enc->pubkey_algo)  ) {
--- ./g10/options.h.ORIG	Tue Aug 11 10:04:56 1998
+++ ./g10/options.h	Thu Aug 20 03:57:37 1998
@@ -54,6 +54,8 @@
     int shm_coprocess;
     const char *set_filename;
     const char *comment_string;
+    int throw_keyid;  /* throw keyid field of encrypted packets */
+    char *firstlocusr;  /* first local user id (from --local-user) */
 } opt;
 
 
--- ./g10/encode.c.ORIG	Tue Aug 11 17:18:15 1998
+++ ./g10/encode.c	Thu Aug 20 05:38:12 1998
@@ -390,6 +390,8 @@
 		    pubkey_algo_to_string(enc->pubkey_algo), ustr );
 		m_free(ustr);
 	    }
+	    if (opt.throw_keyid)
+	       memset (enc->keyid, 0, sizeof(enc->keyid));
 	    /* and write it */
 	    init_packet(&pkt);
 	    pkt.pkttype = PKT_PUBKEY_ENC;

[----- gnupg-0.3.4-throw-keyid.diff -----]

                                                   Nimrod




More information about the Gnupg-devel mailing list