Masterly.Hash.DependencyInjection
2.0.0
dotnet add package Masterly.Hash.DependencyInjection --version 2.0.0
NuGet\Install-Package Masterly.Hash.DependencyInjection -Version 2.0.0
<PackageReference Include="Masterly.Hash.DependencyInjection" Version="2.0.0" />
<PackageVersion Include="Masterly.Hash.DependencyInjection" Version="2.0.0" />
<PackageReference Include="Masterly.Hash.DependencyInjection" />
paket add Masterly.Hash.DependencyInjection --version 2.0.0
#r "nuget: Masterly.Hash.DependencyInjection, 2.0.0"
#:package Masterly.Hash.DependencyInjection@2.0.0
#addin nuget:?package=Masterly.Hash.DependencyInjection&version=2.0.0
#tool nuget:?package=Masterly.Hash.DependencyInjection&version=2.0.0
Masterly.Hash.DependencyInjection

Microsoft.Extensions.DependencyInjection integration for Masterly.Hash.
It registers one thread-safe PasswordHasher singleton (also exposed as IPasswordHasher), binds its options
from IConfiguration, validates them at startup, and gives you a fluent builder for peppers, legacy formats and profiles.
Install
dotnet add package Masterly.Hash.DependencyInjection
Targets net8.0. Depends on the 8.0.x Microsoft.Extensions.* abstractions, so it works on .NET 8 LTS hosts and later.
Quickstart
// Code-only
builder.Services.AddMasterlyHash(); // Argon2id 2026a defaults
// From configuration; code steps always win, whatever order they were registered in
builder.Services.AddMasterlyHash(builder.Configuration.GetSection("MasterlyHash"))
.AddLegacyFormat(myLegacyFormat) // verify and upgrade old hashes
.WithPepper(sp => sp.GetRequiredService<MyVaultPepper>()); // or .WithPepper(IPasswordPepper)
// Use it
public sealed class LoginService(IPasswordHasher hasher) { /* hasher.VerifyOrDummyAsync(...) */ }
"MasterlyHash": {
"DefaultProfile": "2026a",
"MaxConcurrency": 8,
"ConcurrencyTimeout": "00:00:10",
"MaxPasswordBytes": 1024,
"ComputeRehashOnVerify": true,
"Pepper": {
"CurrentKeyId": "k2",
"Keys": { "k1": "<base64, 32+ bytes>", "k2": "<base64, 32+ bytes>" }
}
}
DefaultProfile accepts the built-in ids 2026a (Argon2id 64 MiB), 2026c (Argon2id 19 MiB) and 2026f
(PBKDF2-SHA512). Custom profiles are code-only: .UseProfile(HashProfile.Argon2id(...)), and .AddProfile(old) keeps
older custom profiles verifiable. Every setting is optional; absent or empty values keep the library defaults.
Unknown or misspelled keys under the section (e.g. Peper) are startup errors, so a typo cannot silently drop the pepper.
ConcurrencyTimeout must be positive and at most 24.20:31:23.647, or -00:00:00.001 (infinite).
Builder methods: Configure, Configure<TDep>, WithPepper (instance or factory), AddLegacyFormat (instance or factory),
UseProfile, AddProfile. Satellite packages add their own extension methods on MasterlyHashBuilder.
AddMasterlyHash throws if IPasswordHasher or PasswordHasher is already registered by something else, because
that registration would ignore every option. To decorate the hasher, register your IPasswordHasher after AddMasterlyHash
and resolve PasswordHasher inside it.
Validation
- Unknown profile ids, out-of-range limits, malformed or short pepper keys, and a
CurrentKeyIdmissing fromKeysfail withOptionsValidationException, listing every problem at once. - With Microsoft.Extensions.Hosting 8.0+ the options are validated when the host starts (
ValidateOnStart). On other hosts, callserviceProvider.ValidateMasterlyHash()after building the provider to fail fast. - The hasher is built once, on first resolution. Configuration reloads do not affect an already-built hasher.
Metrics
The hasher publishes System.Diagnostics.Metrics under MasterlyHashBuilder.MeterName ("Masterly.Hash"):
builder.Services.AddOpenTelemetry()
.WithMetrics(m => m.AddMeter(MasterlyHashBuilder.MeterName));
Security notes
- Keep pepper keys in a secret store (Key Vault, user secrets, environment), never in
appsettings.jsonin source control and never in the same database as the hashes. Generate keys withHmacPepper.GenerateKey(). - Validation messages name keys by id only; key text and key bytes are never included. Decoded key buffers are zeroed after use.
- To rotate, add the new key, point
CurrentKeyIdat it, and keep the old key until every hash made with it has been rehashed on login. Removing a key makes those hashes fail withUnknownPepperKey. - Configuration keys are case-insensitive, so pepper key ids that differ only by case cannot both be configured.
- Binding uses the reflection-based configuration binder; this package is not marked trimming/AOT-compatible.
For Native AOT, configure options in code with
AddMasterlyHash(o => ...).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Masterly.Hash (>= 2.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Masterly.Hash.DependencyInjection:
| Package | Downloads |
|---|---|
|
Masterly.Hash.AspNetCore
ASP.NET Core integration for Masterly.Hash: an ASP.NET Core Identity IPasswordHasher<TUser> adapter that keeps verifying existing Identity v2/v3 hashes and upgrades them to Argon2id on login, an IExceptionHandler that maps PasswordHasherBusyException to HTTP 503 with Retry-After, and a minimal API endpoint filter that rejects over-long passwords before hashing. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 75 | 11/3/2026 |