Kevin J. McCarthy wrote:
> I'll probably wait until the oppenc series is committed to push this
> one, because the two patches step on each other a bit.  But I wanted to
> send this out for review and comments.

With oppenc in, I've merged conflicts and added a few more changes.
Attached is a revised patch.

This version changes $pgp_long_ids to default on.  However, that option
now really only controls the display of the keyID in the key selection
menu and in a few other small places.  I've added a note to the option
mentioning this.

Overall, I think it's a good idea to transition to fingerprints
internally.  The only possible downside I can think of is that the
command line invocation gets longer.  Currently we use a HUGE_STRING to
hold the command, which is only 5120 bytes.  Using fingerprints that
limits us to only about 120 keys.

Is this something to be concerned about?  Current command lines can be
much larger, so I suppose we could double that if this is a problem.
Feedback?

Thanks,

-Kevin
# HG changeset patch
# User Kevin McCarthy <[email protected]>
# Date 1424896437 28800
#      Wed Feb 25 12:33:57 2015 -0800
# Node ID 546e4e07adad63a873a9dcc9d4044d5106933d9d
# Parent  e3e6febd8240ec9b304e3d5996a5215b8a10ba26
Use fingerprints instead of keyIDs internally. (see #3695)

Add a helper function, pgp_fpr_or_lkeyid(), that returns the fingerprint
if available, otherwise falls back to the long key id.  Convert Mutt to
use that value for pgp command invocation.

Change gpgme to use an equivalent crypt_fpr_or_lkeyid() function in a
couple places too (for keylist generation and sign-as key selection).

Update documentation to mention fingerprints and the --with-fingerprint
option for gpg invocation.

Change pgp_long_ids to default: yes, but add a note mentioning
it's only used for the display of key IDs in a few places.

diff --git a/crypt-gpgme.c b/crypt-gpgme.c
--- a/crypt-gpgme.c
+++ b/crypt-gpgme.c
@@ -214,16 +214,34 @@
   const char *s = "";
 
   if (k->kobj && k->kobj->subkeys)
     s = k->kobj->subkeys->fpr;
 
   return s;
 }
 
+/* Returns the fingerprint if available, otherwise
+ * returns the long keyid.
+ */
+static const char *crypt_fpr_or_lkeyid(crypt_key_t *k)
+{
+  const char *s = "????????????????";
+
+  if (k->kobj && k->kobj->subkeys)
+  {
+    if (k->kobj->subkeys->fpr)
+      s = k->kobj->subkeys->fpr;
+    else
+      s = k->kobj->subkeys->keyid;
+  }
+
+  return s;
+}
+
 /* Parse FLAGS and return a statically allocated(!) string with them. */
 static char *crypt_key_abilities (int flags)
 {
   static char buff[3];
 
   if (!(flags & KEYFLAG_CANENCRYPT))
     buff[0] = '-';
   else if (flags & KEYFLAG_PREFER_SIGNING)
@@ -2895,34 +2913,34 @@
 {
   crypt_key_t **s = (crypt_key_t **) a;
   crypt_key_t **t = (crypt_key_t **) b;
   int r;
 
   if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
     return r > 0;
   else
-    return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
+    return mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid 
(*t)) > 0;
 }
 
 static int crypt_compare_address (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
                                          :  _crypt_compare_address (a, b));
 }
 
 
 /* Compare two key IDs and the addresses to be used for sorting. */
 static int _crypt_compare_keyid (const void *a, const void *b)
 {
   crypt_key_t **s = (crypt_key_t **) a;
   crypt_key_t **t = (crypt_key_t **) b;
   int r;
 
-  if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
+  if ((r = mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid 
(*t))))
     return r > 0;
   else
     return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
 }
 
 static int crypt_compare_keyid (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
@@ -2986,17 +3004,17 @@
     tt = (*t)->kobj->subkeys->timestamp;
   if (ts > tt)
     return 1;
   if (ts < tt)
     return 0;
 
   if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
     return r > 0;
-  return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
+  return (mutt_strcasecmp (crypt_fpr_or_lkeyid ((*s)), crypt_fpr_or_lkeyid 
((*t)))) > 0;
 }
 
 static int crypt_compare_trust (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
                                       : _crypt_compare_trust (a, b));
 }
 
@@ -4427,17 +4445,17 @@
       if (k_info == NULL)
         {
           FREE (&keylist);
           rfc822_free_address (&addr);
           return NULL;
         }
 
 
