/** * Store calculated hash into the given array. * * @param ctx the algorithm context containing current hashing state * @param result calculated hash in binary form */ void rhash_tth_final(tth_ctx *ctx, unsigned char result[24]) { uint64_t it = 1; unsigned pos = 0; unsigned char msg[24]; const unsigned char* last_message; /* process the bytes left in the context buffer */ if(ctx->tiger.length > 1 || ctx->block_count == 0) { rhash_tth_process_block(ctx); } for(; it < ctx->block_count && (it & ctx->block_count) == 0; it <<= 1) pos += 3; last_message = (unsigned char*)(ctx->stack + pos); for(it <<= 1; it <= ctx->block_count; it <<= 1) { /* merge TTH sums in the tree */ pos += 3; if(it & ctx->block_count) { rhash_tiger_init(&ctx->tiger); ctx->tiger.message[ ctx->tiger.length++ ] = 0x01; rhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24); rhash_tiger_update(&ctx->tiger, last_message, 24); rhash_tiger_final(&ctx->tiger, msg); last_message = msg; } } /* save result hash */ memcpy(ctx->tiger.hash, last_message, tiger_hash_length); if(result) memcpy(result, last_message, tiger_hash_length); }
/** * The core transformation. * * @param ctx algorithm state */ static void rhash_tth_process_block(tth_ctx *ctx) { uint64_t it; unsigned pos = 0; unsigned char msg[24]; for(it = 1; it & ctx->block_count; it <<= 1) { rhash_tiger_final(&ctx->tiger, msg); rhash_tiger_init(&ctx->tiger); ctx->tiger.message[ctx->tiger.length++] = 0x01; rhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24); /* note: we can cut this step, if the previous rhash_tiger_final saves directly to ctx->tiger.message+25; */ rhash_tiger_update(&ctx->tiger, msg, 24); pos += 3; } rhash_tiger_final(&ctx->tiger, (unsigned char*)(ctx->stack + pos)); ctx->block_count++; }
/** * Calculate message hash. * Can be called repeatedly with chunks of the message to be hashed. * * @param ctx the algorithm context containing current hashing state * @param msg message chunk * @param size length of the message chunk */ void rhash_tth_update(tth_ctx *ctx, const unsigned char* msg, size_t size) { size_t rest = 1025 - (size_t)ctx->tiger.length; for(;;) { if(size < rest) rest = size; rhash_tiger_update(&ctx->tiger, msg, rest); msg += rest; size -= rest; if(ctx->tiger.length < 1025) { return; } /* process block hash */ rhash_tth_process_block(ctx); /* init block hash */ rhash_tiger_init(&ctx->tiger); ctx->tiger.message[ ctx->tiger.length++ ] = 0x00; rest = 1024; } }
/** * Initialize context before calculaing hash. * * @param ctx context to initialize */ void rhash_tth_init(tth_ctx *ctx) { rhash_tiger_init(&ctx->tiger); ctx->tiger.message[ ctx->tiger.length++ ] = 0x00; ctx->block_count = 0; }
unsigned char *computeV4(const unsigned char *src, int len) { static unsigned char buf[0x100]; static unsigned char s[20]; memcpy(s, src, 16); unsigned char wtmp[160]; int wpos = 0; int i; uint32_t v4_check_type = ((signed char)s[0] + (signed char)s[3]) % 5u; printf("V4 type: %d\n", v4_check_type); switch(v4_check_type) { case 0: { unsigned char mtmp[16]; md5_ctx mctx; rhash_md5_init(&mctx); rhash_md5_update(&mctx, array, 0x71c); rhash_md5_final(&mctx, mtmp); char tbuf[10]; for (i=0; i<16; ++i) { sprintf((char*)wtmp + wpos, "%02x", mtmp[i]); wpos += 2; } for (i=0; i<8; ++i) { sprintf(tbuf, "%02x", (signed char)(s[2*i])); strcpy((char*)wtmp + wpos, tbuf); wpos += strlen(tbuf); } rhash_md5_init(&mctx); rhash_md5_update(&mctx, array_1, 0x7f3); rhash_md5_final(&mctx, mtmp); for (i=0; i<16; ++i) { sprintf((char*)wtmp + wpos, "%02x", mtmp[i]); wpos += 2; } for (i=0; i<8; ++i) { sprintf(tbuf, "%02x", (signed char)(s[2*i+1])); strcpy((char*)wtmp + wpos, tbuf); wpos += strlen(tbuf); } wpos = 0x60; break; } case 1: { sha1_ctx sctx; rhash_sha1_init(&sctx); rhash_sha1_update(&sctx, array_1,0x7f3); rhash_sha1_final(&sctx, wtmp); wpos += 20; memcpy(wtmp + wpos, s, 6); wpos += 6; rhash_sha1_init(&sctx); rhash_sha1_update(&sctx, array,0x71c); rhash_sha1_final(&sctx,wtmp + wpos); wpos += 20; memcpy(wtmp + wpos, s+6, 10); wpos += 10; break; } case 2: { sha1_ctx sctx; rhash_sha1_init(&sctx); rhash_sha1_update(&sctx,array_1,0x7f3); rhash_sha1_final(&sctx,wtmp); wpos += 20; memcpy(wtmp + wpos, s, 6); wpos += 6; struct ampheck_ripemd128 rctx; ampheck_ripemd128_init(&rctx); ampheck_ripemd128_update(&rctx, array, 0x71c); ampheck_ripemd128_finish(&rctx, wtmp + wpos); wpos += 16; memcpy(wtmp + wpos, s+6, 10); wpos += 10; break; } case 3: { tiger_ctx tctx; rhash_tiger_init(&tctx); rhash_tiger_update(&tctx,array,0x71c); rhash_tiger_final(&tctx,wtmp); wpos += 24; memcpy(wtmp + wpos, s, 10); wpos += 10; struct ampheck_ripemd128 rctx; ampheck_ripemd128_init(&rctx); ampheck_ripemd128_update(&rctx, array_1, 0x7f3); ampheck_ripemd128_finish(&rctx, wtmp + wpos); wpos += 16; memcpy(wtmp + wpos, s+10, 6); wpos += 6; break; } case 4: { tiger_ctx tctx; rhash_tiger_init(&tctx); rhash_tiger_update(&tctx,array_1,0x7f3); rhash_tiger_final(&tctx,wtmp); wpos += 24; memcpy(wtmp + wpos, s, 8); wpos += 8; sha1_ctx sctx; rhash_sha1_init(&sctx); rhash_sha1_update(&sctx,array,0x71c); rhash_sha1_final(&sctx,wtmp + wpos); wpos += 20; memcpy(wtmp + wpos, s+8, 8); wpos += 8; break; } default: { return NULL; } } whirlpool_ctx w; static unsigned char digest[100]; rhash_whirlpool_init(&w); rhash_whirlpool_update(&w, wtmp, wpos); rhash_whirlpool_final(&w, digest); char tbuf[10]; for (i = 0; i<64; ++i) { sprintf(tbuf, "%02x", digest[i]); buf[2*i] = tbuf[0]; buf[2*i+1] = tbuf[1]; } return buf; }