Example #1
0
Hasher::hashStatus_t Hasher::hash(const string& filename, string& hash) {
  unsigned rhashType;
  switch( p_hashType ) {
    case tth: rhashType = RHASH_TTH; break;
    case md5: rhashType = RHASH_MD5; break;
    case sha1: rhashType = RHASH_SHA1; break;
    default:
      LOG(logError) << "Hasher called with no hash algorithm selected";
      return noHashSelected;
  }

  unsigned char digest[64];
  int res = rhash_file(rhashType, filename.c_str(), digest);
  if( res < 0 ) {
    LOG(logError) << "LibRHash error: " << strerror(errno);
    return hashError;
  }

  char output[130];
  size_t length = 0;
  if( p_hashType == tth )
    length = rhash_print_bytes(output, digest, rhash_get_digest_size(rhashType), RHPR_BASE32);
  else
    length = rhash_print_bytes(output, digest, rhash_get_digest_size(rhashType), RHPR_HEX);
  hash = string(output, length);

  LOG(logDetailed) << "Calculated " << rhash_get_name(rhashType) << " hash of file " << filename << ": " << hash;
  return hashSuccess;
}
Example #2
0
/**
 * Verify for all algorithms, that rhash_final() returns the same result as
 * rhash_print().
 */
static void test_results_consistency(void)
{
	const char * msg = "a";
	size_t msg_size = strlen(msg);

	size_t digest_size;
	struct rhash_context *ctx;
	unsigned char res1[70];
	char res2[70];
	unsigned i, hash_id;

	for(i = 0, hash_id = 1; (hash_id & RHASH_ALL_HASHES); hash_id <<= 1, i++) {
		digest_size = rhash_get_digest_size(hash_id);
		assert(digest_size < 70);

		ctx = rhash_init(hash_id);

#ifdef USE_BTIH_WITH_TEST_FILENAME
		if((hash_id & RHASH_BTIH) != 0) {
			unsigned long long total_size = msg_size;
			rhash_transmit(RMSG_BT_ADD_FILE, ctx, RHASH_STR2UPTR("test.txt"), (rhash_uptr_t)&total_size);
		}
#endif

		rhash_update(ctx, msg, msg_size);
		rhash_final(ctx, res1);
		rhash_print(res2, ctx, hash_id, RHPR_RAW);
		rhash_free(ctx);

		if(memcmp(res1, res2, digest_size) != 0) {
			log_message("failed: inconsistent %s(\"%s\") hash results\n", rhash_get_name(hash_id), msg);
		}
	}
}
Example #3
0
/**
 * Initialize information about hashes, stored in the
 * hash_info_table global variable.
 */
void init_hash_info_table(void)
{
	unsigned index, bit;
	unsigned short_opt_mask = RHASH_CRC32 | RHASH_MD5 | RHASH_SHA1 | RHASH_TTH | RHASH_ED2K |
		RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 | RHASH_GOST | OPT_ED2K_LINK;
	char* short_opt = "cmhteawrgl";
	print_hash_info *info = hash_info_table;
	unsigned fullmask = RHASH_ALL_HASHES | OPT_ED2K_LINK;

	memset(hash_info_table, 0, sizeof(hash_info_table));

	for(index = 0, bit = 1; bit <= fullmask; index++, bit = bit << 1, info++) {
		const char *p;
		char *e, *d;

		info->short_char = ((bit & short_opt_mask) != 0 && *short_opt ?
			*(short_opt++) : 0);

		info->name = (bit & RHASH_ALL_HASHES ? rhash_get_name(bit) : "ED2K_LINK");
		d = info->short_name;
		e = info->short_name + 15; /* buffer overflow protection */
		assert(strlen(info->name) < (size_t)(e-d));
		for(p = info->name; *p && d < e; p++) if(*p != '-' || p[1] >= '9') *(d++) = (*p | 0x20);
		*d = 0;
	}
}
Example #4
0
/**
 * Verify that calculated hash doesn't depend on message alignment.
 */