-      keyID = crypt_fpr (k_info);
+      keyID = crypt_fpr_or_lkeyid (k_info);
 
 #if 0
       if (k_info->flags & KEYFLAG_ISX509)
         *r_application &= ~APPLICATION_PGP;
       if (!(k_info->flags & KEYFLAG_ISX509))
         *r_application &= ~APPLICATION_SMIME;
 #endif
       
@@ -4667,17 +4685,18 @@
       msg->security |= SIGN;
       break;
 
     case 'a': /* sign (a)s */
       if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
                                   is_smime? APPLICATION_SMIME:APPLICATION_PGP,
                                   NULL)))
       {
-        snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid 
(p));
+        snprintf (input_signas, sizeof (input_signas), "0x%s",
+            crypt_fpr_or_lkeyid (p));
         mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, 
input_signas);
         crypt_free_key (&p); 
 
         msg->security |= SIGN;
       }
       *redraw = REDRAW_FULL;
       break;
 
diff --git a/doc/manual.xml.head b/doc/manual.xml.head
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -3632,18 +3632,18 @@
 destination address, or because, for some reasons, you need to override
 the key Mutt would normally use.  The <command>crypt-hook</command>
 command provides a method by which you can specify the ID of the public
 key to be used when encrypting messages to a certain recipient.
 </para>
 
 <para>
 The meaning of <emphasis>keyid</emphasis> is to be taken broadly in this
-context: You can either put a numerical key ID here, an e-mail address,
-or even just a real name.
+context: You can either put a numerical key ID or fingerprint here, an
+e-mail address, or even just a real name.
 </para>
 
 </sect1>
 
 <sect1 id="push">
 <title>Adding Key Sequences to the Keyboard Buffer</title>
 
 <para>Usage:</para>
diff --git a/init.h b/init.h
--- a/init.h
+++ b/init.h
@@ -1737,17 +1737,17 @@
   ** The PGP command formats have their own set of \fCprintf(3)\fP-like 
sequences:
   ** .dl
   ** .dt %p .dd Expands to PGPPASSFD=0 when a pass phrase is needed, to an 
empty
   **            string otherwise. Note: This may be used with a %? construct.
   ** .dt %f .dd Expands to the name of a file containing a message.
   ** .dt %s .dd Expands to the name of a file containing the signature part
   ** .          of a \fCmultipart/signed\fP attachment when verifying it.
   ** .dt %a .dd The value of $$pgp_sign_as.
-  ** .dt %r .dd One or more key IDs.
+  ** .dt %r .dd One or more key IDs (or fingerprints if available).
   ** .de
   ** .pp
   ** For examples on how to configure these formats for the various versions
   ** of PGP which are floating around, see the pgp and gpg sample 
configuration files in
   ** the \fCsamples/\fP subdirectory which has been installed on your system
   ** alongside the documentation.
   ** (PGP only)
   */
@@ -1846,46 +1846,49 @@
   ** (PGP only)
   */
   { "pgp_list_pubring_command", DT_STR, R_NONE, UL &PgpListPubringCommand, 0},
   /*
   ** .pp
   ** This command is used to list the public key ring's contents.  The
   ** output format must be analogous to the one used by
   ** .ts
-  ** gpg --list-keys --with-colons
+  ** gpg --list-keys --with-colons --with-fingerprint
   ** .te
   ** .pp
   ** This format is also generated by the \fCpgpring\fP utility which comes
   ** with mutt.
   ** .pp
   ** This is a format string, see the $$pgp_decode_command command for
   ** possible \fCprintf(3)\fP-like sequences.
   ** (PGP only)
   */
   { "pgp_list_secring_command",        DT_STR, R_NONE, UL 
&PgpListSecringCommand, 0},
   /*
   ** .pp
   ** This command is used to list the secret key ring's contents.  The
   ** output format must be analogous to the one used by:
   ** .ts
-  ** gpg --list-keys --with-colons
+  ** gpg --list-keys --with-colons --with-fingerprint
   ** .te
   ** .pp
   ** This format is also generated by the \fCpgpring\fP utility which comes
   ** with mutt.
   ** .pp
   ** This is a format string, see the $$pgp_decode_command command for
   ** possible \fCprintf(3)\fP-like sequences.
   ** (PGP only)
   */
