-
+ D96E2CC71F3CAD83002590418A194953719EAB457B4084C05CCD4CD5B9051E6A2EEF08581054451DD17F5558257473881434FDB90678E840FDFB63DF03352F0A
main.c
(0 . 0)(1 . 119)
460 /* Standalone KECCAK hashing utility
461 * J. Welsh, May 2019
462 */
463
464 #include <fcntl.h>
465 #include <signal.h>
466 #include <unistd.h>
467 #include "io.h"
468
469 void sponge(unsigned capacity, size_t out_bits);
470
471 #pragma GCC diagnostic ignored "-Woverlength-strings" /* wat. */
472
473 static char const usage[] =
474 "Usage: keksum [-c] [-sCAPACITY] [-nLENGTH] [-h] [--] [FILE]...\n"
475 "Compute KECCAK checksums.\n"
476 "\n"
477 "With no FILE, act as a filter, reading from standard input then printing\n"
478 "a single line containing the hex-encoded hash. Otherwise tabulate hash and\n"
479 "name for each FILE.\n"
480 "\n"
481 "Options:\n"
482 " -c read sums from FILEs and check them (TODO)\n"
483 " -l set output length in bits (default 512)\n"
484 " -s set sponge capacity in bits (default 256)\n"
485 " -h print this help and exit\n"
486 "\n"
487 "Capacity and length both establish upper bounds on security level. Capacity\n"
488 "strongly affects speed and hash by changing permutation frequency. Length\n"
489 "acts as a truncation of an infinite output stream. (If you use large length\n"
490 "with small capacity you will be deluding yourself in quite the same manner\n"
491 "as a poorly seeded PRNG.) Both must be multiples of 8. The 1600-bit\n"
492 "permutation is always used, thus capacity must be between 8 and 1592.\n";
493
494 static void usage_err(char const *msg) {
495 write_line(2,msg);
496 write_str(2,usage);
497 _exit(1);
498 }
499
500 static unsigned dec_value(unsigned char c) {
501 unsigned r = c-'0';
502 if (r > 9) usage_err(c ? "Bad integer" : "Missing integer value");
503 return r;
504 }
505
506 static unsigned parse_uint(char const *s) {
507 unsigned acc = dec_value(*s++);
508 if (!acc && *s) usage_err("Bad integer (leading zero)");
509 for (; *s; ++s) {
510 unsigned digit = dec_value(*s);
511 if (acc > ((unsigned) -1)/10)
512 usage_err("Integer out of range");
513 acc *= 10;
514 if (acc > ((unsigned) -1) - digit)
515 usage_err("Integer out of range");
516 acc += digit;
517 }
518 return acc;
519 }
520
521 int main(int argc, char **argv) {
522 unsigned out_len = 512;
523 /* Rationale: for collision resistance, any hash function needs at
524 * least twice the desired security level in non-redundant output bits
525 * due to the birthday problem. */
526
527 unsigned capacity = 256;
528 /* Rationale: sponge capacity is an upper bound on security level
529 * because the permutation is readily inverted if its full output is
530 * known. Beyond that, its relationship to actual security is not clear
531 * to me (or perhaps anyone); some margin of safety seems prudent. The
532 * EuCrypt default is 256 (bitrate 1344). But note that in the FIPS202
533 * parameters, capacity under 512 is seen only in "SHAKE128" and none
534 * of the "SHA3" fixed-width hashes. See also:
535 * http://fixpoint.welshcomputing.com/keksum-a-keccak-imp/#comments */
536
537 signal(SIGPIPE,SIG_IGN); /* standard unix-hate */
538
539 #define SHIFT (--argc, ++argv)
540 if (!argc) goto endopts;
541 for (SHIFT; argc; SHIFT) {
542 char const *arg = *argv;
543 if (arg[0] != '-') goto endopts;
544 switch (arg[1]) {
545 case 0: goto endopts;
546 case 'l': out_len = parse_uint(arg+2); break;
547 case 's': capacity = parse_uint(arg+2); break;
548 case 'h': write_str(1,usage); return 0;
549 case '-': if (!arg[2]) { SHIFT; goto endopts; }
550 /* fallthrough */
551 default: usage_err("Bad option");
552 }
553 }
554 endopts:
555 if (out_len&7) usage_err("Length not byte-aligned");
556 if (capacity&7) usage_err("Capacity not byte-aligned");
557 if (!(0 < capacity && capacity < 1600))
558 usage_err("Capacity out of range");
559
560 if (argc) {
561 /* Listing is similar to the GNU (?) format but with no input
562 * mode character (you may know this as the mysterious extra
563 * space): it's always binary. */
564 for (; argc; SHIFT) {
565 int fd = chkp(*argv, open(*argv, O_RDONLY));
566 chkp("dup2", dup2(fd,0));
567 chkp("close", close(fd));
568 sponge(capacity,out_len);
569 write_str(1," ");
570 write_line(1,*argv);
571 }
572 }
573 else {
574 sponge(capacity,out_len);
575 newline(1);
576 }
577 return 0;
578 }