Isopoh.Cryptography.Argon2 2.0.0

dotnet add package Isopoh.Cryptography.Argon2 --version 2.0.0
NuGet\Install-Package Isopoh.Cryptography.Argon2 -Version 2.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Isopoh.Cryptography.Argon2 --version 2.0.0
#r "nuget: Isopoh.Cryptography.Argon2, 2.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Isopoh.Cryptography.Argon2 as a Cake Addin
#addin nuget:?package=Isopoh.Cryptography.Argon2&version=2.0.0

// Install Isopoh.Cryptography.Argon2 as a Cake Tool
#tool nuget:?package=Isopoh.Cryptography.Argon2&version=2.0.0




Argon2 is a hash generator optimized to produce hashes suitable for credential storage, key derivation, or other situations requiring a cryptographically secure password hash. Argon2 was the winner of the 2015 Password Hashing Competition.

This fully managed implementation of Argon2 runs in .NET Core, .NET Framework, or WebAssembly (via Blazor or Uno Platform).

Standard Argon2 Hashing:

var password = "password1";
var passwordHash = Argon2.Hash(password);

Argon2 Verification:

if (Argon2.Verify(passwordHash, password))
    // do stuff

All Argon2 options available for your hashing needs...


The Argon2 reference implementation is available from and, indeed, the C# code in this repository was based upon that implementation but that implementation is in C. Building a C# wrapper around the C implementation is possible but adds complexity.

This 100% managed-code library allows you to use the Argon2 hash in any .NET (including Blazor) application without added complexity.


This requires a .NET environment and runs on Windows, Linux, MacOS, and WebAssembly (via Blazor).



The recommended way to get started is by use the NuGet package:

Install-Package Isopoh.Cryptography.Argon2


This project uses SourceLink so you should be able to step into the source code for debugging even when just adding the NuGet package as a dependency.


You can also, of course, go old-school and clone the repository and link use the .csproj files directly:

git clone

then add the ProjectReference lines to your .csproj to reference ...Isopoh.Cryptography.SecureArray\Isopoh.Cryptography.SecureArray.csproj, ...Isopoh.Cryptography.Blake2b\Isopoh.Cryptography.Blake2b.csproj, and ...Isopoh.Cryptography.Argon2\Isopoh.Cryptography.Argon2.csproj. For example:

    <ProjectReference Include="..\..\..\Isopoh.Cryptography.Argon2\Isopoh.Cryptography.SecureArray\Isopoh.Cryptography.SecureArray.csproj" />


Using the defaults:

var password = "password1";
var passwordHash = Argon2.Hash(password);
if (Argon2.Verify(passwordHash, password))
    // do stuff

Setting everything:

var password = "password1";
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] salt = new byte[16];

// somewhere in the class definition:
//   private static readonly RandomNumberGenerator Rng =
//       System.Security.Cryptography.RandomNumberGenerator.Create();

var config = new Argon2Config
    Type = Argon2Type.DataIndependentAddressing,
    Version = Argon2Version.Nineteen,
    TimeCost = 10,
    MemoryCost = 32768,
    Lanes = 5,
    Threads = Environment.ProcessorCount, // higher than "Lanes" doesn't help (or hurt)
    Password = passwordBytes,
    Salt = salt, // >= 8 bytes if not null
    Secret = secret, // from somewhere
    AssociatedData = associatedData, // from somewhere
    HashLength = 20 // >= 4
var argon2A = new Argon2(config);
string hashString;
using(SecureArray<byte> hashA = argon2A.Hash())
    hashString = config.EncodeString(hashA.Buffer);

// Now pretend "passwordBytes" is what just came in and that it must be
// verified against the known "hashString".
// Note setting "Threads" to different values doesn't effect the result,
// just the time it takes to get the result.
var configOfPasswordToVerify = new Argon2Config { Password = passwordBytes, Threads = 1 };
SecureArray<byte> hashB = null;
    if (configOfPasswordToVerify.DecodeString(hashString, out hashB) && hashB != null)
        var argon2ToVerify = new Argon2(configOfPasswordToVerify);
        using(var hashToVerify = argon2ToVerify.Hash())
            if (Argon2.FixedTimeEquals(hashB, hashToVerify))
                // verified

// Or, more simply (setting "Threads" to "5")
if (Argon2.Verify(hashString, passwordBytes, 5))
    // verified


The full API is at

In particular, the various options for Argon2 hashing can be found in Argon2Config and used with Argon2.Hash(). There are other Argon2.Hash() convenience calls available there as well.

If you are only interested in Blake2b, the underlying hash used in Argon2, you can go to the Blake2b.ComputeHash() calls.

Also, there is SecureArray<T>. The SecureArray takes a SecureArrayCall which is a class that has three Func<> properties, one to LockMemory, one to UnlockMemory, and one to ZeroMemory. You can easily create your own SecureArrayCall to lock/unlock/zero or perhaps to log secure memory actions.

JUST WHAT IS THIS "SecureArray"?

