chunk: Add predictable hash function
Since chunk_hash() is randomized its output is not predictable, that is, it is only within the same process.
This commit is contained in:
@@ -698,7 +698,6 @@ START_TEST(test_chunk_mac)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* test for chunk_hash[_inc]()
|
* test for chunk_hash[_inc]()
|
||||||
*/
|
*/
|
||||||
@@ -721,6 +720,35 @@ START_TEST(test_chunk_hash)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* test for chunk_hash_static[_inc]()
|
||||||
|
*/
|
||||||
|
|
||||||
|
START_TEST(test_chunk_hash_static)
|
||||||
|
{
|
||||||
|
chunk_t in;
|
||||||
|
u_int32_t out, hash_a, hash_b, hash_inc = 0x7b891a95;
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
count = countof(sip_vectors);
|
||||||
|
in = chunk_alloca(count);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
in.ptr[i] = i;
|
||||||
|
in.len = i;
|
||||||
|
/* compared to chunk_mac() we only get half the value back */
|
||||||
|
out = chunk_hash_static(in);
|
||||||
|
fail_unless(memeq(&out, sip_vectors[i], 4),
|
||||||
|
"test vector failed for %d bytes", i);
|
||||||
|
}
|
||||||
|
hash_a = chunk_hash_static_inc(in, out);
|
||||||
|
ck_assert_int_eq(hash_a, hash_inc);
|
||||||
|
hash_b = chunk_hash_static_inc(in, out);
|
||||||
|
ck_assert_int_eq(hash_a, hash_b);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* printf_hook tests
|
* printf_hook tests
|
||||||
*/
|
*/
|
||||||
@@ -822,6 +850,10 @@ Suite *chunk_suite_create()
|
|||||||
tcase_add_test(tc, test_chunk_hash);
|
tcase_add_test(tc, test_chunk_hash);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("chunk_hash_static");
|
||||||
|
tcase_add_test(tc, test_chunk_hash_static);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("printf_hook");
|
tc = tcase_create("printf_hook");
|
||||||
tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data));
|
tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data));
|
||||||
tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_hook_data));
|
tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_hook_data));
|
||||||
|
|||||||
@@ -705,6 +705,12 @@ u_int64_t chunk_mac(chunk_t chunk, u_char *key)
|
|||||||
*/
|
*/
|
||||||
static u_char key[16];
|
static u_char key[16];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static key used in case predictable hash values are required.
|
||||||
|
*/
|
||||||
|
static u_char static_key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allocate the key once
|
* Only allocate the key once
|
||||||
*/
|
*/
|
||||||
@@ -764,6 +770,22 @@ u_int32_t chunk_hash(chunk_t chunk)
|
|||||||
return chunk_mac(chunk, key);
|
return chunk_mac(chunk, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash)
|
||||||
|
{ /* we could use a mac of the previous hash, but this is faster */
|
||||||
|
return chunk_mac_inc(chunk, static_key, ((u_int64_t)hash) << 32 | hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
u_int32_t chunk_hash_static(chunk_t chunk)
|
||||||
|
{
|
||||||
|
return chunk_mac(chunk, static_key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -302,7 +302,13 @@ bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
|
|||||||
/**
|
/**
|
||||||
* Computes a 32 bit hash of the given chunk.
|
* Computes a 32 bit hash of the given chunk.
|
||||||
*
|
*
|
||||||
* @note This hash is only intended for hash tables not for cryptographic purposes.
|
* @note The output of this function is randomized, that is, it will only
|
||||||
|
* produce the same output for the same input when calling it from the same
|
||||||
|
* process. For a more predictable hash function use chunk_hash_static()
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* @note This hash is only intended for hash tables not for cryptographic
|
||||||
|
* purposes.
|
||||||
*
|
*
|
||||||
* @param chunk data to hash
|
* @param chunk data to hash
|
||||||
* @return hash value
|
* @return hash value
|
||||||
@@ -318,6 +324,30 @@ u_int32_t chunk_hash(chunk_t chunk);
|
|||||||
*/
|
*/
|
||||||
u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
|
u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a 32 bit hash of the given chunk.
|
||||||
|
*
|
||||||
|
* Compared to chunk_hash() this will always calculate the same output for the
|
||||||
|
* same input. Therefore, it should not be used for hash tables (to prevent
|
||||||
|
* hash flooding).
|
||||||
|
*
|
||||||
|
* @note This hash is not intended for cryptographic purposes.
|
||||||
|
*
|
||||||
|
* @param chunk data to hash
|
||||||
|
* @return hash value
|
||||||
|
*/
|
||||||
|
u_int32_t chunk_hash_static(chunk_t chunk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incremental version of chunk_hash_static(). Use this to hash two or more
|
||||||
|
* chunks in a predictable way.
|
||||||
|
*
|
||||||
|
* @param chunk data to hash
|
||||||
|
* @param hash previous hash value
|
||||||
|
* @return hash value
|
||||||
|
*/
|
||||||
|
u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes a quick MAC from the given chunk and key using SipHash.
|
* Computes a quick MAC from the given chunk and key using SipHash.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user