From 34f3fbf852e28886207109dd96fd730c92670119 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Wed, 24 Sep 2014 17:59:08 +0200 Subject: [PATCH] Fix the hash computation in chunks so large files can be hashed without problems. --- main.d | 31 +++++++++++++++++++++++------- tiger.c | 59 ++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/main.d b/main.d index 62a4f6f..e0a81c1 100644 --- a/main.d +++ b/main.d @@ -5,6 +5,9 @@ import std.file; import std.algorithm; extern(C) void tiger (char* parMessage, ulong parLength, out ulong[3] parOut, char parPadding); +extern(C) void tiger_init (out ulong[3] parOut); +extern(C) void tiger_chunk (char* parMessage, ulong parLength, out ulong[3] parOut); +extern(C) void tiger_last_chunk (char* parMessage, ulong parBuffLength, ulong parTotalLength, out ulong[3] parOut, char parPadding); ulong swapLong (ulong parNum) { parNum = (parNum & 0x00000000FFFFFFFF) << 32 | (parNum & 0xFFFFFFFF00000000) >> 32; @@ -29,21 +32,35 @@ ulong[3] getTiger (in string parData, bool parV2) { } ulong[3] getTiger (ref File parData, bool parV2) { - const auto buff_length = 8192; - ubyte[] unaligned = new ubyte[buff_length + ulong.alignof - 1]; + const auto buff_length = 64 * 128; + char[] unaligned = new char[buff_length + ulong.alignof - 1]; size_t offset = ((cast(size_t)unaligned.ptr + (ulong.alignof - 1)) & ~cast(size_t)(ulong.alignof - 1)) - cast(size_t)unaligned.ptr; assert(offset >= 0 && offset < ulong.alignof); - const char padding = (parV2 ? 0x80 : 0x01); assert(offset + buff_length <= unaligned.length); - ubyte[] aligned = unaligned[offset .. buff_length]; + char[] aligned = unaligned[offset .. buff_length]; assert(aligned.length == buff_length); ulong[3] retval; - foreach (ubyte[] buff; parData.byChunk(aligned)) { - assert((cast(size_t)buff.ptr & cast(size_t)(ulong.alignof - 1)) == 0); - tiger((cast(char[])buff).ptr, buff.length, retval, padding); + auto data_left = parData.size; + tiger_init(retval); + while (data_left >= buff_length) { + parData.rawRead(aligned); + tiger_chunk(aligned.ptr, buff_length, retval); + data_left -= buff_length; } + + const char padding = (parV2 ? 0x80 : 0x01); + if (data_left) { + parData.rawRead(aligned[0 .. data_left]); + const ulong proc_length = data_left & ~0x3fUL; + tiger_chunk(aligned.ptr, proc_length, retval); + tiger_last_chunk(aligned.ptr + proc_length, data_left - proc_length, parData.size, retval, padding); + } + else { + tiger_last_chunk(null, 0, parData.size, retval, padding); + } + return retval; } diff --git a/tiger.c b/tiger.c index e3e6e27..30607c0 100644 --- a/tiger.c +++ b/tiger.c @@ -27,6 +27,11 @@ typedef unsigned char byte; extern word64 table[4*256]; +union RawAccessULL4 { + word64 ull[8]; + unsigned char raw[64]; +}; + #define t1 (table) #define t2 (table+256) #define t3 (table+256*2) @@ -125,7 +130,6 @@ extern word64 table[4*256]; register word64 a, b, c, tmpa; \ word64 aa, bb, cc; \ register word64 x0, x1, x2, x3, x4, x5, x6, x7; \ - register word32 i; \ int pass_no; \ \ a = state[0]; \ @@ -143,7 +147,7 @@ extern word64 table[4*256]; } /* The compress function is a function. Requires smaller cache? */ -tiger_compress(word64 *str, word64 state[3]) +void tiger_compress(word64 *str, word64 state[3]) { tiger_compress_macro(((word64*)str), ((word64*)state)); } @@ -156,14 +160,20 @@ tiger_compress(word64 *str, word64 state[3]) tiger_compress_macro(((word64*)str), ((word64*)state)) #endif -tiger(word64 *str, word64 length, word64 res[3], byte pad) +void tiger_init(word64 res[3]) { - register word64 i, j; - unsigned char temp[64]; - res[0]=0x0123456789ABCDEFLL; res[1]=0xFEDCBA9876543210LL; res[2]=0xF096A5B4C3B2E187LL; +} + +void tiger_chunk(word64 *str, word64 length, word64 res[3]) +{ + register word64 i; +#ifdef BIG_ENDIAN + register word64 j; + unsigned char temp[64]; +#endif for(i=length; i>=64; i-=64) { @@ -176,33 +186,48 @@ tiger(word64 *str, word64 length, word64 res[3], byte pad) #endif str += 8; } +} + +void tiger_last_chunk(word64 *str, word64 length, word64 reallength, word64 res[3], byte pad) +{ + const word64 i = length & 0x3f; + register word64 j; + union RawAccessULL4 temp; #ifdef BIG_ENDIAN for(j=0; j56) { for(; j<64; j++) - temp[j] = 0; - tiger_compress(((word64*)temp), res); + temp.raw[j] = 0; + tiger_compress((temp.ull), res); j=0; } for(; j<56; j++) - temp[j] = 0; - ((word64*)(&(temp[56])))[0] = ((word64)length)<<3; - tiger_compress(((word64*)temp), res); + temp.raw[j] = 0; + temp.ull[7] = reallength<<3; + tiger_compress((temp.ull), res); +} + +void tiger(word64 *str, word64 length, word64 res[3], byte pad) +{ + const word64 proc_length = length & ~0x3fULL; + tiger_init(res); + tiger_chunk(str, proc_length, res); + tiger_last_chunk(str + (proc_length / 8), length - proc_length, length, res, pad); }