/** * 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_md5_final(md5_ctx *ctx, unsigned char* result) { unsigned index = ((unsigned)ctx->length & 63) >> 2; unsigned shift = ((unsigned)ctx->length & 3) * 8; /* pad message and run for last block */ /* append the byte 0x80 to the message */ ctx->message[index] &= ~(0xFFFFFFFF << shift); ctx->message[index++] ^= 0x80 << shift; /* if no room left in the message to store 64-bit message length */ if(index > 14) { /* then fill the rest with zeros and process it */ while(index < 16) { ctx->message[index++] = 0; } rhash_md5_process_block(ctx->hash, ctx->message); index = 0; } while(index < 14) { ctx->message[index++] = 0; } ctx->message[14] = (unsigned)(ctx->length << 3); ctx->message[15] = (unsigned)(ctx->length >> 29); rhash_md5_process_block(ctx->hash, ctx->message); if(result) le32_copy(result, 0, &ctx->hash, 16); }
/** * Compute and save calculated hash into the given array. * * @param ctx the algorithm context containing current hashing state * @param result calculated hash in binary form */ void has160_final(has160_ctx *ctx, unsigned char* result) { unsigned shift = ((unsigned)ctx->length & 3) * 8; unsigned index = ((unsigned)ctx->length & 63) >> 2; /* pad message and run for last block */ #ifdef CPU_LITTLE_ENDIAN ctx->message[index] &= ~(0xFFFFFFFF << shift); ctx->message[index++] ^= 0x80 << shift; #else ctx->message[index] &= ~(0xFFFFFFFF >> shift); ctx->message[index++] ^= 0x80000000 >> shift; #endif /* if no room left in the message to store 64-bit message length */ if(index>14) { /* then fill the rest with zeros and process it */ while(index < 16) { ctx->message[index++] = 0; } has160_process_block(ctx->hash, ctx->message); index = 0; } while(index < 14) { ctx->message[index++] = 0; } ctx->message[14] = le2me_32( (unsigned)(ctx->length << 3) ); ctx->message[15] = le2me_32( (unsigned)(ctx->length >> 29) ); has160_process_block(ctx->hash, ctx->message); le32_copy(result, &ctx->hash, has160_hash_size); }
/** * 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_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size) { unsigned index = (unsigned)ctx->length & 63; ctx->length += size; /* fill partial block */ if(index) { unsigned left = md5_block_size - index; le32_copy((char*)ctx->message, index, msg, (size < left ? size : left)); if(size < left) return; /* process partial block */ rhash_md5_process_block(ctx->hash, ctx->message); msg += left; size -= left; } while(size >= md5_block_size) { unsigned* aligned_message_block; if(IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) { /* the most common case is processing a 32-bit aligned message on a little-endian CPU without copying it */ aligned_message_block = (unsigned*)msg; } else { le32_copy(ctx->message, 0, msg, md5_block_size); aligned_message_block = ctx->message; } rhash_md5_process_block(ctx->hash, aligned_message_block); msg += md5_block_size; size -= md5_block_size; } if(size) { /* save leftovers */ le32_copy(ctx->message, 0, msg, size); } }