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 = false
runtime-rng
feature is not set (default on)compile-time-rng
feature 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.