Developers
.NET usage
Package ForgeHash 1.0.0-experimental. The class shares the namespace name — alias it in call sites. Part of the developers path.
Experimental software. Do not store production passwords with ForgeHash.
Install
From nuget.org (experimental prerelease):
dotnet add package ForgeHash --prerelease
dotnet add package ForgeHashX --prerelease
dotnet tool install -g ForgeHash.Cli --prerelease
forgeh --help
ForgeHash · ForgeHashX · ForgeHash.Cli
Or pack / reference from this repo while developing:
dotnet pack src/ForgeHash.Core/ForgeHash.Core.csproj -c Release -o artifacts/nuget
dotnet add package ForgeHash --source ./artifacts/nuget --prerelease
dotnet add reference ../path/to/ForgeHash/src/ForgeHash.Core/ForgeHash.Core.csproj
See Developers for all registries and CLI examples. Publisher ops: docs/PUBLISHING.md.
Minimal login flow
using ForgeHash;
using ForgeHashApi = ForgeHash.ForgeHash; // class shares the namespace name
string encoded = ForgeHashApi.HashPassword(passwordBytes, ForgeHashParameters.Interactive);
bool ok = ForgeHashApi.VerifyPassword(passwordBytes, encoded);
if (ok && ForgeHashApi.NeedsRehash(encoded, ForgeHashParameters.Interactive))
{
string upgraded = ForgeHashApi.HashPassword(passwordBytes, ForgeHashParameters.Interactive);
// Persist upgraded hash
}
Profiles
| Profile | When to use |
|---|---|
ForgeHashParameters.Development | Local tests / CI only |
ForgeHashParameters.Interactive | Default research interactive cost |
ForgeHashParameters.Sensitive | Higher-cost experiments |
Never silently default to Development in production-shaped builds.
Pepper (optional)
byte[] pepper = /* 32 bytes from a secrets manager */;
string encoded = ForgeHashApi.HashPassword(passwordBytes, pepper, parameters);
bool ok = ForgeHashApi.VerifyPassword(passwordBytes, pepper, encoded);
The pepper never appears in the encoded string.
Exact bytes vs strings
ReadOnlySpan<byte>APIs are exact.stringAPIs encode UTF-8 and do not Unicode-normalize.- Immutable strings cannot be wiped; prefer byte buffers for secrets when practical.
Parsing
if (!ForgeHashParser.TryParse(encoded, out ParsedForgeHash? parsed) || parsed is null)
{
// malformed stored hash
}
else
{
// parsed.MemoryKiB / Iterations / Parallelism / Salt / Hash
}
VerifyPassword already returns false for malformed input.
Low-level research API
byte[] digest = ForgeHashApi.DeriveHash(password, salt, parameters);
This does not generate a salt. You must supply one.
Sample project
dotnet run --project samples/ForgeHash.Sample -- "demo-password"