HashMetadataValues carries SaltLength and HashLength alongside the type and
the cost parameters, and NeedsRehash ignored both. A hash with a 16-byte
digest or an 8-byte salt verified fine and was judged current forever --
exactly the drift this method exists to catch. Unreachable today, since
every hash ModernUO has written uses the library defaults of 32 and 16, but
that is a property of the current configuration rather than of the check.
The two lengths are the decoded sizes of the base64 segments rather than
entries in the m/t/p list, so they cannot be varied through the existing
theory template; they get their own rows with pinned literals. The
"current defaults" row of that theory is the negative control.
Also name the benchmark behind the 8.5 ms / 10.1 ms figures in the parameter
comment: ModernUO-Benchmarks/Benchmarks/Argon2Hashing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Argon2's PHC string embeds m, t and p, so verification uses the parameters
stored with each account rather than the configured ones -- and verify is the
hot path. CheckPassword only rehashed when the ALGORITHM changed, never when
its cost parameters did, so changing the defaults reached nobody on an
established shard and the change was cosmetic.
IPasswordProtection.NeedsRehash defaults to false, leaving PBKDF2 and the
HashAlgorithm protections untouched; only Argon2 carries cost in its stored
value. Logged at Debug because a restart migrates the whole population at once.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Argon2.Bindings 1.20.0 resolves the Argon2 type from the stored hash, so
existing Argon2i credentials keep verifying after this switch. Without that
bump this change locks out every existing account -- the pinned legacy-hash
test fails on 1.19.0 for exactly that reason.
16 MiB t=1 measures 8.51 ms against the old 8 MiB t=3 Argon2i at 10.11 ms:
cheaper AND stronger. Memory-hardness resists GPU and ASIC cracking;
iterations mostly buy wall-clock, so trade t down for m up. It also stays
below the 16-32 MiB L3 inflection, which starts to matter once hashing moves
off the game loop and contends with the loop's working set.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
### Summary
.NET 8 supports Xoroshiro 256** off the shelf and added Shuffle. Switching to that implementation.
### Developer Notes
* Removed many convenience methods that weren't used.
**Only one functional change**
* Fixes a bug in LogFactory where `Warning` is being logged as `Information`
Non-functional changes:
* Updates/Fixes copyright headers
* Removes namespace scopes for core files.
View with [whitespace off](https://github.com/modernuo/ModernUO/pull/1187/files?w=1).