From e705502ad014949c8eaebee7b4b5d56c05607f11 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Thu, 19 Nov 2015 13:30:16 -0800 Subject: [PATCH] This might be useful. --- tools/half-sign.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tools/half-sign.c diff --git a/tools/half-sign.c b/tools/half-sign.c new file mode 100644 index 000000000..561fa22be --- /dev/null +++ b/tools/half-sign.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include + +// Sign with SHA1 +#define HASH_SIZE 20 + +void usage() { + printf("half-sign [binary hash file]\n"); + printf("\n"); + printf(" Computes and prints a binary RSA signature over data given the SHA1 hash of\n"); + printf(" the data as input.\n"); + printf("\n"); + printf(" should be PEM encoded.\n"); + printf("\n"); + printf(" The input SHA1 hash should be %d bytes in length. If no binary hash file is\n", HASH_SIZE); + printf(" specified, it will be read from stdin.\n"); + exit(1); +} + +void sign_hashed_data(EVP_PKEY *signing_key, unsigned char *md, size_t mdlen) { + // cribbed from the openssl EVP_PKEY_sign man page + EVP_PKEY_CTX *ctx; + unsigned char *sig; + size_t siglen; + + /* NB: assumes signing_key, md and mdlen are already set up + * and that signing_key is an RSA private key + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL); + if ((!ctx) + || (EVP_PKEY_sign_init(ctx) <= 0) + || (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) + || (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()) <= 0)) { + fprintf(stderr, "Failure establishing ctx for signature\n"); + exit(1); + } + + /* Determine buffer length */ + if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0) { + fprintf(stderr, "Unable to determine buffer length for signature\n"); + exit(1); + } + + sig = OPENSSL_malloc(siglen); + + if (!sig) { + fprintf(stderr, "Malloc failed\n"); + exit(1); + } + + if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0) { + fprintf(stderr, "Signature error\n"); + exit(1); + } + + /* Signature is siglen bytes written to buffer sig */ + fwrite(sig, siglen, 1, stdout); +} + +EVP_PKEY *read_private_key(char *filename) { + FILE *keyfile; + EVP_PKEY *privkey; + keyfile = fopen(filename, "r"); + if (!keyfile) { + fprintf(stderr, "Failed to open private key.pem file %s\n", filename); + exit(1); + } + privkey = PEM_read_PrivateKey(keyfile, NULL, NULL, NULL); + if (!privkey) { + fprintf(stderr, "Failed to read PEM private key from %s\n", filename); + exit(1); + } + if (EVP_PKEY_type(privkey->type) != EVP_PKEY_RSA) { + fprintf(stderr, "%s was a non-RSA key\n", filename); + exit(1); + } + return privkey; +} + +int main(int argc, char *argv[]) { + FILE *input; + unsigned char *buffer; + int test; + EVP_PKEY *privkey; + if (argc > 3 || argc < 2) + usage(); + if (argc < 3 || strcmp(argv[2],"-") == 0) + input = stdin; + else { + input = fopen(argv[2], "r"); + if (!input) usage(); + } + privkey = read_private_key(argv[1]); + buffer = malloc(HASH_SIZE); + if (!buffer) { + fprintf(stderr, "Argh, malloc failed\n"); + exit(1); + } + if (fread(buffer, HASH_SIZE, 1, input) != 1) { + perror("half-sign: Failed to read SHA1 from input\n"); + exit(1); + } + + test = fgetc(input); + if (test != EOF && test != '\n') { + fprintf(stderr,"Error, more than %d bytes fed to half-sign\n", HASH_SIZE); + fprintf(stderr,"Last byte was :%d\n" , (int) test); + exit(1); + } + sign_hashed_data(privkey, buffer, HASH_SIZE); + return 0; +}