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