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 45byte *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 86byte *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 144void 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 207void 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 237void 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 250void 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 276main (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