The Timing Test
Naturally, we want a cryptographic hash function that is fast. If the function spends at least half a second to produce a hash, it is simply too slow for real-world use.
Listing Three describes the test routine that measures how fast a hash function processes a given message. The routine, testTimingWith:forType:, receives the message (aMsg) as an NSString object, the hash type (aTyp) as an NSInteger.
Listing Three: The timing testbed.
- (void)testTimingWith:(NSString *)aMsg forType:(NSInteger)aTyp
{
NSMutableString *tStr, *tSub;
NSTimeInterval tAve, tSmp;
NSInteger tIdx, tRun, tLen;
NSData *tTst;
NSDate *tMrk;
NSRange tPos;
NSNumber *tNum;
unichar tChr;
// perform the test
tLen = [aMsg length];
for (tRun = 0; tRun < tLen; tRun++)
{
// create a copy of the message text
tStr = [NSMutableString stringWithString:aMsg];
for (tIdx = 0; tIdx < 255; tIdx++)
{
// read a character byte
tChr = [tStr characterAtIndex:tRun];
tChr = tChr + tIdx + 1;
tChr %= 255;
// update the string
tSub = [NSMutableString stringWithCharacters:&tChr length:1];
tPos = NSMakeRange(tRun, 1);
[tStr replaceCharactersInRange:tPos withString:tSub];
// mark the start time
tMrk = [NSDate date];
// generate a test hash
tTst = [tStr sha3Hash:aTyp];
// calculate the elapsed time
tSmp = [[NSDate date] timeIntervalSinceDate:tMrk];
tAve += tSmp;
}
}
// calculate the average hash time
tAve = tAve / (tLen * 255);
tStr = [NSString stringWithFormat:@"%10.5f", (tAve * 1000000)];
tNum = [NSNumber numberWithDouble:tAve];
// store the results
// ...
}
The test routine begins by extracting the message length (line 13). It then starts two nested loops the outer loop for making a copy of the message (line 17), the inner loop for modifying and hashing the copy (lines 22-35). The outer loop repeats for the length of the message. As for the inner loop, it repeats for a full byte value, which is from 0 to 255.
To modify the message copy, the test routine extracts and increments a message character (lines 22-24). Then it inserts the new character back into the copy, replacing the original character (lines 27-29). To time the hash process, the routine creates an instance of NSDate (line 32). It calls the category method sha3hash:, passing the modified message as input (line 35). Then the routine uses the NSDate class to compute the elapsed time in seconds (line 38). It sums up the elapsed time of each call to sha3hash: (line 39), and it calculates the average time per message byte once the nested loop ends (lines 43-45). Note it stores the test result into an NSNumber.
Table 1 shows how the five SHA-3 candidates and the OpenSSL hashes fare in terms of time. Not surprisingly, both MD5 and SHA-1 gave the best time readings. This is due to those routines being library functions, thus optimized for use. Again, bear in mind that neither function emits a 256-bit hash.
As for SHA-2, it was based on source provided by Aaron Gifford on his web page. It gave the third best time, just slightly slower than SHA-1 by 1.5 microseconds.
Of the five SHA-3 candidates, BLAKE was the fastest, taking almost 4 microseconds more than SHA-2 to produce a 256-bit hash. Skein came in second, about three times slower than BLAKE. The slowest of the group was JH. It took nearly 1 millisecond per message byte to produce a hash.


