2a088a1417
the correctness of this program. Previously, it printed out the MD5 values of some test strings, but did not tell you if they were correct or not!
241 lines
5.1 KiB
C
241 lines
5.1 KiB
C
/*
|
|
* Derived from:
|
|
*
|
|
* MDDRIVER.C - test driver for MD2, MD4 and MD5
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
|
|
* rights reserved.
|
|
*
|
|
* RSA Data Security, Inc. makes no representations concerning either
|
|
* the merchantability of this software or the suitability of this
|
|
* software for any particular purpose. It is provided "as is"
|
|
* without express or implied warranty of any kind.
|
|
*
|
|
* These notices must be retained in any copies of any part of this
|
|
* documentation and/or software.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static const char rcsid[] =
|
|
"$FreeBSD$";
|
|
#endif /* not lint */
|
|
|
|
#include <sys/types.h>
|
|
#include <err.h>
|
|
#include <md5.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;
|
|
int sflag;
|
|
|
|
static void MDString(const char *);
|
|
static void MDTimeTrial(void);
|
|
static void MDTestSuite(void);
|
|
static void MDFilter(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
|
|
*/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int ch;
|
|
char *p;
|
|
char buf[33];
|
|
|
|
while ((ch = getopt(argc, argv, "pqrs:tx")) != -1)
|
|
switch (ch) {
|
|
case 'p':
|
|
MDFilter(1);
|
|
break;
|
|
case 'q':
|
|
qflag = 1;
|
|
break;
|
|
case 'r':
|
|
rflag = 1;
|
|
break;
|
|
case 's':
|
|
sflag = 1;
|
|
MDString(optarg);
|
|
break;
|
|
case 't':
|
|
MDTimeTrial();
|
|
break;
|
|
case 'x':
|
|
MDTestSuite();
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if (*argv) {
|
|
do {
|
|
p = MD5File(*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("MD5 (%s) = %s\n", *argv, p);
|
|
} while (*++argv);
|
|
} else if (!sflag && (optind == 1 || qflag || rflag))
|
|
MDFilter(0);
|
|
|
|
return (0);
|
|
}
|
|
/*
|
|
* Digests a string and prints the result.
|
|
*/
|
|
static void
|
|
MDString(const char *string)
|
|
{
|
|
size_t len = strlen(string);
|
|
char buf[33];
|
|
|
|
if (qflag)
|
|
printf("%s\n", MD5Data(string, len, buf));
|
|
else if (rflag)
|
|
printf("%s \"%s\"\n", MD5Data(string, len, buf), string);
|
|
else
|
|
printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf));
|
|
}
|
|
/*
|
|
* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
|
|
*/
|
|
static void
|
|
MDTimeTrial(void)
|
|
{
|
|
MD5_CTX context;
|
|
time_t endTime, startTime;
|
|
unsigned char block[TEST_BLOCK_LEN];
|
|
unsigned int i;
|
|
char *p, buf[33];
|
|
|
|
printf
|
|
("MD5 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 */
|
|
MD5Init(&context);
|
|
for (i = 0; i < TEST_BLOCK_COUNT; i++)
|
|
MD5Update(&context, block, TEST_BLOCK_LEN);
|
|
p = MD5End(&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, ric@Artisoft.COM.) */
|
|
printf
|
|
("Speed = %ld bytes/second\n",
|
|
(long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (long)(endTime - startTime) : 1));
|
|
}
|
|
/*
|
|
* Digests a reference suite of strings and prints the results.
|
|
*/
|
|
|
|
#define MD5TESTCOUNT 8
|
|
|
|
char *MDTestInput[] = {
|
|
"",
|
|
"a",
|
|
"abc",
|
|
"message digest",
|
|
"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"
|
|
};
|
|
|
|
char *MDTestOutput[MD5TESTCOUNT] = {
|
|
"d41d8cd98f00b204e9800998ecf8427e",
|
|
"0cc175b9c0f1b6a831c399e269772661",
|
|
"900150983cd24fb0d6963f7d28e17f72",
|
|
"f96b697d7cb7938d525a2f31aaf161d0",
|
|
"c3fcd3d76192e4007dfb496cca67e13b",
|
|
"d174ab98d277d9f5a5611c2c9f419d9f",
|
|
"57edf4a22be3c955ac49da2e2107b67a",
|
|
"b50663f41d44d92171cb9976bc118538"
|
|
};
|
|
|
|
static void
|
|
MDTestSuite(void)
|
|
{
|
|
int i;
|
|
char buffer[33];
|
|
|
|
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(" - verified correct\n");
|
|
else
|
|
printf(" - INCORRECT RESULT!\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Digests the standard input and prints the result.
|
|
*/
|
|
static void
|
|
MDFilter(int tee)
|
|
{
|
|
MD5_CTX context;
|
|
unsigned int len;
|
|
unsigned char buffer[BUFSIZ];
|
|
char buf[33];
|
|
|
|
MD5Init(&context);
|
|
while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
|
|
if (tee && len != fwrite(buffer, 1, len, stdout))
|
|
err(1, "stdout");
|
|
MD5Update(&context, buffer, len);
|
|
}
|
|
printf("%s\n", MD5End(&context,buf));
|
|
}
|
|
|
|
static void
|
|
usage(void)
|
|
{
|
|
|
|
fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n");
|
|
exit(1);
|
|
}
|