Home
Software
Utilities
About
Reader (main.c)
https://centaur.pw/software/m18/main.c
[
Direct Link
]
/* Centaur M18 * 2/24/2026 * Version 1.0 * Jon Siragusa <jon@centaur.pw> * https://www.centaur.pw/ * * Copyright (C) Centaur, 2026. All Rights Reserved. * * main.c */ #define _GNU_SOURCE #include <getopt.h> #include <openssl/evp.h> #include <openssl/provider.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "color.h" #include "ftype.h" #include "md.h" #define MAX_STDIN_LEN 24576 int main(int argc, char **argv) { int op_string = 0; int op_uppercase = 0; int op_compare = 0; int op_checksum_file = 0; int op_standard_in = 0; int op_no_file_names = 0; int op_help = 0; int op_blake2s_256 = 0; int op_blake2b_512 = 0; int op_md4 = 0; int op_md5 = 0; int op_sha1 = 0; int op_sha224 = 0; int op_sha256 = 0; int op_sha384 = 0; int op_sha512_224 = 0; int op_sha512_256 = 0; int op_sha512 = 0; int op_sha3_224 = 0; int op_sha3_256 = 0; int op_sha3_384 = 0; int op_sha3_512 = 0; int op_sm3 = 0; int op_ripemd_160 = 0; int op_whirlpool = 0; int op_all = 0; OpenSSL_add_all_digests(); OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy"); if (legacy == NULL) printf("%s: warning: legacy provider not available\n", argv[0]); int i; int c; int opt; int AC = 0; char alg[16]; static struct option long_options[] = { {"string", no_argument, NULL, 's'}, {"uppercase", no_argument, NULL, 'u'}, {"compare", no_argument, NULL, 'c'}, {"checksum-file", no_argument, NULL, 'f'}, {"stdin", no_argument, NULL, 'i'}, {"no-file-names", no_argument, NULL, 'n'}, {"help", no_argument, NULL, 'h'}, {"blake2s-256", no_argument, NULL, 'k'}, {"blake2b-512", no_argument, NULL, 'b'}, {"md4", no_argument, NULL, '4'}, {"md5", no_argument, NULL, '5'}, {"sha1", no_argument, NULL, '1'}, {"sha224", no_argument, NULL, '2'}, {"sha256", no_argument, NULL, 'a'}, {"sha384", no_argument, NULL, '8'}, {"sha512-224", no_argument, NULL, 'd'}, {"sha512-256", no_argument, NULL, 'z'}, {"sha512", no_argument, NULL, 't'}, {"sha3-224", no_argument, NULL, 'y'}, {"sha3-256", no_argument, NULL, 'A'}, {"sha3-384", no_argument, NULL, '3'}, {"sha3-512", no_argument, NULL, 'T'}, {"sm3", no_argument, NULL, 'm'}, {"ripemd-160", no_argument, NULL, 'r'}, {"whirlpool", no_argument, NULL, 'w'}, {"all-algorithms", no_argument, NULL, 'x'}, {0, 0, 0, 0} }; char *providers[] = { "BLAKE2S-256", "BLAKE2B-512", "MD4", "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512-224", "SHA512-256", "SHA512", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512", "SM3", "RIPEMD160", "WHIRLPOOL" }; while ((c = getopt_long(argc, argv, "sucfinhkb4512a8dztyA3Tmrwx", long_options, &opt)) != -1) { switch (c) { case 's': op_string++; break; case 'u': op_uppercase++; break; case 'c': op_compare++; break; case 'f': op_checksum_file++; break; case 'i': op_standard_in++; break; case 'n': op_no_file_names++; break; case 'h': op_help++; break; case 'k': op_blake2s_256++; AC++; strcpy(alg, providers[0]); break; case 'b': op_blake2b_512++; AC++; strcpy(alg, providers[1]); break; case '4': op_md4++; AC++; strcpy(alg, providers[2]); break; case '5': op_md5++; AC++; strcpy(alg, providers[3]); break; case '1': op_sha1++; AC++; strcpy(alg, providers[4]); break; case '2': op_sha224++; AC++; strcpy(alg, providers[5]); break; case 'a': op_sha256++; AC++; strcpy(alg, providers[6]); break; case '8': op_sha384++; AC++; strcpy(alg, providers[7]); break; case 'd': op_sha512_224++; AC++; strcpy(alg, providers[8]); break; case 'z': op_sha512_256++; AC++; strcpy(alg, providers[9]); break; case 't': op_sha512++; AC++; strcpy(alg, providers[10]); break; case 'y': op_sha3_224++; AC++; strcpy(alg, providers[11]); break; case 'A': op_sha3_256++; AC++; strcpy(alg, providers[12]); break; case '3': op_sha3_384++; AC++; strcpy(alg, providers[13]); break; case 'T': op_sha3_512++; AC++; strcpy(alg, providers[14]); break; case 'm': op_sm3++; AC++; strcpy(alg, providers[15]); break; case 'r': op_ripemd_160++; AC++; strcpy(alg, providers[16]); break; case 'w': op_whirlpool++; AC++; strcpy(alg, providers[17]); break; case 'x': op_all++; AC += 18; break; case '?': break; default: break; } } if (op_help) { printf("Usage: %s [-sucfinhkb4512a8dztyA3Tmrwx] <file|string> <comparison-hash>\n", argv[0]); printf("Options:\n-s, --string\n-u, --uppercase\n-c, --compare\n-f, --checksum-file\n-i, --stdin\n-n, --no-file-names\n-h, --help\n-k, --blake2s-256\n-b, --blake2b-512\n-4, --md4\n-5, --md5\n-1, --sha1\n-2, --sha224\n-a, --sha256\n-8, --sha384\n-d, --sha512-224\n-z, --sha512-256\n-t, --sha512\n-y, --sha3-224\n-A, --sha3-256\n-3, --sha3-384\n-T, --sha3-512\n-m, --sm3\n-r, --ripemd-160\n-w, --whirlpool\n-x, --all-algorithms\n"); exit(EXIT_SUCCESS); } if (op_compare) { if (AC > 1) { printf("%s: only one algorithm may be specified for hash comparison\n", argv[0]); exit(EXIT_FAILURE); } else if (AC < 1) { printf("%s: no algorithm specified\n", argv[0]); exit(EXIT_FAILURE); } if (argc < 4) { printf("%s: invalid syntax for hash comparison\n", argv[0]); exit(EXIT_FAILURE); } char *hash = argv[argc - 1]; char *file = argv[argc - 2]; if (!op_string) { if (!strcasecmp(mdfile(EVP_MD_fetch(NULL, alg, (!strcmp(alg, "MD4") || !strcmp(alg, "WHIRLPOOL") ? "provider=legacy" : "provider=default")), argv[argc - 2], op_uppercase), hash)) { printf("%s: %s: file hash comparison %s%sPASSED%s\n", argv[0], file, BOLD, GREEN, RESET); exit(EXIT_SUCCESS); } else { printf("%s: %s: file hash comparison %s%sFAILED%s\n", argv[0], file, BOLD, RED, RESET); exit(EXIT_SUCCESS); } } else if (op_string) { if (!strcasecmp(mdstring(EVP_MD_fetch(NULL, alg, (!strcmp(alg, "MD4") || !strcmp(alg, "WHIRLPOOL") ? "provider=legacy" : "provider=default")), argv[argc - 2], op_uppercase), hash)) { printf("%s: string hash comparison %s%sPASSED%s\n", argv[0], BOLD, GREEN, RESET); exit(EXIT_SUCCESS); } else { printf("%s: string hash comparison %s%sFAILED%s\n", argv[0], BOLD, RED, RESET); exit(EXIT_SUCCESS); } } } if (op_checksum_file) { if (AC > 1) { printf("%s: only one algorithm may be specified for verifying checksum files\n", argv[0]); exit(EXIT_FAILURE); } else if (AC < 1) { printf("%s: no algorithm specified\n", argv[0]); exit(EXIT_FAILURE); } if (argc < 3) { printf("%s: invalid syntax for verifying checksum files\n", argv[0]); exit(EXIT_FAILURE); } char *file = argv[argc - 1]; int s; int ok = 0, failed = 0, files = 0; s = valid_checksum_file(file); if (s == 0) { printf("%s: %s: no properly formatted checksum lines found\n", argv[0], file); exit(EXIT_FAILURE); } else if (s == FTYPE_NONE) { printf("%s: %s: could not open file\n", argv[0], file); exit(EXIT_FAILURE); } else if (s == FTYPE_DIR) { printf("%s: %s: is a directory\n", argv[0], file); exit(EXIT_FAILURE); } const EVP_MD *cmp_alg = EVP_MD_fetch(NULL, alg, (!strcmp(alg, "MD4") || !strcmp(alg, "WHIRLPOOL") ? "provider=legacy" : "provider=default")); FILE *fptr; char r[EVP_MD_size(cmp_alg) * 2 + 1]; fptr = fopen(file, "r"); if (!fptr) { printf("%s: %s: cannot open file for reading\n", argv[0], file); exit(EXIT_FAILURE); } char ln[1024]; char *S; int lines = 1; while (fgets(ln, sizeof(ln), fptr)) { ln[strcspn(ln, "\n")] = 0; if (strlen(ln) == 0 || (strlen(ln) > 0 && ln[0] == '#')) { lines++; continue; } else { char *H = strtok_r(ln, " \t", &S); char *F = strtok_r(NULL, " \t", &S); if (strlen(H) < 32 || strlen(F) == 0) { printf("%s: %s: line %d is not valid; skipping\n", argv[0], file, lines); lines++; continue; } strcpy(r, mdfile(cmp_alg, F, op_uppercase)); if (!strcmp(r, "(directory)")) { printf("%s: %s%sIS A DIRECTORY%s\n", F, BOLD, RED, RESET); failed++; } else if (!strcmp(r, "(file access error)")) { printf("%s: %s%sFILE ACCESS ERROR%s\n", F, BOLD, RED, RESET); failed++; } else if (!strcasecmp(mdfile(cmp_alg, F, op_uppercase), H)) { printf("%s: %s%sOK%s\n", F, BOLD, GREEN, RESET); ok++; } else { printf("%s: %s%sFAILED%s\n", F, BOLD, RED, RESET); failed++; } lines++; files++; } } fclose(fptr); printf("\n%d files processed\n%d %s%spassed%s\n%d %s%sfailed%s\n", files, ok, BOLD, GREEN, RESET, failed, BOLD, RED, RESET); exit(EXIT_SUCCESS); } if (op_standard_in) { if (AC < 1) { printf("%s: no algorithm specified\n", argv[0]); exit(EXIT_FAILURE); } else if (AC > 1) { printf("%s: only one algorithm may be specified when reading from standard input\n", argv[0]); exit(EXIT_FAILURE); } char stdinput[MAX_STDIN_LEN]; int ch; while ((ch = fgetc(stdin)) && ch != EOF) { stdinput[strlen(stdinput)] = ch; stdinput[strlen(stdinput) + 1] = '\0'; } printf("%s\n", mdstring(EVP_MD_fetch(NULL, alg, (!strcmp(alg, "MD4") || !strcmp(alg, "WHIRLPOOL") ? "provider=legacy" : "provider=default")), stdinput, op_uppercase)); exit(EXIT_SUCCESS); } if (AC < 1) { printf("%s: no algorithm specified\n", argv[0]); exit(EXIT_FAILURE); } if (!argv[optind]) { printf("%s: no file specified\n", argv[0]); exit(EXIT_FAILURE); } if (op_string && op_blake2s_256) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "BLAKE2S-256", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_blake2s_256) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "BLAKE2S-256", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_blake2b_512) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "BLAKE2B-512", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_blake2b_512) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "BLAKE2B-512", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_md4) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "MD4", "provider=legacy"), argv[argc - 1], op_uppercase)); else if (!op_string && op_md4) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "MD4", "provider=legacy"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_md5) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "MD5", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_md5) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "MD5", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha1) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA1", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha1) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA1", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha224) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA224", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha224) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA224", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha256) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA256", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha256) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA256", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha384) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA384", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha384) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA384", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha512_224) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA512-224", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha512_224) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA512-224", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha512_256) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA512-256", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha512_256) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA512-256", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha512) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA512", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha512) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA512", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha3_224) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA3-224", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha3_224) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA3-224", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha3_256) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA3-256", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha3_256) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA3-256", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha3_384) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA3-384", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha3_384) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA3-384", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sha3_512) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SHA3-512", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sha3_512) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SHA3-512", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_sm3) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "SM3", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_sm3) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "SM3", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_ripemd_160) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "RIPEMD160", "provider=default"), argv[argc - 1], op_uppercase)); else if (!op_string && op_ripemd_160) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "RIPEMD160", "provider=default"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_whirlpool) printf("%s\n", mdstring(EVP_MD_fetch(NULL, "WHIRLPOOL", "provider=legacy"), argv[argc - 1], op_uppercase)); if (!op_string && op_whirlpool) for (i = optind; i < argc; i++) printf("%s%s%s\n", mdfile(EVP_MD_fetch(NULL, "WHIRLPOOL", "provider=legacy"), argv[i], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[i] : "")); if (op_string && op_all) { for (size_t j = 0; j < sizeof(providers)/sizeof(providers)[0]; j++) printf("%s: %s\n", providers[j], mdstring(EVP_MD_fetch(NULL, providers[j], (!strcmp(providers[j], "MD4") || !strcmp(providers[j], "WHIRLPOOL") ? "provider=legacy" : "provider=default")), argv[argc - 1], op_uppercase)); } else if (!op_string && op_all) { int v; for (v = optind; v < argc; v++) { if (ftype(argv[v]) == FTYPE_DIR) { printf("%s: %s: is a directory\n", argv[0], argv[v]); break; } for (size_t j = 0; j < sizeof(providers)/sizeof(providers)[0]; j++) printf("%s: %s%s%s\n", providers[j], mdfile(EVP_MD_fetch(NULL, providers[j], (!strcmp(providers[j], "MD4") || !strcmp(providers[j], "WHIRLPOOL") ? "provider=legacy" : "provider=default")), argv[v], op_uppercase), (!op_no_file_names ? " " : ""), (!op_no_file_names ? argv[v] : "")); } } exit(EXIT_SUCCESS); }