You can think of the SecureArray sort of like you would think of SecureString except that SecureString does crypto (usually - encryption isn't supported everywhere) to protect its sensitive data and has windows of vulnerability when it decrypts the string for use. SecureArray protects its data by locking the data into RAM to keep it from swapping to disk and also zeroing the buffer when disposed. So, unlike SecureString, any process with access to your process's memory will be able to read the data in your SecureArray, but you do not have to worry about your data persisting anywhere or multiple copies of your data floating around RAM due to C#'s memory management.

Because it locks the memory into RAM (and at a non-movable-by-the-garbage-collector location), you need to use it as infrequently as possible and for as short a time as possible. RAM secured this way puts stress on the computer as a whole by denying physical RAM for other processes and puts stress on your particular executable by denying freedom to the garbage collector to reduce fragmentation as needed for best performance.

Note: when using SecureArray in the browser (for example, under Blazor or UnoPlatform), the memory cannot be locked into RAM so SecureArray does its best effort to protect the data by zeroing the buffer when it is disposed.

Note similarly: when using SecureArray in a Universal Windows Platform (UWP) application, I have yet to figure out how to use the supposedly available VirtualAllocFromApp() system call to lock memory into RAM so SecureArray does its best effort to protect the data by zeroing the buffer when it is disposed.

Always dispose of your SecureArrays.


Argon2 uses Blake2b as a cryptographic building block. This code uses the C# implementation of Blake2 modified from The main modification is that the Blake2 here uses SecureArray<T>. The SecureArray takes a SecureArrayCall to protect potentially sensitive data. Most other modifications are strictly cosmetic.

As part of this Blake2b port, an effort was made to speed Blake2b by using techniques like unrolling and using raw buffers in unsafe code. It turns out the CLR optimizes plain code better than unrolled/unsafe code and the original always ran faster. At some point I may try a port to System.Numerics.Vector<T>...


The API Documentation at gets generated automatically upon build. This happens via a dummy C# "Doc" project that uses the DocFx NuGet package to produce the API documentation.


Michael Heyman


List of people and project that inspired creation of this one:

  • The many contributers of the Argon2 repository
  • and the cryptographers responsible for creating and testing that algorithm
  • @CodesInChaos for the fully managed Blake2b implementation here
  • @PurpleBooth for his readme template posted here


<a rel="license" href=""><img alt="Creative Commons License" style="border-width:0" src="" /></a><br /><span xmlns:dct="" property="dct:title">Isopoh.Cryptography.Argon2</span> by <a xmlns:cc="" href="" property="cc:attributionName" rel="cc:attributionURL">Michael Heyman</a> is licensed under a <a rel="license" href="">Creative Commons Attribution 4.0 International License</a>.


You should be aware that this project is supported solely by me and provided as is.

Go back to the project description

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (21)

Showing the top 5 NuGet packages that depend on Isopoh.Cryptography.Argon2:

Package Downloads

Peachpie PHP language library functions.


Library for performing SFTP (FTP over SSH). Features include Automatic Reconnect & Resume, Proxy Support, Public & Private Keys, ZLIB Compression, Directory Synchronization, SCP, Shell, Port Forwarding (Tunneling), FIPS Compliant Mode, and more.

FluffySpoon.Security.Hashing The ID prefix of this package has been reserved for one of the owners of this package by

Provides mechanisms for hashing.


A free library for ASP.NET Core 6+ Microservices development, with Model, Model Repository, Entity Framework Core and common Web Api features like CORS, Json serialization fixes, Swagger generation, JWT Authentication for simple and objective microservices development


This is a very early stage release of the vlingo platform. The vlingo-net-common project consists of some tools that are used across various other vlingo-net projects.

GitHub repositories (3)

Showing the top 3 popular GitHub repositories that depend on Isopoh.Cryptography.Argon2:

Repository Stars
PeachPie - the PHP compiler and runtime for .NET and .NET Core
Core behind AniAPI HTTP Rest APIs.
Raise your baseline in security by using this as your template instead of default Mvc project. Keep your app secure by continuously applying Security rules
Version Downloads Last updated
2.0.0 117,331 8/17/2023
1.1.12 335,138 5/22/2022
1.1.11 60,362 12/12/2021
1.1.10 458,299 11/18/2020
1.1.9 19,476 10/2/2020
1.1.8 50,788 7/26/2020
1.1.7 597 7/26/2020
1.1.6 570 7/25/2020
1.1.5 588 7/25/2020
1.1.4 5,180 7/5/2020
1.1.3 91,658 10/27/2019
1.1.2 112,174 5/14/2019
1.1.1 2,226 2/16/2019
1.1.0 721 2/16/2019
1.0.10 1,304 2/10/2019
1.0.9 685 2/10/2019
1.0.8 86,382 3/11/2018
1.0.7 1,012 3/11/2018
1.0.6 11,881 1/13/2018
1.0.5 1,175 10/29/2017
1.0.4 1,029 9/23/2017
1.0.3 963 9/10/2017
1.0.2 1,080 8/31/2017
1.0.1 1,545 3/8/2017
1.0.0 2,356 7/31/2016

Hash string no longer has $data field. Proper hash on >64-byte but not multiple of 64-byte.