static void test_alignment(void)
{
    int i, start, hash_id, alignment_size;

    /* loop by sums */
    for(i = 0, hash_id = 1; (hash_id & RHASH_ALL_HASHES); hash_id <<= 1, i++) {
        char expected_hash[130];
        assert(rhash_get_digest_size(hash_id) < (int)sizeof(expected_hash));

        alignment_size = (hash_id & (RHASH_TTH | RHASH_TIGER | RHASH_WHIRLPOOL | RHASH_SHA512) ? 8 : 4);

        /* start message with different alignment */
        for(start = 0; start < alignment_size; start++) {
            char message[30];
            char* obtained;
            int j, msg_length = 11 + alignment_size;

            /* fill the buffer fifth shifted letter sequence */
            for(j = 0; j < msg_length; j++) message[start + j] = 'a' + j;
            message[start + j] = 0;

            obtained = calc_sum(message + start, hash_id);

            if(start == 0) {
                /* save original sum */
                strcpy(expected_hash, obtained);
            } else {
                /* verify sum result */
                assert_equals(obtained, expected_hash, rhash_get_name(hash_id), message);
                fflush(stdout);
            }
        }
    }
}
Example #5
0
/**
 * Test a hash algorithm against a long messages of zeroes.
 * Report error if calculated hash doesn't coincide with expected value.
 *
 * @param hash_id id of the algorithm to test
 * @param size the length of message of zeroes in bytes
 * @param expected_hash the expected hash balue
 */
static void test_long_zero_msg(unsigned hash_id, size_t size, const char* expected_hash)
{
    char buffer[8192];
    char msg[80], *obtained;
    memset(buffer, 0, 8192);
    sprintf(msg, "\"\\0\"x%u", (unsigned)size);
    obtained = calc_sums_c(buffer, 8192, size, hash_id);
    assert_equals(obtained, expected_hash, rhash_get_name(hash_id), msg);
}
Example #6
0
/**
 * Print the names of all supported hash algorithms to the console.
 */
static void list_hashes(void)
{
	int id;
	for(id = 1; id < RHASH_ALL_HASHES; id <<= 1) {
		const char* hash_name = rhash_get_name(id);
		if(hash_name) fprintf(rhash_data.out, "%s\n", hash_name);
	}
	rsh_exit(0);
}
Example #7
0
/**
 * Test a hash algorithm against a message of given length, consisting
 * of repeated chunks.
 * Report error if calculated hash differs from the expected value.
 *
 * @param hash_id id of the algorithm to test
 * @param msg_chunk the message chunk as a null-terminated string
 * @param chunk_size the size of the chunk in bytes
 * @param count the number of chunks in the message
 * @param hash the expected hash value
 * @param set_filename need to set a filename for BTIH hash
 */
static void assert_hash_long_msg(unsigned hash_id, const char* msg_chunk, size_t chunk_size, size_t msg_size, const char* hash, const char* msg_name, int set_filename)
{
	char* result;
	result = repeat_hash(hash_id, msg_chunk, chunk_size, msg_size, set_filename);
	if(strcmp(result, hash) != 0) {
		const char* hash_name = rhash_get_name(hash_id); /* the hash function name */
		if(msg_name) log_message("failed: %s(%s) = %s, expected %s\n", hash_name, msg_name, result, hash);
		else log_message("failed: %s(\"%s\") = %s, expected %s\n", hash_name, msg_chunk, result, hash);
		g_errors++;
	}
}
Example #8
0
File: output.c Project: rhash/RHash
/**
 * Print verbose error on hash sums mismatch.
 *
 * @param info file information with path and its hash sums.
 */
