Argon2.NetCore is a .NET implementation of the Argon2 password/key derivation function (PHC winner) by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich. This package is optimized to work with PinnedMemory so sensitive material can stay in pinned buffers for better memory-handling control.
dotnet add package Argon2.NetCoreInstall-Package Argon2.NetCoreNuGet package page: https://www.nuget.org/packages/Argon2.NetCore/
using System;
using System.Security.Cryptography;
using Argon2.NetCore;
using PinnedMemory;
var salt = new byte[16];
var secret = new byte[32];
RandomNumberGenerator.Fill(salt);
RandomNumberGenerator.Fill(secret);
using var keyPin = new PinnedMemory<byte>(secret, false);
using var argon2 = new Argon2(keyPin, salt)
{
// Argon2i (IndependentAddressing) by default.
// Set DependentAddressing for Argon2d.
Addressing = Argon2.AddressType.IndependentAddressing,
HashLength = 32,
MemoryCost = 65536, // 64 MiB (value is KiB)
TimeCost = 3,
Lanes = 4,
Threads = 2
};
// Optional: include additional context bytes in the hash input.
var message = new byte[] { 0x63, 0x61, 0x77 }; // "caw"
argon2.UpdateBlock(message, 0, message.Length);
using var hash = new PinnedMemory<byte>(new byte[argon2.GetLength()]);
argon2.DoFinal(hash, 0);
Console.WriteLine(Convert.ToHexString(hash.ToArray()));Additional sample code is available in Argon2.NetCore.Examples/Program.cs.
Argon2(PinnedMemory<byte> key, byte[] salt, byte[] associatedData = null)key: secret key / password bytes (required).salt: unique random salt bytes (required, minimum 8 bytes).associatedData: optional associated bytes mixed into derivation.
Set these on the Argon2 instance before calling DoFinal.
AddressingIndependentAddressing(Argon2ibehavior; default)DependentAddressing(Argon2dbehavior)
HashLength(int)- Number of output bytes.
- Minimum value:
4.
MemoryCost(int)- Memory cost in KiB.
- Example:
65536= 64 MiB.
TimeCost(int)- Number of iterations/passes over memory.
Lanes(int)- Number of lanes (parallelism level).
Threads(int)- Number of worker threads used by the implementation.
int GetLength()- Returns currently configured output length.
void Update(byte input)- Appends one byte to the message input.
void UpdateBlock(byte[] input, int inOff, int len)- Appends part of a byte array to the message input.
void UpdateBlock(PinnedMemory<byte> input, int inOff, int len)- Appends a pinned byte buffer to the message input.
void DoFinal(PinnedMemory<byte> output, int outOff)- Computes derived output and writes to the provided pinned output buffer.
void Reset()- Resets internal state for another run while retaining key/salt.
void Dispose()- Clears key/salt state and frees resources.
- Use at least 16 bytes of cryptographically secure randomness.
- Never reuse a salt for different secrets when avoiding correlation matters.
- Start from:
MemoryCost: 64 MiB to 256 MiB (65536to262144KiB)TimeCost:2to4Lanes: number of physical cores (or a smaller operational cap)
- Benchmark in production-like conditions and target a derivation time that balances security and user latency.
IndependentAddressing(default) maps to Argon2i-style memory addressing and is generally safer for password hashing scenarios.- Use
DependentAddressingonly when you specifically need Argon2d-style behavior.
- Keep password/key data in
PinnedMemory<byte>while hashing. - Dispose of
Argon2and pinned buffers promptly to reduce lifetime of sensitive data.
- 32 bytes is a common default for key derivation.
- Use larger output (for example 64 bytes) only when your protocol needs it.
When persisting hashes, store:
- Algorithm identifier (
Argon2variant/addressing mode) MemoryCost,TimeCost,Lanes,HashLength- Salt
- Hash output
This ensures future verification and migration remain possible.
- Very high memory/thread settings can exhaust container/host resources.
- Use load testing to verify worst-case concurrency and avoid denial-of-service through excessive KDF pressure.
DoFinalrequires an output buffer large enough forHashLengthat the given offset.saltmust be at least 8 bytes.- Parameter validation throws exceptions for invalid values (e.g., non-positive costs/lanes/threads).
MIT. See LICENSE.