-  { "pgp_long_ids",    DT_BOOL, R_NONE, OPTPGPLONGIDS, 0 },
+  { "pgp_long_ids",    DT_BOOL, R_NONE, OPTPGPLONGIDS, 1 },
   /*
   ** .pp
   ** If \fIset\fP, use 64 bit PGP key IDs, if \fIunset\fP use the normal 32 
bit key IDs.
+  ** NOTE: Internally, Mutt has transitioned to using fingerprints (or long 
key IDs
+  ** as a fallback).  This option now only controls the display of key IDs
+  ** in the key selection menu and few other places.
   ** (PGP only)
   */
   { "pgp_mime_auto", DT_QUAD, R_NONE, OPT_PGPMIMEAUTO, M_ASKYES },
   /*
   ** .pp
   ** This option controls whether Mutt will prompt you for
   ** automatically sending a (signed/encrypted) message using
   ** PGP/MIME when inline (traditional) fails (for any reason).
@@ -2150,18 +2153,18 @@
   ** When \fIset\fP, postponed messages that are marked for encryption will be
   ** encrypted using the key in $$postpone_encrypt_as before saving.
   ** (Crypto only)
   */
   { "postpone_encrypt_as", DT_STR,  R_NONE, UL &PostponeEncryptAs, 0 },
   /*
   ** .pp
   ** This is the key used to encrypt postponed messages.  It should be in
-  ** keyid form (e.g. 0x00112233 for PGP or the hash-value that OpenSSL
-  ** generates for S/MIME).
+  ** keyid or fingerprint form (e.g. 0x00112233 for PGP or the
+  ** hash-value that OpenSSL generates for S/MIME).
   ** (Crypto only)
   */
 #ifdef USE_SOCKET
   { "preconnect",      DT_STR, R_NONE, UL &Preconnect, UL 0},
   /*
   ** .pp
   ** If \fIset\fP, a shell command to be executed if mutt fails to establish
   ** a connection to the server. This is useful for setting up secure
diff --git a/pgp.c b/pgp.c
--- a/pgp.c
+++ b/pgp.c
@@ -151,16 +151,37 @@
 char *_pgp_keyid(pgp_key_t k)
 {
   if(option(OPTPGPLONGIDS))
     return k->keyid;
   else
     return (k->keyid + 8);
 }
 
+char *pgp_fingerprint(pgp_key_t k)
+{
+  k = _pgp_parent(k);
+
+  return k->fingerprint;
+}
+
+/* Grab the longest key identifier available: fingerprint or else
+ * the long keyid.
+ *
+ * The longest available should be used for internally identifying
+ * the key and for invoking pgp commands.
+ */
+char *pgp_fpr_or_lkeyid(pgp_key_t k)
+{
+  char *fingerprint;
+
+  fingerprint = pgp_fingerprint (k);
+  return fingerprint ? fingerprint : pgp_long_keyid (k);
+}
+
 /* ----------------------------------------------------------------------------
  * Routines for handing PGP input.
  */
 
 
 
 /* Copy PGP output messages and look for signs of a good signature */
 
@@ -1242,17 +1263,17 @@
 
     if (k_info == NULL)
     {
       FREE (&keylist);
       rfc822_free_address (&addr);
       return NULL;
     }
 
-    keyID = pgp_keyid (k_info);
+    keyID = pgp_fpr_or_lkeyid (k_info);
     
   bypass_selection:
     keylist_size += mutt_strlen (keyID) + 4;
     safe_realloc (&keylist, keylist_size);
     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",        
/* __SPRINTF_CHECKED__ */
             keyID);
     keylist_used = mutt_strlen (keylist);
 
@@ -1685,17 +1706,17 @@
       break;
 
     case 'a': /* sign (a)s */
       unset_option(OPTPGPCHECKTRUST);
 
       if ((p = pgp_ask_for_key (_("Sign as: "), NULL, 0, PGP_SECRING)))
       {
         snprintf (input_signas, sizeof (input_signas), "0x%s",
-            pgp_keyid (p));
+            pgp_fpr_or_lkeyid (p));
         mutt_str_replace (&PgpSignAs, input_signas);
         pgp_free_key (&p);
 
         msg->security |= SIGN;
 
         crypt_pgp_void_passphrase ();  /* probably need a different passphrase 
*/
       }
       *redraw = REDRAW_FULL;
