Verify key fingerprints.
authormdw <mdw>
Tue, 13 Sep 2005 15:25:39 +0000 (15:25 +0000)
committermdw <mdw>
Tue, 13 Sep 2005 15:25:39 +0000 (15:25 +0000)
key.1
keyutil.c

diff --git a/key.1 b/key.1
index 07237a7..785021e 100644 (file)
--- a/key.1
+++ b/key.1
@@ -117,6 +117,14 @@ is one of:
 .IR hash ]
 .RI [ tag ...]
 .br
+.B verify
+.RB [ \-f
+.IR filter ]
+.RB [ \-a
+.IR hash ]
+.I tag
+.I fingerprint
+.br
 .B tidy
 .br
 .B extract
@@ -301,7 +309,9 @@ command.
 .B hash
 The hash functions which can be used with the
 .B fingerprint
-command.
+and
+.B verify
+commands.
 .TP
 .B ec
 The built-in elliptic curves which can be used with the
@@ -613,7 +623,7 @@ Finally, the
 option can be given, in which case the parameters are taken directly
 from the provided group specification, which may either be the the name
 of one of the built-in groups (say
-.B "key add \-a dh\-param \-C list 42"
+.B "key show dh"
 for a list) or a triple
 .RI ( p ,\  q ,\  g ).
 separated by commas.  No random generation is done in this case: the
@@ -715,7 +725,7 @@ A
 can be given explicitly (in which case
 .RB ` \-b '
 is ignored).  It can either be the name of a built-in curve (say
-.B "key add \-a ec\-param \-C list 42"
+.B "key show ec"
 for a list of curve names) or a full specification.  The curve is
 checked for correctness and security according to the SEC1
 specification: failed checks cause a warning to be issued to standard
@@ -868,7 +878,7 @@ decrypt locked keys.  Make sure nobody is looking over your shoulder
 when you do this!
 .SS "fingerprint"
 Reports a fingerprint (secure hash) on components of requested keys.
-The following option is supported:
+The following options are supported:
 .TP
 .BI "\-f, \-\-filter " filter
 Specifies a filter.  Only keys and key components which match the filter
@@ -877,7 +887,7 @@ components.
 .TP
 .BI "\-a, \-\-algorithm " hash
 Names the hashing algorithm.  Run
-.B hashsum -a list
+.B key show hash
 for a list of hashing algorithms.  The default is
 .BR rmd160 .
 .PP
@@ -886,6 +896,24 @@ command line arguments.  If no key tags are given, all keys which match
 the filter are fingerprinted.  See
 .BR keyring (5)
 for a description of how key fingerprints are computed.
+.SS "verify"
+Check a key's fingerprint against a reference copy.  The following
+options are supported:
+.TP
+.BI "\-f, \-\-filter " filter
+Specifies a filter.  Only key components which match the filter are
+hashed.  The default is to only fingerprint nonsecret components.  An
+error is reported if no part of the key matches.
+.TP
+.BI "\-a, \-\-algorithm " hash
+Names the hashing algorithm.  Run
+.B key show hash
+for a list of hashing algorithms.  The default is
+.BR rmd160 .
+.PP
+The reference fingerprint is given as hex, in upper or lower case.  The
+hash may contain hyphens, colons and whitespace.  Other characters are
+not permitted.
 .SS "tidy"
 Simply reads the keyring from file and writes it back again.  This has
 the effect of removing any deleted keys from the file.
index 5e1fa66..1ead08d 100644 (file)
--- a/keyutil.c
+++ b/keyutil.c
@@ -31,6 +31,7 @@
 
 #include "config.h"
 
+#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1695,6 +1696,101 @@ static int cmd_finger(int argc, char *argv[])
   return (rc);
 }
 
+/* --- @cmd_verify@ --- */
+
+static unsigned xdigit(char c)
+{
+  if ('A' <= c && c <= 'Z') return (c + 10 - 'A');
+  if ('a' <= c && c <= 'z') return (c + 10 - 'a');
+  if ('0' <= c && c <= '9') return (c - '0');
+  return (~0u);
+}
+
+static void unhexify(octet *q, char *p, size_t n)
+{
+  unsigned a = 0;
+  int i = 0;
+
+  for (;;) {
+    if (*p == '-' || *p == ':' || isspace((unsigned char)*p)) {
+      p++;
+      continue;
+    }
+    if (!n && !*p)
+      break;
+    if (!*p)
+      die(EXIT_FAILURE, "hex string too short");
+    if (!isxdigit((unsigned char)*p))
+      die(EXIT_FAILURE, "bad hex string");
+    if (!n)
+      die(EXIT_FAILURE, "hex string too long");
+    a = (a << 4) | xdigit(*p++);
+    i++;
+    if (i == 2) {
+      *q++ = U8(a);
+      a = 0;
+      i = 0;
+      n--;
+    }
+  }
+}
+
+static int cmd_verify(int argc, char *argv[])
+{
+  key_file f;
+  int rc = 0;
+  const gchash *ch = &rmd160;
+  ghash *h;
+  key *k;
+  octet *buf;
+  const octet *fpr;
+  key_filter kf = { KF_NONSECRET, KF_NONSECRET };
+
+  for (;;) {
+    static struct option opt[] = {
+      { "filter",      OPTF_ARGREQ,    0,      'f' },
+      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'f': {
+       char *p;
+       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
+       if (err || *p)
+         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
+      } break;
+      case 'a':
+       if ((ch = ghash_byname(optarg)) == 0)
+         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
+       break;
+      default:
+       rc = 1;
+       break;
+    }
+  }
+
+  argv += optind; argc -= optind;
+  if (rc || argc != 2)
+    die(EXIT_FAILURE, "Usage: verify [-f FILTER] TAG FINGERPRINT");
+
+  doopen(&f, KOPEN_READ);
+
+  if ((k = key_bytag(&f, argv[0])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[0]);
+  buf = xmalloc(ch->hashsz);
+  unhexify(buf, argv[1], ch->hashsz);
+  h = GH_INIT(ch);
+  if (!key_fingerprint(k, h, &kf))
+    die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)");
+  fpr = GH_DONE(h, 0);
+  if (memcmp(fpr, buf, ch->hashsz) != 0)
+    die(EXIT_FAILURE, "key fingerprint mismatch");
+  return (0);
+}
+  
 /* --- @cmd_comment@ --- */
 
 static int cmd_comment(int argc, char *argv[])
@@ -1949,6 +2045,13 @@ Options:\n\
 -a, --algorithm=HASH   Use the named HASH algorithm.\n\
                          ($ show hash for list.)\n\
 " },
+  { "verify", cmd_verify, "verify [-f FILTER] TAG FINGERPRINT", "\
+Options:\n\
+\n\
+-f, --filter=FILT      Only hash key components matching FILT.\n\
+-a, --algorithm=HASH   Use the named HASH algorithm.\n\
+                         ($ show hash for list.)\n\
+" },
   { "extract", cmd_extract, "extract [-f FILTER] FILE [TAG...]", "\
 Options:\n\
 \n\