sigchk

sign and check files using ed25519
git clone git://z3bra.org/sick
Log | Files | Refs | Submodules | README | LICENSE

commit aac44022b75173cad5a9f45d99245505147bc032
parent be05c7998b1e7b6c601aef8d9728939fdc0a0ddb
Author: z3bra <willyatmailoodotorg>
Date:   Thu Apr 28 21:55:37 2016

Add a magic string to check signature presence

In order to check wether a file has been signed or not, we write a magic
string between the file and the signature. As the signature is always 64
bytes long, when can check if the bytes before the 64 last bytes of a file
match the magic. If it does, it means our file is already signed.

This will prevent from signing files twice, or checking unsigned files
against the whole keyring.

Diffstat:
 sick.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/sick.c b/sick.c @@ -15,6 +15,7 @@ #define PRIVSIZ ((PUBSIZ) * 2) #define SIGSIZ 64 +#define MAGIC "0xdeadca7" #define DEFAULT_ALIAS "ed25519" #define KEYRING (getenv("KEYRING")?getenv("KEYRING"):"./keyring") @@ -30,6 +31,7 @@ enum { void usage(char *name); char *base_name(char *path); +int check_magic(char *file); unsigned char *read_sig(char *file); int keygen(char *alias); int sign(char *file, char *key); @@ -52,6 +54,37 @@ base_name(char *path) return b ? b + 1 : path; } +int +check_magic(char *file) +{ + int fd = 0, is_magic = -1; + struct stat sb; + char *magic = NULL; + + if (stat(file, &sb) < 0) { + perror(file); + return NULL; + } + + magic = malloc(strlen(MAGIC)); + if (magic == NULL) + return -1; + + fd = open(file, O_RDONLY); + lseek(fd, sb.st_size - 64 - strlen(MAGIC), SEEK_SET); + if (read(fd, magic, strlen(MAGIC)) < (unsigned int)strlen(MAGIC)) { + perror(file); + close(fd); + return NULL; + } + close(fd); + + is_magic = strcmp(magic, MAGIC); + + free(magic); + return is_magic; +} + unsigned char * read_sig(char *file) { @@ -175,6 +208,11 @@ sign(char *file, char *key) free(msg); return fd; } + if (write(fd, MAGIC, strlen(MAGIC)) < (unsigned int)strlen(MAGIC)) { + perror(file); + free(msg); + return -1; + } if (write(fd, sig, 64) < 64) { perror(file); free(msg); @@ -232,6 +270,12 @@ check(char *file, char *keyring) struct dirent *dt = NULL; char path[PATH_MAX]; + if (check_magic(file) != 0) + { + fprintf(stderr, "%s: Not signed\n", file); + return -1; + } + dirp = opendir(keyring); if (dirp == NULL) { perror(keyring); @@ -304,7 +348,7 @@ main(int argc, char **argv) break; case ACTION_SIGN: /* TODO: only check the pubkey matchng the private */ - if (check(*argv, keyring) != 0) { + if (check_magic(*argv) != 0) { sign(*argv, key ? key : DEFAULT_ALIAS ".key"); } else { fprintf(stderr, "%s: Already signed\n", *argv);