A little background: Among the many ways a signature can fail to verify is the user trying to verify with the wrong public key. In a setup like signify where users may be expected (required) at times to specify the public key, I expect this to be one of the leading failure modes. (Somewhere on this list is also using the wrong private key to create the signature.)
This can be a frustrating error because the only message you get back is "signature failed". The obvious solution is to encode some identifier information into the key and signature files. That provides a quick check where we can easily say "this public key belongs to X, but the signature was created by Y". Why doesn't signify do this? Because that identity isn't trusted. Just because a public key says it came from root@openbsd doesn't mean it did. I didn't want to open up a social engineering avenue whereby somebody provides a user with a backdoor pkg and matching public key, allegedly from root@openbsd. "Hey, openbsd is using a new key now, but as you can see, it comes from them." Nothing in a signify key or signature should be mistaken as a voucher for its own integrity. As a concession to usability, I did include a comment line in the files. If you accidentally mix up some key files, for whatever reason, maybe that can help set you straight. The signify tool itself ignores this line, as documented. Now we're back to asking, can this be used to trick the user? I was hoping that users would know the comment isn't to be trusted, but that may be asking too much. To that end, I think the comment should be marked as untrusted, and signify should even check that it says untrusted. Hopefully this makes it a little harder to con somebody into believing the comment actually should be trusted. Is this really necessary? Honestly, I think so. The weakest link here is an adversary's ability to trick the user into using the wrong key; I don't want to assist them in any way. (I'm also open to reconsidering whether keys should include identifiers. Perhaps a random id created during key generation? Just enough to say "you're using the wrong key.") Index: signify.c =================================================================== RCS file: /cvs/src/usr.bin/signify/signify.c,v retrieving revision 1.12 diff -u -p -r1.12 signify.c --- signify.c 6 Jan 2014 01:50:54 -0000 1.12 +++ signify.c 30 Dec 2013 16:14:25 -0000 @@ -38,6 +38,9 @@ #define PKALG "Ed" #define KDFALG "BK" +#define COMMENTHDR "untrusted comment:" +#define COMMENTHDRLEN 18 + struct enckey { uint8_t pkalg[2]; uint8_t kdfalg[2]; @@ -118,8 +121,9 @@ readb64file(const char *filename, void * if (rv == -1) err(1, "read from %s", filename); commentend = strchr(b64, '\n'); - if (!commentend) - errx(1, "no newline in %s", filename); + if (!commentend || commentend - b64 <= COMMENTHDRLEN || + memcmp(b64, COMMENTHDR, COMMENTHDRLEN)) + errx(1, "invalid comment in %s", filename); rv = b64_pton(commentend + 1, buf, len); if (rv != len) errx(1, "invalid b64 encoding in %s", filename); @@ -172,7 +176,8 @@ writeb64file(const char *filename, const int fd, rv; fd = xopen(filename, O_CREAT|O_EXCL|O_NOFOLLOW|O_RDWR, mode); - snprintf(header, sizeof(header), "signify -- %s\n", comment); + snprintf(header, sizeof(header), "%s signify %s\n", COMMENTHDR, + comment); writeall(fd, header, strlen(header), filename); if ((rv = b64_ntop(buf, len, b64, sizeof(b64)-1)) == -1) errx(1, "b64 encode failed");