diff options
author | eik <eik@FreeBSD.org> | 2004-06-11 16:07:02 +0000 |
---|---|---|
committer | eik <eik@FreeBSD.org> | 2004-06-11 16:07:02 +0000 |
commit | 6ce46a0816813d4d69abd00d4820d640ddaa9bbc (patch) | |
tree | 1430582fd9c7ef7641be87f5097d224ce5e20c4b /sbin/md5 | |
parent | ad8a1611c3afd38808fa8ebc76ca5128459c4efc (diff) | |
download | FreeBSD-src-6ce46a0816813d4d69abd00d4820d640ddaa9bbc.zip FreeBSD-src-6ce46a0816813d4d69abd00d4820d640ddaa9bbc.tar.gz |
Add sha1 and rmd160 checksum tools.
Since the algorithms are already supported in libmd,
the size increase is small when a dynamic root is used.
Approved by: joerg, ru
MFC after: 2 weeks
Diffstat (limited to 'sbin/md5')
-rw-r--r-- | sbin/md5/Makefile | 11 | ||||
-rw-r--r-- | sbin/md5/md5.1 | 81 | ||||
-rw-r--r-- | sbin/md5/md5.c | 181 |
3 files changed, 206 insertions, 67 deletions
diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile index 56187d7..007fb4c 100644 --- a/sbin/md5/Makefile +++ b/sbin/md5/Makefile @@ -3,7 +3,16 @@ PROG= md5 -LDADD= -lmd +LINKS= ${BINDIR}/md5 ${BINDIR}/rmd160 \ + ${BINDIR}/md5 ${BINDIR}/sha1 + +MLINKS= md5.1 rmd160.1 \ + md5.1 sha1.1 + +WARNS?= 6 +WFORMAT?= 1 + DPADD= ${LIBMD} +LDADD= -lmd .include <bsd.prog.mk> diff --git a/sbin/md5/md5.1 b/sbin/md5/md5.1 index 852f1d4..9d37731 100644 --- a/sbin/md5/md5.1 +++ b/sbin/md5/md5.1 @@ -1,20 +1,30 @@ .\" $FreeBSD$ -.Dd February 14, 1994 +.Dd June 6, 2004 .Dt MD5 1 .Os .Sh NAME -.Nm md5 +.Nm md5 , sha1 , rmd160 .Nd calculate a message-digest fingerprint (checksum) for a file .Sh SYNOPSIS -.Nm +.Nm md5 +.Op Fl pqrtx +.Op Fl s Ar string +.Op Ar +.Nm sha1 +.Op Fl pqrtx +.Op Fl s Ar string +.Op Ar +.Nm rmd160 .Op Fl pqrtx .Op Fl s Ar string .Op Ar .Sh DESCRIPTION -The -.Nm -utility takes as input a message of arbitrary length and produces -as output a 128-bit +The +.Nm md5 , sha1 +and +.Nm rmd160 +utilities take as input a message of arbitrary length and produce as +output a .Dq fingerprint or .Dq message digest @@ -22,17 +32,23 @@ of the input. 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. -The MD5 algorithm is intended for digital signature applications, where a +The +.Tn MD5 , SHA-1 +and +.Tn RIPEMD-160 +algorithms are intended for digital signature applications, where a large file must be .Dq compressed in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as -.Em RSA . +.Tn RSA . .Pp -MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been +.Tn MD5 +has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt. -The attacks on MD5 +The attacks on +.Tn MD5 are in the nature of finding .Dq collisions \(em that is, multiple @@ -41,17 +57,16 @@ to be able to determine the exact original input given a hash value. .Pp The following options may be used in any combination and must precede any files named on the command line. -The MD5 -sum of each file listed on the command line is printed after the options -are processed. +The hexadecimal checksum 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 MD5 sum to stdout. +Echo stdin to stdout and append the checksum to stdout. .It Fl q -Quiet mode - only the MD5 sum is printed out. +Quiet mode - only the checksum is printed out. Overrides the .Fl r option. @@ -69,16 +84,44 @@ Run a built-in test script. .El .Sh DIAGNOSTICS The -.Nm -utility exits 0 on success, +.Nm md5 , sha1 +and +.Nm rmd160 +utilities exit 0 on success, and 1 if at least one of the input files could not be read. .Sh SEE ALSO -.Xr cksum 1 +.Xr cksum 1 , +.Xr md5 3 , +.Xr ripemd 3 , +.Xr sha 3 .Rs .%A R. Rivest .%T The MD5 Message-Digest Algorithm .%O RFC1321 .Re +.Rs +.%A J. Burrows +.%T The Secure Hash Standard +.%O FIPS PUB 180-1 +.Re +.Rs +.%A D. Eastlake and P. Jones +.%T US Secure Hash Algorithm 1 +.%O RFC 3174 +.Re +.Pp +RIPEMD-160 is part of the ISO draft standard +.Qq ISO/IEC DIS 10118-3 +on dedicated hash functions. +.Pp +Secure Hash Standard (SHS): +.Pa http://csrc.nist.gov/cryptval/shs.html . +.Pp +The RIPEMD-160 page: +.Pa http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html . .Sh ACKNOWLEDGMENTS This program is placed in the public domain for free general use by RSA Data Security. +.Pp +Support for SHA-1 and RIPEMD-160 has been added by +.An Oliver Eikemeier Aq eik@FreeBSD.org . diff --git a/sbin/md5/md5.c b/sbin/md5/md5.c index 9fd0cf8..8672d3f 100644 --- a/sbin/md5/md5.c +++ b/sbin/md5/md5.c @@ -25,6 +25,8 @@ __FBSDID("$FreeBSD$"); #include <sys/resource.h> #include <err.h> #include <md5.h> +#include <ripemd.h> +#include <sha.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -36,16 +38,66 @@ __FBSDID("$FreeBSD$"); */ #define TEST_BLOCK_LEN 10000 #define TEST_BLOCK_COUNT 100000 +#define MDTESTCOUNT 8 int qflag; int rflag; int sflag; -static void MDString(const char *); -static void MDTimeTrial(void); -static void MDTestSuite(void); -static void MDFilter(int); -static void usage(void); +typedef void (DIGEST_Init)(void *); +typedef void (DIGEST_Update)(void *, const unsigned char *, size_t); +typedef char *(DIGEST_End)(void *, char *); + +extern const char *MD5TestOutput[MDTESTCOUNT]; +extern const char *SHA1_TestOutput[MDTESTCOUNT]; +extern const char *RIPEMD160_TestOutput[MDTESTCOUNT]; + +typedef struct Algorithm_t { + const char *progname; + const char *name; + const char *(*TestOutput)[MDTESTCOUNT]; + DIGEST_Init *Init; + DIGEST_Update *Update; + DIGEST_End *End; + char *(*Data)(const unsigned char *, unsigned int, char *); + char *(*File)(const char *, char *); +} Algorithm_t; + +static void MD5_Update(MD5_CTX *, const unsigned char *, size_t); +static void MDString(Algorithm_t *, const char *); +static void MDTimeTrial(Algorithm_t *); +static void MDTestSuite(Algorithm_t *); +static void MDFilter(Algorithm_t *, int); +static void usage(Algorithm_t *); + +typedef union { + MD5_CTX md5; + SHA1_CTX sha1; + RIPEMD160_CTX ripemd160; +} DIGEST_CTX; + +/* max(MD5_DIGEST_LENGTH, SHA_DIGEST_LENGTH, RIPEMD160_DIGEST_LENGTH)*2+1 */ +#define HEX_DIGEST_LENGTH 41 + +/* algorithm function table */ + +struct Algorithm_t Algorithm[] = { + { "md5", "MD5", &MD5TestOutput, (DIGEST_Init*)&MD5Init, + (DIGEST_Update*)&MD5_Update, (DIGEST_End*)&MD5End, + &MD5Data, &MD5File }, + { "sha1", "SHA1", &SHA1_TestOutput, (DIGEST_Init*)&SHA1_Init, + (DIGEST_Update*)&SHA1_Update, (DIGEST_End*)&SHA1_End, + &SHA1_Data, &SHA1_File }, + { "rmd160", "RMD160", &RIPEMD160_TestOutput, + (DIGEST_Init*)&RIPEMD160_Init, (DIGEST_Update*)&RIPEMD160_Update, + (DIGEST_End*)&RIPEMD160_End, &RIPEMD160_Data, &RIPEMD160_File } +}; + +static void +MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len) +{ + MD5Update(c, data, len); +} /* Main driver. @@ -61,14 +113,28 @@ main(int argc, char *argv[]) { int ch; char *p; - char buf[33]; + char buf[HEX_DIGEST_LENGTH]; int failed; + unsigned digest; + const char* progname; + + if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + progname++; + + for (digest = 0; digest < sizeof(Algorithm)/sizeof(*Algorithm); digest++) + if (strcasecmp(Algorithm[digest].progname, progname) == 0) + break; + + if (Algorithm[digest].progname == NULL) + digest = 0; failed = 0; while ((ch = getopt(argc, argv, "pqrs:tx")) != -1) switch (ch) { case 'p': - MDFilter(1); + MDFilter(&Algorithm[digest], 1); break; case 'q': qflag = 1; @@ -78,23 +144,23 @@ main(int argc, char *argv[]) break; case 's': sflag = 1; - MDString(optarg); + MDString(&Algorithm[digest], optarg); break; case 't': - MDTimeTrial(); + MDTimeTrial(&Algorithm[digest]); break; case 'x': - MDTestSuite(); + MDTestSuite(&Algorithm[digest]); break; default: - usage(); + usage(&Algorithm[digest]); } argc -= optind; argv += optind; if (*argv) { do { - p = MD5File(*argv, buf); + p = Algorithm[digest].File(*argv, buf); if (!p) { warn("%s", *argv); failed++; @@ -104,11 +170,11 @@ main(int argc, char *argv[]) else if (rflag) printf("%s %s\n", p, *argv); else - printf("MD5 (%s) = %s\n", *argv, p); + printf("%s (%s) = %s\n", Algorithm[digest].name, *argv, p); } } while (*++argv); } else if (!sflag && (optind == 1 || qflag || rflag)) - MDFilter(0); + MDFilter(&Algorithm[digest], 0); if (failed != 0) return (1); @@ -119,35 +185,35 @@ main(int argc, char *argv[]) * Digests a string and prints the result. */ static void -MDString(const char *string) +MDString(Algorithm_t *alg, const char *string) { size_t len = strlen(string); - char buf[33]; + char buf[HEX_DIGEST_LENGTH]; if (qflag) - printf("%s\n", MD5Data(string, len, buf)); + printf("%s\n", alg->Data(string, len, buf)); else if (rflag) - printf("%s \"%s\"\n", MD5Data(string, len, buf), string); + printf("%s \"%s\"\n", alg->Data(string, len, buf), string); else - printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); + printf("%s (\"%s\") = %s\n", alg->name, string, alg->Data(string, len, buf)); } /* * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. */ static void -MDTimeTrial(void) +MDTimeTrial(Algorithm_t *alg) { - MD5_CTX context; + DIGEST_CTX context; struct rusage before, after; struct timeval total; float seconds; unsigned char block[TEST_BLOCK_LEN]; unsigned int i; - char *p, buf[33]; + char *p, buf[HEX_DIGEST_LENGTH]; printf - ("MD5 time trial. Digesting %d %d-byte blocks ...", - TEST_BLOCK_COUNT, TEST_BLOCK_LEN); + ("%s time trial. Digesting %d %d-byte blocks ...", + alg->name, TEST_BLOCK_COUNT, TEST_BLOCK_LEN); fflush(stdout); /* Initialize block */ @@ -158,10 +224,10 @@ MDTimeTrial(void) getrusage(0, &before); /* Digest blocks */ - MD5Init(&context); + alg->Init(&context); for (i = 0; i < TEST_BLOCK_COUNT; i++) - MD5Update(&context, block, TEST_BLOCK_LEN); - p = MD5End(&context,buf); + alg->Update(&context, block, TEST_BLOCK_LEN); + p = alg->End(&context, buf); /* Stop timer */ getrusage(0, &after); @@ -179,9 +245,7 @@ MDTimeTrial(void) * Digests a reference suite of strings and prints the results. */ -#define MD5TESTCOUNT 8 - -char *MDTestInput[] = { +const char *MDTestInput[MDTESTCOUNT] = { "", "a", "abc", @@ -189,10 +253,11 @@ char *MDTestInput[] = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt" + "MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made \ +that its security is in some doubt" }; -char *MDTestOutput[MD5TESTCOUNT] = { +const char *MD5TestOutput[MDTESTCOUNT] = { "d41d8cd98f00b204e9800998ecf8427e", "0cc175b9c0f1b6a831c399e269772661", "900150983cd24fb0d6963f7d28e17f72", @@ -203,17 +268,39 @@ char *MDTestOutput[MD5TESTCOUNT] = { "b50663f41d44d92171cb9976bc118538" }; +const char *SHA1_TestOutput[MDTESTCOUNT] = { + "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", + "a9993e364706816aba3e25717850c26c9cd0d89d", + "c12252ceda8be8994d5fa0290a47231c1d16aae3", + "32d10c7b8cf96570ca04ce37f2a19d84240d3a89", + "761c457bf73b14d27e9e9265c46f4b4dda11f940", + "50abf5706a150990a08b2c5ea40fa0e585554732", + "18eca4333979c4181199b7b4fab8786d16cf2846" +}; + +const char *RIPEMD160_TestOutput[MDTESTCOUNT] = { + "9c1185a5c5e9fc54612808977ee8f548b2258d31", + "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", + "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", + "5d0689ef49d2fae572b881b123a85ffa21595f36", + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc", + "b0e20b6e3116640286ed3a87a5713079b21f5189", + "9b752e45573d4b39f4dbd3323cab82bf63326bfb", + "5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32" +}; + static void -MDTestSuite(void) +MDTestSuite(Algorithm_t *alg) { int i; - char buffer[33]; + char buffer[HEX_DIGEST_LENGTH]; - printf("MD5 test suite:\n"); - for (i = 0; i < MD5TESTCOUNT; i++) { - MD5Data(MDTestInput[i], strlen(MDTestInput[i]), buffer); - printf("MD5 (\"%s\") = %s", MDTestInput[i], buffer); - if (strcmp(buffer, MDTestOutput[i]) == 0) + printf("%s test suite:\n", alg->name); + for (i = 0; i < MDTESTCOUNT; i++) { + (*alg->Data)(MDTestInput[i], strlen(MDTestInput[i]), buffer); + printf("%s (\"%s\") = %s", alg->name, MDTestInput[i], buffer); + if (strcmp(buffer, (*alg->TestOutput)[i]) == 0) printf(" - verified correct\n"); else printf(" - INCORRECT RESULT!\n"); @@ -224,26 +311,26 @@ MDTestSuite(void) * Digests the standard input and prints the result. */ static void -MDFilter(int tee) +MDFilter(Algorithm_t *alg, int tee) { - MD5_CTX context; + DIGEST_CTX context; unsigned int len; unsigned char buffer[BUFSIZ]; - char buf[33]; + char buf[HEX_DIGEST_LENGTH]; - MD5Init(&context); + alg->Init(&context); while ((len = fread(buffer, 1, BUFSIZ, stdin))) { if (tee && len != fwrite(buffer, 1, len, stdout)) err(1, "stdout"); - MD5Update(&context, buffer, len); + alg->Update(&context, buffer, len); } - printf("%s\n", MD5End(&context,buf)); + printf("%s\n", alg->End(&context, buf)); } static void -usage(void) +usage(Algorithm_t *alg) { - fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n"); + fprintf(stderr, "usage: %s [-pqrtx] [-s string] [files ...]\n", alg->progname); exit(1); } |