diff --git a/pgp.h b/pgp.h
--- a/pgp.h
+++ b/pgp.h
@@ -32,16 +32,18 @@
 BODY *pgp_decrypt_part (BODY *, STATE *, FILE *, BODY *);
 BODY *pgp_make_key_attachment (char *);
 const char *pgp_micalg (const char *fname);
 
 char *_pgp_keyid (pgp_key_t);
 char *pgp_keyid (pgp_key_t);
 char *pgp_short_keyid (pgp_key_t);
 char *pgp_long_keyid (pgp_key_t);
+char *pgp_fingerprint (pgp_key_t k);
+char *pgp_fpr_or_lkeyid (pgp_key_t k);
 
 
 int mutt_check_pgp (HEADER * h);
 
 int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **);
 
 /* int pgp_string_matches_hint (const char *s, LIST * hints); */
 
diff --git a/pgpkey.c b/pgpkey.c
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -301,18 +301,18 @@
   int r;
 
   pgp_uid_t **s = (pgp_uid_t **) a;
   pgp_uid_t **t = (pgp_uid_t **) b;
 
   if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr)))
     return r > 0;
   else
-    return (mutt_strcasecmp (_pgp_keyid ((*s)->parent),
-                            _pgp_keyid ((*t)->parent)) > 0);
+    return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent),
+                            pgp_fpr_or_lkeyid ((*t)->parent)) > 0);
 }
 
 static int pgp_compare_address (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_address (a, b)
                                       : _pgp_compare_address (a, b));
 }
 
@@ -320,18 +320,18 @@
 
 static int _pgp_compare_keyid (const void *a, const void *b)
 {
   int r;
 
   pgp_uid_t **s = (pgp_uid_t **) a;
   pgp_uid_t **t = (pgp_uid_t **) b;
 
-  if ((r = mutt_strcasecmp (_pgp_keyid ((*s)->parent), 
-                           _pgp_keyid ((*t)->parent))))
+  if ((r = mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), 
+                           pgp_fpr_or_lkeyid ((*t)->parent))))
     return r > 0;
   else
     return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0;
 }
 
 static int pgp_compare_keyid (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_keyid (a, b)
@@ -368,18 +368,18 @@
   if ((r = ((*s)->trust - (*t)->trust)))
     return r < 0;
   if ((r = ((*s)->parent->keylen - (*t)->parent->keylen)))
     return r < 0;
   if ((r = ((*s)->parent->gen_time - (*t)->parent->gen_time)))
     return r < 0;
   if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr)))
     return r > 0;
-  return (mutt_strcasecmp (_pgp_keyid ((*s)->parent), 
-                          _pgp_keyid ((*t)->parent))) > 0;
+  return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), 
+                          pgp_fpr_or_lkeyid ((*t)->parent))) > 0;
 }
 
 static int pgp_compare_trust (const void *a, const void *b)
 {
   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_trust (a, b)
                                       : _pgp_compare_trust (a, b));
 }
 
@@ -557,17 +557,18 @@
       {
        safe_fclose (&devnull);
        mutt_perror _("Can't create temporary file");
        break;
       }
 
       mutt_message _("Invoking PGP...");
 
-      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s", pgp_keyid (pgp_principal_key 
(KeyTable[menu->current]->parent)));
+      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s",
+          pgp_fpr_or_lkeyid (pgp_principal_key 
(KeyTable[menu->current]->parent)));
 
       if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1,
                    fileno (fp), fileno (devnull), tmpbuf)) == -1)
       {
        mutt_perror _("Can't create filter");
        unlink (tempfile);
        safe_fclose (&fp);
        safe_fclose (&devnull);
@@ -720,17 +721,17 @@
   pid_t thepid;
   pgp_key_t key;
   unset_option (OPTPGPCHECKTRUST);
 
   key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING);
 
   if (!key)    return NULL;
 
-  snprintf (tmp, sizeof (tmp), "0x%s", pgp_keyid (pgp_principal_key (key)));
+  snprintf (tmp, sizeof (tmp), "0x%s", pgp_fpr_or_lkeyid (pgp_principal_key 
(key)));
   pgp_free_key (&key);
 
   if (!tempf)
   {
     mutt_mktemp (tempfb, sizeof (tempfb));
     tempf = tempfb;
   }
 

Attachment: signature.asc
Description: PGP signature

Reply via email to