On 5/29/21 2:26 AM, Theo de Raadt wrote:
Why does anyone require this functionality?

Within OpenWrt we store keys based on fingerprint (/etc/opkg/keys/<fingerprint>). If you verify a signature the key is selected based on the signatures public key fingerprint. This way we support storing multiple public keys on a device, e.g. one for sysupgrades, one for package repositories, etc.

Another approach which could make the -F functionality obsolete would be to iterate over all stored keys and see if one works out. I'll think about that but as a drop-in replacement this would be easiest.

(minus the irony the additional feature is coming from a "slimmed" clone)

Adding the feature is cheaper (as in smaller) than using a shell script[1] to determine the fingerprint, since we don't ship base64 in our distribution.

I guess the best solution is to fix signifys currently broken VERIFY_ONLY (aka VERIFYONLY) option and include base64 by default. Resulting in a net-negative size change and allow us to no longer maintain usign.

[1]: tail -n 1 key-build.pub | base64 -d | dd skip=2 count=8 bs=1 2>/dev/null | hexdump -ve '1/1 "%.2x"'


Paul Spooren <m...@aparcar.org> wrote:

To know the fingerprint used for a sec/pub/sig the option `-F` is added
which works in combination with `-s`, `-p` or `-x`. It will load the
file and and print the used fingerprint in hex.

This feature was ported over from OpenWrt's usign[0], which is a slimmed
simpler implementation of `signify`.

[0]: https://git.openwrt.org/project/usign.git

Signed-off-by: Paul Spooren <m...@aparcar.org>
---
  signify.c | 46 +++++++++++++++++++++++++++++++++++++++++++---
  1 file changed, 43 insertions(+), 3 deletions(-)

diff --git a/signify.c b/signify.c
index 8e54737..0f88ee4 100644
--- a/signify.c
+++ b/signify.c
@@ -84,7 +84,8 @@ usage(const char *error)
            "\t%1$s -G [-n] [-c comment] -p pubkey -s seckey\n"
            "\t%1$s -S [-enz] [-x sigfile] -s seckey -m message\n"
  #endif
-           "\t%1$s -V [-eqz] [-p pubkey] [-t keytype] [-x sigfile] -m 
message\n",
+           "\t%1$s -V [-eqz] [-p pubkey] [-t keytype] [-x sigfile] -m 
message\n"
+           "\t%1$s -F [-p pubkey] [-s seckey ] [-x sigfile]\n",
            getprogname());
        exit(1);
  }
@@ -547,6 +548,35 @@ verifysimple(const char *pubkeyfile, const char *msgfile, 
const char *sigfile,
        free(msg);
  }
+static int
+fingerprint(const char *seckeyfile, const char *pubkeyfile, const char 
*sigfile)
+{
+       struct sig sig;
+       struct pubkey pubkey;
+       struct enckey enckey;
+       uint8_t *fp;
+
+       if (seckeyfile) {
+               readb64file(seckeyfile, &enckey, sizeof(enckey), NULL);
+               fp = enckey.keynum;
+       } else if (pubkeyfile) {
+               readb64file(pubkeyfile, &pubkey, sizeof(pubkey), NULL);
+               fp = pubkey.keynum;
+       } else if (sigfile) {
+               readb64file(sigfile, &sig, sizeof(sig), NULL);
+               fp = sig.keynum;
+       } else
+               return 1;
+
+       int i;
+       for (i = 0; i < KEYNUMLEN; i++)
+       {
+               fprintf(stdout, "%02x", fp[i]);
+       }
+       fprintf(stdout, "\n");
+       return 0;
+}
+
  static uint8_t *
  verifyembedded(const char *pubkeyfile, const char *sigfile,
      int quiet, unsigned long long *msglenp, const char *keytype)
@@ -769,13 +799,14 @@ main(int argc, char **argv)
                CHECK,
                GENERATE,
                SIGN,
-               VERIFY
+               VERIFY,
+               FINGERPRINT
        } verb = NONE;
if (pledge("stdio rpath wpath cpath tty", NULL) == -1)
                err(1, "pledge");
- while ((ch = getopt(argc, argv, "CGSVzc:em:np:qs:t:x:")) != -1) {
+       while ((ch = getopt(argc, argv, "CGSVFzc:em:np:qs:t:x:")) != -1) {
                switch (ch) {
  #ifndef VERIFYONLY
                case 'C':
@@ -802,6 +833,11 @@ main(int argc, char **argv)
                                usage(NULL);
                        verb = VERIFY;
                        break;
+               case 'F':
+                       if (verb)
+                               usage(NULL);
+                       verb = FINGERPRINT;
+                       break;
                case 'c':
                        comment = optarg;
                        break;
@@ -909,6 +945,10 @@ main(int argc, char **argv)
                            quiet, keytype);
                }
                break;
+       case FINGERPRINT:
+               if (!!seckeyfile + !!pubkeyfile + !!sigfile != 1)
+                       usage("Need one secret/public key or signature");
+               return fingerprint(seckeyfile, pubkeyfile, sigfile);
        default:
                if (pledge("stdio", NULL) == -1)
                        err(1, "pledge");
--
2.30.2


Reply via email to