Optimize hashing of generic types

Use a proper hash function instead of f(x)=x to achieve better distribution of hash values

(cherry picked from commit 5eeff1d9c15dfdce6ade9bed455e8fdaab777b31)
This commit is contained in:
SChernykh
2026-10-04 18:50:21 -04:00
committed by such-gitea
parent 1ead51defe
commit ad119391eb
4 changed files with 32 additions and 8 deletions
+18 -7
View File
@@ -32,9 +32,13 @@
#include <cstddef>
#include <cstring>
#include <cstdint>
#include <functional>
#include <memory>
#include <sodium/crypto_verify_32.h>
#include <sodium/crypto_shorthash_siphash24.h>
#include "random.h"
#define CRYPTO_MAKE_COMPARABLE(type) \
namespace crypto { \
@@ -57,22 +61,29 @@ namespace crypto { \
} \
}
namespace crypto {
inline std::size_t siphash_to_size_t(const void *data, std::size_t length) {
static_assert(sizeof(crypto_siphash_key) == crypto_shorthash_siphash24_KEYBYTES,
"crypto_siphash_key size must match the SipHash-2-4 key length");
static_assert(sizeof(std::uint64_t) == crypto_shorthash_siphash24_BYTES,
"std::uint64_t size must match the SipHash-2-4 digest length");
std::uint64_t h;
crypto_shorthash_siphash24(reinterpret_cast<unsigned char*>(&h), static_cast<const unsigned char*>(data), length, crypto_siphash_key);
return h;
}
}
#define CRYPTO_DEFINE_HASH_FUNCTIONS(type) \
namespace crypto { \
static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \
inline std::size_t hash_value(const type &_v) { \
std::size_t h; \
memcpy(&h, std::addressof(_v), sizeof(h)); \
return h; \
return siphash_to_size_t(std::addressof(_v), sizeof(_v)); \
} \
} \
namespace std { \
template<> \
struct hash<crypto::type> { \
std::size_t operator()(const crypto::type &_v) const { \
std::size_t h; \
memcpy(&h, std::addressof(_v), sizeof(h)); \
return h; \
return ::crypto::siphash_to_size_t(std::addressof(_v), sizeof(_v)); \
} \
}; \
}
+3
View File
@@ -96,6 +96,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
#endif
static union hash_state state;
unsigned char crypto_siphash_key[16];
#if !defined(NDEBUG)
static volatile int curstate; /* To catch thread safety problems. */
@@ -107,10 +108,12 @@ FINALIZER(deinit_random) {
curstate = 0;
#endif
memset(&state, 0, sizeof(union hash_state));
memset(crypto_siphash_key, 0, sizeof(crypto_siphash_key));
}
INITIALIZER(init_random) {
generate_system_random_bytes(32, &state);
generate_system_random_bytes(sizeof(crypto_siphash_key), crypto_siphash_key);
REGISTER_FINALIZER(deinit_random);
#if !defined(NDEBUG)
assert(curstate == 0);
+10
View File
@@ -32,5 +32,15 @@
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void generate_random_bytes_not_thread_safe(size_t n, void *result);
void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes);
extern unsigned char crypto_siphash_key[16];
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -789,7 +789,7 @@ inline std::ostream &operator <<(std::ostream &o, const rct::key &v) {
namespace std
{
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return reinterpret_cast<const std::size_t&>(k); } };
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return ::crypto::siphash_to_size_t(&k, sizeof(k)); } };
}
BLOB_SERIALIZER(rct::key);