C# Isopoh Argon2 Implementation hash does not verify



Summary

  • trying to implement password hashing using Argon2 in C#
  • I have already tried searching, and can’t find this specific issue. Nor does there seem to be a lot of good (easy for me to interpret?) examples for C# Argon2 (please let me know if there is a better way than Isopoh)
  • Using a C# implementation (Isopoh.Cryptography.Argon2) as recommended here
  • I can generate hashes with no issues, passing through various arguments for the Argon2Config
  • I can verify hashes with no issues ONLY IF the hash length is = 32. Anything seems to fail
  • However, I can verify ALL hashes online

This is my first post here so do let me know if I should make any amendments accordingly.

Thanks in advance for any help in resolving this!

Background

I’m testing out different ways of storing encrypted data. I already have a way to encrypt/decrypt data, But I am now looking at ways to implement proper password hashing (and to also use this hashed password as the key for the encryption of the other data – but I will raise this in another thread once I get to that point).

I am developing using VS2019 in a Windows 10 x64 environment. Whilst I’m not new to programming, I am learning C# (from VB.NET), and I’m certainly no expert in Cryptography.

I’m using an implementation of Argon2 that I found recommended in this post to learn how to securely store/hash passwords.

Issue

I can get the hashing process to work (whilst customising the configuration). However, when it comes to verifying the hash, I cannot verify the hash if I use any other hash length apart from 32 – I can play around with the other config settings and it works, but not the hash length.

BUT, where it gets really weird, when I generate a hash that uses a hash length not equal to 32, I verify it using this site, and I get a successful verification

Code

  • I’ve installed the Isopoh.Cryptography packages in the project via NuGet (using v1.1.4)

Namespace:

using System.Security.Cryptography; using Isopoh.Cryptography.Argon2; using Isopoh.Cryptography.SecureArray; 

Variable:

private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create(); 

Hashing code:

        string str_ConsoleText;          txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("[START NEW HASH]");         txtConsole.AppendText(Environment.NewLine);         str_ConsoleText = "Starting encryption process";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);          var stopwatch = Stopwatch.StartNew();          //var password = "password1";         var password = txtPasword.Text;         byte[] passwordBytes = Encoding.UTF8.GetBytes(password);         byte[] salt = new byte[16];                              Rng.GetBytes(salt);          txtSalt.Text = salt.ToString();          var config = new Argon2Config         {             Type = Argon2Type.HybridAddressing,             Version = Argon2Version.Nineteen,             TimeCost = Int32.Parse(txtIterations.Text),             MemoryCost = Int32.Parse(txtMemory.Text) * 1024,             Lanes = Int32.Parse(txtParallelism.Text),             Threads = Int32.Parse(txtThreads.Text),             Password = passwordBytes,             Salt = salt, // >= 8 bytes if not null             //Secret = secret, // from somewhere             //AssociatedData = associatedData, // from somewhere             HashLength = Int32.Parse(txtHashLength.Text) //20 // >= 4         };         var argon2A = new Isopoh.Cryptography.Argon2.Argon2(config);         string hashString;         using (SecureArray<byte> hashA = argon2A.Hash())         {             hashString = config.EncodeString(hashA.Buffer);         }          txtHashResult.Text = hashString;          stopwatch.Stop();          str_ConsoleText = "Encoded hash is: ";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(hashString);         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Details are:");         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Time cost: " + config.TimeCost.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Memory cost: " + config.MemoryCost.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Lanes: " + config.Lanes.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Threads: " + config.Threads.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Salt: " + config.Salt.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("Hash length: " + config.HashLength.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(Environment.NewLine);                  str_ConsoleText = $  "Encryption process took { stopwatch.ElapsedMilliseconds / 1024.0 } s";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("[END HASH]"); 

Verifying code:

        var stopwatch = Stopwatch.StartNew();          string str_ConsoleText;          var password = txtPasword.Text;         var passwordHash = txtHashResult.Text;          txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("[START VERIFY HASH]");         txtConsole.AppendText(Environment.NewLine);         str_ConsoleText = "Starting verification process";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);          txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(Environment.NewLine);         str_ConsoleText = "[Hash to verify]: ";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(passwordHash.ToString());         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(Environment.NewLine);           if (Isopoh.Cryptography.Argon2.Argon2.Verify(passwordHash, password))         {             // do stuff             str_ConsoleText = "!!!!!!!!!!HASH VERIFICATION SUCCESS!!!!!!!!!!";             txtConsole.AppendText(str_ConsoleText);         }         else         {             str_ConsoleText = "******HASH VERIFICATION FAILED******";             txtConsole.AppendText(str_ConsoleText);         }           stopwatch.Stop();         txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText(Environment.NewLine);         str_ConsoleText = $  "Verification process took { stopwatch.ElapsedMilliseconds / 1024.0 } s";         txtConsole.AppendText(str_ConsoleText);         txtConsole.AppendText(Environment.NewLine);                                 txtConsole.AppendText(Environment.NewLine);         txtConsole.AppendText("[END VERIFY HASH]"); 

Outputs/Results

Password = Hello World!

Hash length = 32:

[START NEW HASH] Starting encryption process Encoded hash is:  $  argon2id$  v=19$  m=32768,t=4,p=8$  bPsTGKZu/reihfAlLEVlCA$  o79dNC9/toz7CbbFhhkSy4/E2a5pRETd7h+79R7V7iU Details are: Time cost: 4 Memory cost: 32768 Lanes: 8 Threads: 4 Salt: System.Byte[] Hash length: 32  Encryption process took 2.130859375 s [END HASH]  [START VERIFY HASH] Starting verification process      [Hash to verify]:  $  argon2id$  v=19$  m=32768,t=4,p=8$  bPsTGKZu/reihfAlLEVlCA$  o79dNC9/toz7CbbFhhkSy4/E2a5pRETd7h+79R7V7iU  !!!!!!!!!!HASH VERIFICATION SUCCESS!!!!!!!!!!  Verification process took 1.3115234375 s  [END VERIFY HASH] 

Argon2.online hash verification:

enter image description here

Hash length = 64:

[START NEW HASH] Starting encryption process Encoded hash is:  $  argon2id$  v=19$  m=32768,t=4,p=8$  h/zEPuZWQsBSAPhZn23gRQ$  6FZzr5DhOMemPTzZ5WY+4MgsxKsxYLNuRbiKo8og+FoYOJFfBsfdCtr1Zs8z6lXVX+E7FUYsGaLA2ZESH6aE0w Details are: Time cost: 4 Memory cost: 32768 Lanes: 8 Threads: 4 Salt: System.Byte[] Hash length: 64  Encryption process took 2.0400390625 s [END HASH]  [START VERIFY HASH] Starting verification process   [Hash to verify]:  $  argon2id$  v=19$  m=32768,t=4,p=8$  h/zEPuZWQsBSAPhZn23gRQ$  6FZzr5DhOMemPTzZ5WY+4MgsxKsxYLNuRbiKo8og+FoYOJFfBsfdCtr1Zs8z6lXVX+E7FUYsGaLA2ZESH6aE0w  ******HASH VERIFICATION FAILED******  Verification process took 1.3076171875 s  [END VERIFY HASH] 

Argon2.online hash verification: enter image description here