Always pad fingerprints to 16 characters
[project/usign.git] / main.c
diff --git a/main.c b/main.c
index d177e976ee74f25b70d756b3c2bb81063f79140f..ebfdfb0809c4d8394b2254625d47649975d72000 100644 (file)
--- a/main.c
+++ b/main.c
@@ -57,6 +57,7 @@ static const char *pubkeyfile;
 static const char *pubkeydir;
 static const char *sigfile;
 static const char *seckeyfile;
+static const char *comment;
 static bool quiet;
 static enum {
        CMD_NONE,
@@ -66,7 +67,7 @@ static enum {
        CMD_GENERATE,
 } cmd = CMD_NONE;
 
-static uint64_t fingerprint_u64(uint8_t *data)
+static uint64_t fingerprint_u64(const uint8_t *data)
 {
        uint64_t val = 0;
 
@@ -128,13 +129,30 @@ get_file(const char *filename, char *buf, int buflen)
 
        len = fread(buf, 1, buflen - 1, f);
        buf[len] = 0;
+       fclose(f);
 }
 
 static bool
 get_base64_file(const char *file, void *dest, int size, void *buf, int buflen)
 {
        get_file(file, buf, buflen - 1);
-       return b64_pton(buf, dest, size) == size;
+       return b64_decode(buf, dest, size) == size;
+}
+
+static void write_file(const char *name, const uint8_t *fingerprint,
+                      const char *prefix, char *buf)
+{
+       FILE *f;
+
+       f = open_file(name, false);
+       fputs("untrusted comment: ", f);
+       if (comment)
+               fputs(comment, f);
+       else
+               fprintf(f, "%s %016"PRIx64, prefix,
+                       fingerprint_u64(fingerprint));
+       fprintf(f, "\n%s\n", buf);
+       fclose(f);
 }
 
 static int verify(const char *msgfile)
@@ -154,11 +172,12 @@ static int verify(const char *msgfile)
        if (!get_base64_file(sigfile, &sig, sizeof(sig), buf, sizeof(buf)) ||
            memcmp(sig.pkalg, "Ed", 2) != 0) {
                fprintf(stderr, "Failed to decode signature\n");
+               fclose(f);
                return 1;
        }
 
        if (!pubkeyfile) {
-               snprintf(buf, sizeof(buf), "%s/%"PRIx64, pubkeydir,
+               snprintf(buf, sizeof(buf), "%s/%016"PRIx64, pubkeydir,
                         fingerprint_u64(sig.fingerprint));
                pubkeyfile = buf;
        }
@@ -166,6 +185,7 @@ static int verify(const char *msgfile)
        if (!get_base64_file(pubkeyfile, &pkey, sizeof(pkey), buf, sizeof(buf)) ||
            memcmp(pkey.pkalg, "Ed", 2) != 0) {
                fprintf(stderr, "Failed to decode public key\n");
+               fclose(f);
                return 1;
        }
 
@@ -200,7 +220,6 @@ static int sign(const char *msgfile)
        long mlen;
        void *m;
        int mfd;
-       FILE *out;
 
        if (!get_base64_file(seckeyfile, &skey, sizeof(skey), buf, sizeof(buf)) ||
            memcmp(skey.pkalg, "Ed", 2) != 0) {
@@ -229,12 +248,10 @@ static int sign(const char *msgfile)
        munmap(m, mlen);
        close(mfd);
 
-       if (b64_ntop(&sig, sizeof(sig), buf, sizeof(buf)) < 0)
+       if (b64_encode(&sig, sizeof(sig), buf, sizeof(buf)) < 0)
                return 1;
 
-       out = open_file(sigfile, false);
-       fprintf(out, "untrusted comment: signed by key %"PRIx64"\n%s\n", fingerprint_u64(sig.fingerprint), buf);
-       fclose(out);
+       write_file(sigfile, sig.fingerprint, "signed by key", buf);
 
        return 0;
 }
@@ -259,7 +276,7 @@ static int fingerprint(void)
        else
                return 1;
 
-       fprintf(stdout, "%"PRIx64"\n", fingerprint_u64(fp));
+       fprintf(stdout, "%016"PRIx64"\n", fingerprint_u64(fp));
        return 0;
 }
 
@@ -278,11 +295,16 @@ static int generate(void)
        FILE *f;
 
        f = fopen("/dev/urandom", "r");
-       if (!f ||
-           fread(skey.fingerprint, sizeof(skey.fingerprint), 1, f) != 1 ||
+       if (!f) {
+               fprintf(stderr, "Can't open /dev/urandom\n");
+               return 1;
+       }
+
+       if (fread(skey.fingerprint, sizeof(skey.fingerprint), 1, f) != 1 ||
            fread(skey.seckey, EDSIGN_SECRET_KEY_SIZE, 1, f) != 1 ||
            fread(skey.salt, sizeof(skey.salt), 1, f) != 1) {
                fprintf(stderr, "Can't read data from /dev/urandom\n");
+               fclose(f);
                return 1;
        }
        if (f)
@@ -295,22 +317,18 @@ static int generate(void)
        sha512_add(&s, skey.seckey, sizeof(skey.seckey));
        memcpy(skey.checksum, sha512_final_get(&s), sizeof(skey.checksum));
 
-       if (b64_ntop(&skey, sizeof(skey), buf, sizeof(buf)) < 0)
+       if (b64_encode(&skey, sizeof(skey), buf, sizeof(buf)) < 0)
                return 1;
 
-       f = open_file(seckeyfile, false);
-       fprintf(f, "untrusted comment: secret key %"PRIx64"\n%s\n", fingerprint_u64(skey.fingerprint), buf);
-       fclose(f);
+       write_file(seckeyfile, skey.fingerprint, "private key", buf);
 
        memcpy(pkey.fingerprint, skey.fingerprint, sizeof(pkey.fingerprint));
        memcpy(pkey.pubkey, skey.seckey + 32, sizeof(pkey.pubkey));
 
-       if (b64_ntop(&pkey, sizeof(pkey), buf, sizeof(buf)) < 0)
+       if (b64_encode(&pkey, sizeof(pkey), buf, sizeof(buf)) < 0)
                return 1;
 
-       f = open_file(pubkeyfile, false);
-       fprintf(f, "untrusted comment: public key %"PRIx64"\n%s\n", fingerprint_u64(pkey.fingerprint), buf);
-       fclose(f);
+       write_file(pubkeyfile, pkey.fingerprint, "public key", buf);
 
        return 0;
 }
@@ -320,17 +338,18 @@ static int usage(const char *cmd)
        fprintf(stderr,
                "Usage: %s <command> <options>\n"
                "Commands:\n"
-               "  -V:          verify (needs at least -m and -p|-P)\n"
-               "  -S:          sign (needs at least -m and -s)\n"
-               "  -F:          print key fingerprint of public/secret key or signature\n"
-               "  -G:          generate a new keypair\n"
+               "  -V:                  verify (needs at least -m and -p|-P)\n"
+               "  -S:                  sign (needs at least -m and -s)\n"
+               "  -F:                  print key fingerprint of public/secret key or signature\n"
+               "  -G:                  generate a new keypair (needs at least -p and -s)\n"
                "Options:\n"
-               "  -m <file>:   message file\n"
-               "  -p <file>:   public key file (verify/fingerprint only)\n"
-               "  -P <path>:   public key directory (verify only)\n"
+               "  -c <comment>:        add comment to keys\n"
+               "  -m <file>:           message file\n"
+               "  -p <file>:           public key file (verify/fingerprint only)\n"
+               "  -P <path>:           public key directory (verify only)\n"
                "  -q:                  quiet (do not print verification result, use return code only)\n"
-               "  -s <file>:   secret key file (sign/fingerprint only)\n"
-               "  -x <file>:   signature file (defaults to <message file>.sig)\n"
+               "  -s <file>:           secret key file (sign/fingerprint only)\n"
+               "  -x <file>:           signature file (defaults to <message file>.sig)\n"
                "\n",
                cmd);
        return 1;
@@ -349,7 +368,7 @@ int main(int argc, char **argv)
        const char *msgfile = NULL;
        int ch;
 
-       while ((ch = getopt(argc, argv, "FGSVm:P:p:qs:x:")) != -1) {
+       while ((ch = getopt(argc, argv, "FGSVc:m:P:p:qs:x:")) != -1) {
                switch (ch) {
                case 'V':
                        set_cmd(argv[0], CMD_VERIFY);
@@ -363,6 +382,9 @@ int main(int argc, char **argv)
                case 'G':
                        set_cmd(argv[0], CMD_GENERATE);
                        break;
+               case 'c':
+                       comment = optarg;
+                       break;
                case 'm':
                        msgfile = optarg;
                        break;