static void print_verbose_error(struct file_info *info)
{
	char actual[130], expected[130];
	assert(HC_FAILED(info->hc.flags));

	rsh_fprintf(rhash_data.out, _("ERROR"));

	if (HC_WRONG_FILESIZE & info->hc.flags) {
		sprintI64(actual, info->rctx->msg_size, 0);
		sprintI64(expected, info->hc.file_size, 0);
		rsh_fprintf(rhash_data.out, _(", size is %s should be %s"), actual, expected);
	}

	if (HC_WRONG_EMBCRC32 & info->hc.flags) {
		rhash_print(expected, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
		rsh_fprintf(rhash_data.out, _(", embedded CRC32 should be %s"), expected);
	}

	if (HC_WRONG_HASHES & info->hc.flags) {
		int i;
		unsigned reported = 0;
		for (i = 0; i < info->hc.hashes_num; i++) {
			hash_value *hv = &info->hc.hashes[i];
			char *expected_hash = info->hc.data + hv->offset;
			unsigned hid = hv->hash_id;
			int pflags;
			if ((info->hc.wrong_hashes & (1 << i)) == 0) continue;

			assert(hid != 0);

			/* if can't detect precise hash */
			if ((hid & (hid - 1)) != 0) {
				/* guess the hash id */
				if (hid & opt.sum_flags) hid &= opt.sum_flags;
				if (hid & ~info->hc.found_hash_ids) hid &= ~info->hc.found_hash_ids;
				if (hid & ~reported) hid &= ~reported; /* avoiding repeating */
				if (hid & REPORT_FIRST_MASK) hid &= REPORT_FIRST_MASK;
				hid &= -(int)hid; /* take the lowest bit */
			}
			assert(hid != 0 && (hid & (hid - 1)) == 0); /* single bit only */
			reported |= hid;

			pflags = (hv->length == (rhash_get_digest_size(hid) * 2) ?
				(RHPR_HEX | RHPR_UPPERCASE) : (RHPR_BASE32 | RHPR_UPPERCASE));
			rhash_print(actual, info->rctx, hid, pflags);
			rsh_fprintf(rhash_data.out, _(", %s is %s should be %s"),
				rhash_get_name(hid), actual, expected_hash);
		}
	}

	rsh_fprintf(rhash_data.out, "\n");
}
Example #9
0
/**
 * Find hash id by its name.
 *
 * @param name hash algorithm name
 * @return algorithm id
 */
static unsigned find_hash(const char* name)
{
	char buf[30];
	unsigned hash_id;
	int i;

	if(strlen(name) > (sizeof(buf) - 1)) return 0;
	for(i = 0; name[i]; i++) buf[i] = toupper(name[i]);
	buf[i] = 0;

	for(hash_id = 1; (hash_id & RHASH_ALL_HASHES); hash_id <<= 1) {
		if(strcmp(buf, rhash_get_name(hash_id)) == 0) return hash_id;
	}
	return 0;
}
Example #10
0
/**
 * Test a hash algorithm against a message of given length and consisting
 * of repeated chunks.
 * Report error if calculated hash doesn't coincide with expected value.
 *
 * @param hash_id id of the algorithm to test
 * @param chunk the message chunk as a null-terminated string
 * @param size the length of message of zeroes in bytes
 * @param expected_hash the expected hash balue
 */
static void test_long_msg(unsigned hash_id, const char* chunk, size_t size, const char* expected_hash)
{
    size_t chunk_length = strlen(chunk);
    char* obtained = calc_sums_c(chunk, chunk_length, size, hash_id);
    assert_equals(obtained, expected_hash, rhash_get_name(hash_id), chunk);
}
Example #11
0
/**
 * Test a hash algorithm on given message by comparing calculated result with
 * expected one. Report error on fail.
 *
 * @param message the message to hash
 * @param expected_hash the expected hash balue
 * @param hash_id id of the algorithm to test
 */
static void test_str(const char* message, const char* expected_hash, unsigned hash_id)
{
    char* obtained = calc_sum(message, hash_id);
    assert_equals(obtained, expected_hash, rhash_get_name(hash_id), message);
}
Example #12
0
/**
 * Benchmark a hash algorithm.
 *
 * @deprecated This function shall be removed soon, since
 * it is not related to the hashing library main functionality.
 *
 * @param hash_id hash algorithm identifier
 * @param flags benchmark flags, can be RHASH_BENCHMARK_QUIET and RHASH_BENCHMARK_CPB
 * @param output the stream to print results
 */
void rhash_run_benchmark(unsigned hash_id, unsigned flags, FILE* output)
{
	unsigned char ALIGN_ATTR(16) message[8192]; /* 8 KiB */
	timedelta_t timer;
	int i, j;
	size_t sz_mb, msg_size;
	double time, total_time = 0;
	const int rounds = 4;
	const char* hash_name;
	unsigned char out[130];
#ifdef HAVE_TSC
	double cpb = 0;
#endif /* HAVE_TSC */

#ifdef _WIN32
	benchmark_cpu_init(); /* set cpu affinity to improve test results */
#endif

	/* set message size for fast and slow hash functions */
	msg_size = 1073741824 / 2;
	if (hash_id & (RHASH_WHIRLPOOL | RHASH_SNEFRU128 | RHASH_SNEFRU256 | RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512)) {
		msg_size /= 8;
	} else if (hash_id & (RHASH_GOST | RHASH_GOST_CRYPTOPRO | RHASH_SHA384 | RHASH_SHA512)) {
		msg_size /= 2;
	}
	sz_mb = msg_size / (1 << 20); /* size in MiB */
	hash_name = rhash_get_name(hash_id);
	if (!hash_name) hash_name = ""; /* benchmarking several hashes*/

	for (i = 0; i < (int)sizeof(message); i++) message[i] = i & 0xff;

	for (j = 0; j < rounds; j++) {
		rhash_timer_start(&timer);
		hash_in_loop(hash_id, message, sizeof(message), (int)(msg_size / sizeof(message)), out);

		time = rhash_timer_stop(&timer);
		total_time += time;

		if ((flags & (RHASH_BENCHMARK_QUIET | RHASH_BENCHMARK_RAW)) == 0) {
			fprintf(output, "%s %u MiB calculated in %.3f sec, %.3f MBps\n", hash_name, (unsigned)sz_mb, time, (double)sz_mb / time);
			fflush(output);
		}
	}

#if defined(HAVE_TSC)
	/* measure the CPU "clocks per byte" speed */
	if (flags & RHASH_BENCHMARK_CPB) {
		unsigned int c1 = -1, c2 = -1;
		unsigned volatile long long cy0, cy1, cy2;
		int msg_size = 128 * 1024;

		/* make 200 tries */
		for (i = 0; i < 200; i++) {
			cy0 = read_tsc();
			hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
			cy1 = read_tsc();
			hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
			hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
			cy2 = read_tsc();

			cy2 -= cy1;
			cy1 -= cy0;
			c1 = (unsigned int)(c1 > cy1 ? cy1 : c1);
			c2 = (unsigned int)(c2 > cy2 ? cy2 : c2);
		}
		cpb = ((c2 - c1) + 1) / (double)msg_size;
	}
#endif /* HAVE_TSC */

	if (flags & RHASH_BENCHMARK_RAW) {
		/* output result in a "raw" machine-readable format */
		fprintf(output, "%s\t%u\t%.3f\t%.3f", hash_name, ((unsigned)sz_mb * rounds), total_time, (double)(sz_mb * rounds) / total_time);
#if defined(HAVE_TSC)
		if (flags & RHASH_BENCHMARK_CPB) fprintf(output, "\t%.2f", cpb);
#endif /* HAVE_TSC */
		fprintf(output, "\n");
	} else {
		fprintf(output, "%s %u MiB total in %.3f sec, %.3f MBps", hash_name, ((unsigned)sz_mb * rounds), total_time, (double)(sz_mb * rounds) / total_time);
#if defined(HAVE_TSC)
		if (flags & RHASH_BENCHMARK_CPB) fprintf(output, ", CPB=%.2f", cpb);
#endif /* HAVE_TSC */
		fprintf(output, "\n");
	}
}