hash-pipe/hash-pipe.c
2021-03-14 13:45:28 +01:00

91 lines
1.8 KiB
C

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#define BUF_SIZE 4096
void print_usage (void) {
dprintf(STDERR_FILENO, "Usage:\n"
"\n"
" hash-pipe ALGORITHM FILENAME LOGFILE\n"
"\n"
"where\n"
" ALGORITHM is an openssl Digest name, e.g. sha512\n"
" FILENAME is the name to display within the logfile\n"
" LOGFILE is a text file into which sha*sum-compatible hashes are to be appended\n");
}
int main (int argc, char **argv) {
if (argc != 4) {
print_usage();
exit(1);
}
const char *algo_name = argv[1];
const char *file_name = argv[2];
const char *log_name = argv[3];
/*
* determine the algorithm
*/
const EVP_MD *md = EVP_get_digestbyname(algo_name);
if (md == NULL) {
dprintf(STDERR_FILENO, "Unknown algorithm: %s\n", algo_name);
exit(1);
}
/*
* open the file for appending, create if necessary
*/
int fd = open(log_name, O_WRONLY | O_APPEND | O_CREAT, 0644);
if (fd == -1) {
dprintf(STDERR_FILENO, "Unable to open file for writing: %s\n", log_name);
}
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
uint8_t buf[BUF_SIZE];
ssize_t s;
while (true) {
s = read(STDIN_FILENO, buf, BUF_SIZE);
if (s == -1) {
dprintf(STDERR_FILENO, "Unknown error.\n");
exit(1);
} else if (s == 0) {
break;
}
/*
* add the chunk to the digest and transparently pass
* it to stdout
*/
EVP_DigestUpdate(mdctx, buf, s);
write(STDOUT_FILENO, buf, s);
}
/*
* convert to an ascii representation
*/
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);
for (int i = 0; i < md_len; i++) {
dprintf(fd, "%02x", md_value[i]);
}
dprintf(fd, " %s\n", file_name);
close(fd);
return 0;
}