1 /********************************************************************\
2 *
3 * FILE: hashtest.c
4 *
5 * CONTENTS: test file for sample C-implementation of
6 * RIPEMD-160 and RIPEMD128
7 * * command line arguments:
8 * filename -- compute hash code of file read binary
9 * -sstring -- print string & hashcode
10 * -t -- perform time trial
11 * -x -- execute standard test suite, ASCII input
12 * * for linkage with rmd128.c: define RMDsize as 128
13 * for linkage with rmd160.c: define RMDsize as 160 (default)
14 * TARGET: any computer with an ANSI C compiler
15 *
16 * AUTHOR: Antoon Bosselaers, ESAT-COSIC
17 * DATE: 18 April 1996
18 * VERSION: 1.1
19 * HISTORY: bug in RMDonemillion() corrected
20 *
21 * Copyright (c) Katholieke Universiteit Leuven
22 * 1996, All Rights Reserved
23 *
24 \********************************************************************/
25 #ifndef RMDsize
26 #define RMDsize 160
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <string.h>
33 #if RMDsize == 128
34 #include "rmd128.h"
35 #elif RMDsize == 160
36 #include "rmd160.h"
37 #endif
38
39 #define TEST_BLOCK_SIZE 8000
40 #define TEST_BLOCKS 1250
41 #define TEST_BYTES ((long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS)
42
43 /********************************************************************/
44
RMD(byte * message)45 byte *RMD(byte *message)
46 /*
47 * returns RMD(message)
48 * message should be a string terminated by '\0'
49 */
50 {
51 dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(, E)) */
52 static byte hashcode[RMDsize/8]; /* for final hash-value */
53 dword X[16]; /* current 16-word chunk */
54 word i; /* counter */
55 dword length; /* length in bytes of message */
56 dword nbytes; /* # of bytes not yet processed */
57
58 /* initialize */
59 MDinit(MDbuf);
60 length = (dword)strlen((char *)message);
61
62 /* process message in 16-word chunks */
63 for (nbytes=length; nbytes > 63; nbytes-=64) {
64 for (i=0; i<16; i++) {
65 X[i] = BYTES_TO_DWORD(message);
66 message += 4;
67 }
68 compress(MDbuf, X);
69 } /* length mod 64 bytes left */
70
71 /* finish: */
72 MDfinish(MDbuf, message, length, 0);
73
74 for (i=0; i<RMDsize/8; i+=4) {
75 hashcode[i] = MDbuf[i>>2]; /* implicit cast to byte */
76 hashcode[i+1] = (MDbuf[i>>2] >> 8); /* extracts the 8 least */
77 hashcode[i+2] = (MDbuf[i>>2] >> 16); /* significant bits. */
78 hashcode[i+3] = (MDbuf[i>>2] >> 24);
79 }
80
81 return (byte *)hashcode;
82 }
83
84 /********************************************************************/
85
RMDbinary(char * fname)86 byte *RMDbinary(char *fname)
87 /*
88 * returns RMD(message in file fname)
89 * fname is read as binary data.
90 */
91 {
92 FILE *mf; /* pointer to file <fname> */
93 byte data[1024]; /* contains current mess. block */
94 dword nbytes; /* length of this block */
95 dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(, E)) */
96 static byte hashcode[RMDsize/8]; /* for final hash-value */
97 dword X[16]; /* current 16-word chunk */
98 word i, j; /* counters */
99 dword length[2]; /* length in bytes of message */
100 dword offset; /* # of unprocessed bytes at */
101 /* call of MDfinish */
102
103 /* initialize */
104 if ((mf = fopen(fname, "rb")) == NULL) {
105 fprintf(stderr, "\nRMDbinary: cannot open file \"%s\".\n",
106 fname);
107 exit(1);
108 }
109 MDinit(MDbuf);
110 length[0] = 0;
111 length[1] = 0;
112
113 while ((nbytes = fread(data, 1, 1024, mf)) != 0) {
114 /* process all complete blocks */
115 for (i=0; i<(nbytes>>6); i++) {
116 for (j=0; j<16; j++)
117 X[j] = BYTES_TO_DWORD(data+64*i+4*j);
118 compress(MDbuf, X);
119 }
120 /* update length[] */
121 if (length[0] + nbytes < length[0])
122 length[1]++; /* overflow to msb of length */
123 length[0] += nbytes;
124 }
125
126 /* finish: */
127 offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */
128 MDfinish(MDbuf, data+offset, length[0], length[1]);
129
130 for (i=0; i<RMDsize/8; i+=4) {
131 hashcode[i] = MDbuf[i>>2];
132 hashcode[i+1] = (MDbuf[i>>2] >> 8);
133 hashcode[i+2] = (MDbuf[i>>2] >> 16);
134 hashcode[i+3] = (MDbuf[i>>2] >> 24);
135 }
136
137 fclose(mf);
138
139 return (byte *)hashcode;
140 }
141
142 /********************************************************************/
143
speedtest(void)144 void speedtest(void)
145 /*
146 * A time trial routine, to measure the speed of ripemd.
147 * Measures processor time required to process TEST_BLOCKS times
148 * a message of TEST_BLOCK_SIZE characters.
149 */
150 {
151 clock_t t0, t1;
152 byte *data;
153 byte hashcode[RMDsize/8];
154 dword X[16];
155 dword MDbuf[RMDsize/32];
156 word i, j, k;
157
158 srand(time(NULL));
159
160 /* allocate and initialize test data */
161 if ((data = (byte*)malloc(TEST_BLOCK_SIZE)) == NULL) {
162 fprintf(stderr, "speedtest: allocation error\n");
163 exit(1);
164 }
165 for (i=0; i<TEST_BLOCK_SIZE; i++)
166 data[i] = (byte)(rand() >> 7);
167
168 /* start timer */
169 printf("RIPEMD time trial. Processing %ld characters...\n",
170 TEST_BYTES);
171 t0 = clock();
172
173 /* process data */
174 MDinit(MDbuf);
175 for (i=0; i<TEST_BLOCKS; i++) {
176 for (j=0; j<TEST_BLOCK_SIZE; j+=64) {
177 for (k=0; k<16; k++)
178 X[k] = BYTES_TO_DWORD(data+j+4*k);
179 compress(MDbuf, X);
180 }
181 }
182 MDfinish(MDbuf, data, TEST_BYTES, 0);
183
184 /* stop timer, get time difference */
185 t1 = clock();
186 printf("\nTest input processed in %g seconds.\n",
187 (double)(t1-t0)/(double)CLOCKS_PER_SEC);
188 printf("Characters processed per second: %g\n",
189 (double)CLOCKS_PER_SEC*TEST_BYTES/((double)t1-t0));
190
191 for (i=0; i<RMDsize/8; i+=4) {
192 hashcode[i] = MDbuf[i>>2];
193 hashcode[i+1] = (MDbuf[i>>2] >> 8);
194 hashcode[i+2] = (MDbuf[i>>2] >> 16);
195 hashcode[i+3] = (MDbuf[i>>2] >> 24);
196 }
197 printf("\nhashcode: ");
198 for (i=0; i<RMDsize/8; i++)
199 printf("%02x", hashcode[i]);
200
201 free(data);
202 return;
203 }
204
205 /********************************************************************/
206
RMDonemillion(void)207 void RMDonemillion(void)
208 /*
209 * returns RMD() of message consisting of 1 million 'a' characters
210 */
211 {
212 dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(, E)) */
213 static byte hashcode[RMDsize/8]; /* for final hash-value */
214 dword X[16]; /* current 16-word chunk */
215 word i; /* counter */
216
217 MDinit(MDbuf);
218 memcpy(X, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 32);
219 memcpy(X+8, X, 32);
220 for (i=15625; i>0; i--)
221 compress(MDbuf, X);
222 MDfinish(MDbuf, NULL, 1000000UL, 0);
223 for (i=0; i<RMDsize/8; i+=4) {
224 hashcode[i] = MDbuf[i>>2];
225 hashcode[i+1] = (MDbuf[i>>2] >> 8);
226 hashcode[i+2] = (MDbuf[i>>2] >> 16);
227 hashcode[i+3] = (MDbuf[i>>2] >> 24);
228 }
229 printf("\n* message: 1 million times \"a\"\n hashcode: ");
230 for (i=0; i<RMDsize/8; i++)
231 printf("%02x", hashcode[i]);
232
233 }
234
235 /********************************************************************/
236
RMDstring(char * message,char * print)237 void RMDstring(char *message, char *print)
238 {
239 int i;
240 byte *hashcode;
241
242 hashcode = RMD((byte *)message);
243 printf("\n* message: %s\n hashcode: ", print);
244 for (i=0; i<RMDsize/8; i++)
245 printf("%02x", hashcode[i]);
246 }
247
248 /********************************************************************/
249
testsuite(void)250 void testsuite (void)
251 /*
252 * standard test suite
253 */
254 {
255 printf("\nRIPEMD-%u test suite results (ASCII):\n", RMDsize);
256
257 RMDstring("", "\"\" (empty string)");
258 RMDstring("a", "\"a\"");
259 RMDstring("abc", "\"abc\"");
260 RMDstring("message digest", "\"message digest\"");
261 RMDstring("abcdefghijklmnopqrstuvwxyz", "\"abcdefghijklmnopqrstuvwxyz\"");
262 RMDstring("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
263 "\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"");
264 RMDstring("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
265 "\"A...Za...z0...9\"");
266 RMDstring("1234567890123456789012345678901234567890"
267 "1234567890123456789012345678901234567890",
268 "8 times \"1234567890\"");
269 RMDonemillion();
270
271 return;
272 }
273
274 /********************************************************************/
275
main(int argc,char * argv[])276 main (int argc, char *argv[])
277 /*
278 * main program. calls one or more of the test routines depending
279 * on command line arguments. see the header of this file.
280 *
281 */
282 {
283 int i, j;
284 byte *hashcode;
285
286 if (argc == 1) {
287 printf("For each command line argument in turn:\n");
288 printf(" filename -- compute hash code of file binary read\n");
289 printf(" -sstring -- print string & hashcode\n");
290 printf(" -t -- perform time trial\n");
291 printf(" -x -- execute standard test suite, ASCII input\n");
292 }
293 else {
294 for (i = 1; i < argc; i++) {
295 if (argv[i][0] == '-' && argv[i][1] == 's') {
296 printf("\n\nmessage: %s", argv[i]+2);
297 hashcode = RMD((byte *)argv[i] + 2);
298 printf("\nhashcode: ");
299 for (j=0; j<RMDsize/8; j++)
300 printf("%02x", hashcode[j]);
301 }
302 else if (strcmp (argv[i], "-t") == 0)
303 speedtest ();
304 else if (strcmp (argv[i], "-x") == 0)
305 testsuite ();
306 else {
307 hashcode = RMDbinary (argv[i]);
308 printf("\n\nmessagefile (binary): %s", argv[i]);
309 printf("\nhashcode: ");
310 for (j=0; j<RMDsize/8; j++)
311 printf("%02x", hashcode[j]);
312 }
313 }
314 }
315 printf("\n");
316
317 return 0;
318 }
319
320 /********************** end of file hashtest.c **********************/
321
322