Static Hashing
To counter DOS attacks, the hasher used by Rhai, ahash, automatically generates a different
seed for hashing during each compilation and execution run.
This means that hash values generated by the hasher will not be stable – they change during each compile, and during each run.
For certain niche scenarios, however, dynamic hashes are undesirable.
So, when static hashing is employed, all hashing uses a fixed, predictable seed all the time.
Under static hashing, the same function signature always generate the same hash value, given the same seed.
A fixed hashing seed enlarges the attack surface of Rhai to malicious intent (e.g. DOS attacks).
Set at Run-Time
Call the static function rhai::config::hashing::set_ahash_seed with four u64 numbers that make
up the hashing seed.
The seed specified is always used to initialize the hasher.
// Set specific hashing seed - do this BEFORE anything else!
rhai::config::hashing::set_ahash_seed(Some([123, 456, 789, 42]))?;
// ... from now on, all hashing will be predictable
let engine = Engine::new();
rhai::config::hashing::set_ahash_seed can only ever be called once,
and must be called BEFORE performing any operation on Rhai (e.g. creating
an Engine).
Calling it a second time simply returns an error.
Set at Compile Time
The hashing seed can also be provided, at compile time, via the environment variable
RHAI_AHASH_SEED, with four u64 numbers that must be specified in Rust array literal format.
If a hashing seed is also set via rhai::config::hashing::set_ahash_seed,
this environment variable has no effect.
RHAI_AHASH_SEED="[123, 456, 789, 42]" cargo build ...
The seed specified in RHAI_AHASH_SEED is always used to initialize the hasher.
If the environment variable is missing, or it contains all zeros (i.e. [0, 0, 0, 0]),
then static hashing is disabled.
TL;DR
For static hashing seed, ahash requires:
default-features = falseruntime-rngfeature is not set (default on)compile-time-rngfeature is not set
The bane of additive Cargo features
However, ahash is also extremely popular, used by many many other crates,
most notably hashbrown.
Chances are that there are dependency crates that in turn depend on ahash with
default features. Since cargo features are additive, it is almost certain that ahash
will use a runtime-generated seed for large projects.
Hence, there exists a need to tell ahash to use a fixed seed, even when its feature flags
say otherwise.