We currently have a MD5 driver, but no SHA1 driver, even though we have SHA1 as part of libmd. So I took md5.c from /usr/src/sbin/md5 and made sha1.c as well as a respective man page. Attached is the source file, the manual page for it, as well as a makefile.
Hope this is useful and makes its way into the tree. Md5 has some questionable attacks against it, and Schneier claims that sha is resillient to such attacks. mike
/* * Derived from: * * MDDRIVER.C - test driver for MD2, MD4 and MD5 */ /* * Further dervied from the FreeBSD md5 driver program. * Converted to generate SHA 160 bit hashes. * Mike Wiacek <[EMAIL PROTECTED]> 12/14/2001 */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include <sys/types.h> #include <err.h> #include <sha.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> /* * Length of test block, number of test blocks. */ #define TEST_BLOCK_LEN 10000 #define TEST_BLOCK_COUNT 100000 int qflag; int rflag; static void SHAString(const char *); static void SHATimeTrial(void); static void SHATestSuite(void); static void SHAFilter(int); static void usage(void); /* Main driver. Arguments (may be any combination): -sstring - digests string -t - runs time trial -x - runs test script filename - digests file (none) - digests standard input */ main(int argc, char *argv[]) { int ch; char *p; unsigned char buf[41] = {0}; while ((ch = getopt(argc, argv, "pqrs:tx")) != -1) switch (ch) { case 'p': SHAFilter(1); break; case 'q': qflag = 1; break; case 'r': rflag = 1; break; case 's': SHAString(optarg); break; case 't': SHATimeTrial(); break; case 'x': SHATestSuite(); break; default: usage(); } argc -= optind; argv += optind; if (*argv) { do { p = SHA1_File(*argv, buf); if (!p) warn("%s", *argv); else if (qflag) printf("%s\n", p); else if (rflag) printf("%s %s\n", p, *argv); else printf("SHA1 (%s) = %s\n", *argv, p); } while (*++argv); } else if (optind == 1 || qflag || rflag) SHAFilter(0); return (0); } /* * Digests a string and prints the result. */ static void SHAString(const char *string) { size_t len = strlen(string); unsigned char buf[41] = {0}; if (qflag) printf("%s\n", SHA1_Data(string, len, buf)); else if (rflag) printf("%s \"%s\"\n", SHA1_Data(string, len, buf), string); else printf("SHA1 (\"%s\") = %s\n", string, SHA1_Data(string, len, buf)); } /* * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. */ static void SHATimeTrial(void) { SHA_CTX context; time_t endTime, startTime; unsigned char block[TEST_BLOCK_LEN]; unsigned int i; char *p; unsigned char buf[41] = {0}; printf ("SHA1 time trial. Digesting %d %d-byte blocks ...", TEST_BLOCK_COUNT, TEST_BLOCK_LEN); fflush(stdout); /* Initialize block */ for (i = 0; i < TEST_BLOCK_LEN; i++) block[i] = (unsigned char) (i & 0xff); /* Start timer */ time(&startTime); /* Digest blocks */ SHA_Init(&context); for (i = 0; i < TEST_BLOCK_COUNT; i++) SHA_Update(&context, block, TEST_BLOCK_LEN); p = SHA1_End(&context,buf); /* Stop timer */ time(&endTime); printf(" done\n"); printf("Digest = %s", p); printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); /* Be careful that endTime-startTime is not zero. (Bug fix from Ric * Anderson, [EMAIL PROTECTED]) */ printf ("Speed = %ld bytes/second\n", (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1)); } /* * Digests a reference suite of strings and prints the results. */ static void SHATestSuite(void) { printf("SHA1 test suite:\n"); SHAString(""); SHAString("a"); SHAString("abc"); SHAString("message digest"); SHAString("abcdefghijklmnopqrstuvwxyz"); SHAString ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); SHAString ("1234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890"); } /* * Digests the standard input and prints the result. */ static void SHAFilter(int tee) { SHA_CTX context; unsigned int len; unsigned char buffer[BUFSIZ]; unsigned char buf[41] = {0}; SHA_Init(&context); while ((len = fread(buffer, 1, BUFSIZ, stdin))) { if (tee && len != fwrite(buffer, 1, len, stdout)) err(1, "stdout"); SHA_Update(&context, buffer, len); } printf("%s\n", SHA1_End(&context,buf)); } static void usage(void) { fprintf(stderr, "usage: sha1 [-pqrtx] [-s string] [files ...]\n"); exit(1); }
.\" $FreeBSD$ .Dd February 14, 1994 .Dt SHA1 1 .Os .Sh NAME .Nm sha1 .Nd calculate a message-digest fingerprint (checksum) for a file .Sh SYNOPSIS .Nm .Op Fl pqrtx .Op Fl s Ar string .Op Ar .Sh DESCRIPTION .Nm Sha1 takes as input a message of arbitrary length and produces as output a 160-bit .Dq fingerprint or .Dq message digest of the input, using the National Institute of Standards and Technology's Secure Hash Algorithm. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. .Pp The following options may be used in any combination and must precede any files named on the command line. The SHA1 sum of each file listed on the command line is printed after the options are processed. .Bl -tag -width indent .It Fl s Ar string Print a checksum of the given .Ar string . .It Fl p Echo stdin to stdout and appends the SHA1 sum to stdout. .It Fl q Quiet mode - only the SHA1 sum is printed out. Overrides the .Fl r option. .It Fl r Reverses the format of the output. This helps with visual diffs. Does nothing when combined with the .Fl ptx options. .It Fl t Run a built-in time trial. .It Fl x Run a built-in test script. .El .Sh SEE ALSO .Xr cksum 1 .Xr md5 1 .Rs .%A D. Eastlake .%T US Secure Hash Algorithm 1 (SHA1) .%O RFC3174 .Re
# @(#)Makefile 8.1 (Berkeley) 6/9/93 # $FreeBSD$ PROG= sha1 LDADD+= -lmd -g DPADD+= ${LIBMD} .include <bsd.prog.mk>