Argon2 0.1.2-preview
dotnet add package Argon2 --version 0.1.2-preview
NuGet\Install-Package Argon2 -Version 0.1.2-preview
<PackageReference Include="Argon2" Version="0.1.2-preview" />
<PackageVersion Include="Argon2" Version="0.1.2-preview" />
<PackageReference Include="Argon2" />
paket add Argon2 --version 0.1.2-preview
#r "nuget: Argon2, 0.1.2-preview"
#:package Argon2@0.1.2-preview
#addin nuget:?package=Argon2&version=0.1.2-preview&prerelease
#tool nuget:?package=Argon2&version=0.1.2-preview&prerelease
Argon2
A from-scratch C# implementation of the Argon2 password-hashing function (RFC 9106, version 1.3). All three variants are supported: Argon2d, Argon2i, and Argon2id.
Overview
Argon2 is the winner of the 2015 Password Hashing Competition and is the recommended password hashing scheme by OWASP. This library implements Argon2 directly from RFC 9106 without wrapping a native binary.
- Managed C# only. No P/Invoke, no unmanaged DLLs.
- Targets
net10.0. - Cross-validated against Konscious, Isopoh, and RustCrypto.
- PHC-string output compatible with other Argon2 implementations.
Status
Pre-release (0.1.0-preview). The implementation is a port of the
audited RustCrypto argon2 crate. It passes the RFC 9106 §5 test
vectors and more than 450 cross-validation samples drawn from three
independent Argon2 libraries (Konscious, Isopoh, RustCrypto). See
SECURITY.md and the Security Disclaimers section below.
Installation
dotnet add package Authaz.Argon2 --prerelease
All public types live in the flat Authaz.Argon2 namespace; a single
using Authaz.Argon2; brings the whole API into scope.
Quick Start
PHC string (recommended for password storage)
Argon2Phc picks OWASP-recommended parameters (Argon2id, m=64 MiB, t=3,
p=4, 32-byte tag) and generates a fresh 16-byte salt via
RandomNumberGenerator. The returned string is in PHC format and
contains everything Verify needs.
using Authaz.Argon2;
string phc = Argon2Phc.HashToString("hunter2"u8);
// phc looks like: "$argon2id$v=19$m=65536,t=3,p=4$<salt>$<hash>"
bool ok = Argon2Phc.Verify("hunter2"u8, phc);
Verify uses CryptographicOperations.FixedTimeEquals for the final
tag comparison.
Raw bytes (custom parameters / custom salt)
For direct control over parameters, salt, and output length, use
Argon2Context directly:
using Authaz.Argon2;
var parameters = new Argon2Parameters(
memoryCost: 65536, // 64 MiB (in KiB)
timeCost: 3,
parallelism: 4,
outputLength: 32);
var ctx = new Argon2Context(Argon2Variant.Argon2id, parameters);
Span<byte> hash = stackalloc byte[32];
ctx.HashPasswordInto("hunter2"u8, "sixteen_byte_sal"u8, hash);
A secret key (sometimes called a "pepper") and associated data can also be supplied:
byte[] pepper = Convert.FromHexString("aabbccddeeff11223344556677889900");
byte[] ad = "tenant-a"u8.ToArray();
var parameters = new Argon2Parameters(
memoryCost: 65536, timeCost: 3, parallelism: 4, outputLength: 32,
associatedData: ad);
var ctx = new Argon2Context(Argon2Variant.Argon2id, parameters, secret: pepper);
API Reference
All public types live in the Authaz.Argon2 namespace. A single
using Authaz.Argon2; brings the whole API into scope.
Core types
Argon2Variant—Argon2d,Argon2i,Argon2id.Argon2Version—V1_3(0x13).V1_0is defined but rejected byArgon2Context.Argon2Parameters(uint memoryCost, uint timeCost, uint parallelism, uint outputLength, ReadOnlyMemory<byte> associatedData = default)— validates thatp >= 1,m >= 8*p,t >= 1, andtau >= 4. Exposes derived quantitiesActualMemoryBlocks,LaneLength, andSegmentLength.Argon2Context(Argon2Variant, Argon2Parameters, ReadOnlyMemory<byte> secret = default, Argon2Version version = V1_3)— throwsNotSupportedExceptionfor anything other than version 1.3.Argon2Context.HashPasswordInto(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, Span<byte> output)— writes exactlyParameters.OutputLengthbytes. Salt must be at least 8 bytes (RFC 9106 §3.1).
PHC helpers
Argon2Phc.HashToString(ReadOnlySpan<byte> password)— uses OWASP defaults and a CSPRNG-generated salt.Argon2Phc.HashToString(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, Argon2Variant variant, Argon2Parameters parameters)— explicit form.Argon2Phc.Verify(ReadOnlySpan<byte> password, string phcString)— usesCryptographicOperations.FixedTimeEqualsfor the tag comparison. See Security Disclaimers for caveats.
Security Disclaimers
This library is a port of the audited RustCrypto argon2 crate,
cross-validated against three independent implementations, but the
C# port itself has not been independently audited. Please read these
caveats carefully before using it for anything that matters.
- Port, not an independent audit. The algorithm is a direct port of a reviewed implementation, and the output is byte-equal against Konscious, Isopoh, and RustCrypto across 450+ samples. That is strong correctness evidence — not a substitute for a professional review of the C# source and JIT-emitted code.
- Constant-time best-effort only. We avoid obvious branches on secret data, but this implementation has not been audited for timing side-channels in the JIT's emitted code. RyuJIT may introduce data-dependent branches or variable-latency instructions that a pure-source review would not catch.
- Memory zeroization is partial. We explicitly zero sensitive
buffers (initial hash
H0, intermediate tag buffers, and the memory matrix) usingCryptographicOperations.ZeroMemory. However, the .NET GC can move managed arrays during compaction; copies left in old heap regions are not cleared. Threat models that require strict memory hygiene should not rely on C# for this. - No FIPS-140 claims. This library is not FIPS-validated.
- Version 1.3 only. Argon2 v1.0 is intentionally rejected with
NotSupportedException; do not use it anyway.
If you find a security issue, see SECURITY.md for how to report it.
Testing
The solution ships with two test projects:
dotnet test Argon2.sln
To collect merged coverage for the production assembly only
(src/Authaz.Argon2), use the checked-in Coverlet settings and the local
reportgenerator tool manifest:
dotnet tool restore
dotnet test Argon2.sln --settings coverage.runsettings --collect:"XPlat Code Coverage" --results-directory artifacts/coverage/raw
dotnet tool run reportgenerator "-reports:artifacts/coverage/raw/**/coverage.cobertura.xml" "-targetdir:artifacts/coverage/report" "-reporttypes:HtmlSummary;TextSummary"
cat artifacts/coverage/report/Summary.txt
coverage.runsettings limits collection to the Authaz.Argon2
production assembly so the final percentages are not diluted by test
code or generated test-host code.
Authaz.Argon2.Tests— RFC 9106 §5.1/5.2/5.3 vectors, unit tests for BLAKE2b, H', indexing, Argon2i address generator, and fill, plus PHC string parse/format, PHC base64, and FsCheck property tests (determinism, avalanche, output length, variant distinctness, PHC round-trip).Authaz.Argon2.CrossValidation.Tests— parity runs against Konscious (100 samples × 3 variants, variable tag length, secret, AD), Isopoh (50 samples × 3 variants + PHC-string round-trip), and 12 RustCrypto-extracted vectors.
171 tests total.
License
MIT. See LICENSE.
Acknowledgements
- RFC 9106, Biryukov, Dinu, Khovratovich, and Josefsson.
- The Konscious, Isopoh, and RustCrypto maintainers, whose implementations were used as oracles for cross-validation.
- The PHC-format specification maintained at P-H-C/phc-string-format.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.2-preview | 131 | 4/17/2026 |