Skip to content

Commit

Permalink
Argon2id.cs: Provide overloads that accept/return strings
Browse files Browse the repository at this point in the history
  • Loading branch information
ektrah committed Dec 16, 2024
1 parent 174a475 commit a6d77c3
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
28 changes: 23 additions & 5 deletions src/Geralt.Tests/Argon2idTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void NeedsRehash_Invalid(int hashSize, int iterations, int memorySize)

[TestMethod]
[DataRow("correct horse battery staple", Argon2id.MinIterations, Argon2id.MinMemorySize)]
public void ComputeHash_Valid_String(string password, int iterations, int memorySize)
public void ComputeHash_String_Valid(string password, int iterations, int memorySize)
{
Span<byte> p = Encoding.UTF8.GetBytes(password);

Expand All @@ -206,7 +206,7 @@ public void ComputeHash_Valid_String(string password, int iterations, int memory

[TestMethod]
[DynamicData(nameof(StringTestVectors), DynamicDataSourceType.Method)]
public void VerifyHash_Valid_String(bool expected, string hash, string password)
public void VerifyHash_String_Valid(bool expected, string hash, string password)
{
Span<byte> p = Encoding.UTF8.GetBytes(password);

Expand All @@ -218,7 +218,7 @@ public void VerifyHash_Valid_String(bool expected, string hash, string password)
[TestMethod]
[DataRow("$argon2i$v=19$m=4096,t=3,p=1$eXNtbzQwOTFzajAwMDAwMA$Bb7qAql9aguCTBpLP4PVnlBd+ehJ5rX0R7smB/FggOM", "password")]
[DataRow("$argon2d$v=19$m=4096,t=3,p=1$YTBxd2k1bXBhZHIwMDAwMA$3MM5BChSl8q+MQED0fql0nwP5ykjHdBrGE0mVJHFEUE", "password")]
public void VerifyHash_Tampered_String(string hash, string password)
public void VerifyHash_String_Tampered(string hash, string password)
{
var p = Encoding.UTF8.GetBytes(password);

Expand All @@ -235,10 +235,28 @@ public void VerifyHash_Tampered_String(string hash, string password)
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiX", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiXysd3WbTRzmEOw$Nm8QBM+7", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiXysd3WbTRzmEOw$Nm8QBM+7RH1DXo9rvp5cwKEOOOfD2g6JuxlXihoNcp", "")]
public void VerifyHash_Invalid_String(string hash, string password)
public void VerifyHash_String_Invalid(string hash, string password)
{
var p = Encoding.UTF8.GetBytes(password);

Assert.IsFalse(Argon2id.VerifyHash(hash, p));
bool valid = Argon2id.VerifyHash(hash, p);
Assert.IsFalse(valid);
}

[TestMethod]
[DataRow("$argon2id$", "")]
[DataRow("$argon2id$v=1", "")]
[DataRow("$argon2id$v=19", "")]
[DataRow("$argon2id$v=19$", "")]
[DataRow("$argon2id$v=19$m=4882,t=", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiX", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiXysd3WbTRzmEOw$Nm8QBM+7", "")]
[DataRow("$argon2id$v=19$m=4882,t=2,p=1$bA81arsiXysd3WbTRzmEOw$Nm8QBM+7RH1DXo9rvp5cwKEOOOfD2g6JuxlXihoNcp", "")]
public void NeedsRehash_String_Invalid(string hash, string password)
{
var p = Encoding.UTF8.GetBytes(password);

Assert.ThrowsException<FormatException>(() => Argon2id.NeedsRehash(hash, Argon2id.MinIterations, Argon2id.MinMemorySize));
}
}
16 changes: 9 additions & 7 deletions src/Geralt/Crypto/Argon2id.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using System.Runtime.InteropServices;
using System.Text;
using static Interop.Libsodium;

namespace Geralt;
Expand Down Expand Up @@ -40,13 +41,15 @@ public static string ComputeHash(ReadOnlySpan<byte> password, int iterations, in
Validation.NotLessThanMin(nameof(iterations), iterations, MinIterations);
Validation.NotLessThanMin(nameof(memorySize), memorySize, MinMemorySize);
Sodium.Initialize();
unsafe
{
sbyte* hash = stackalloc sbyte[crypto_pwhash_STRBYTES];
nint hash = Marshal.AllocHGlobal(MaxHashSize);
try {
int ret = crypto_pwhash_str_alg(hash, password, (ulong)password.Length, (ulong)iterations, (nuint)memorySize, crypto_pwhash_argon2id_ALG_ARGON2ID13);
if (ret != 0) { throw new InsufficientMemoryException("Insufficient memory to perform password hashing."); }
return new string(hash);
return Marshal.PtrToStringAnsi(hash)!;
}
finally {
Marshal.FreeHGlobal(hash);
}
}

public static bool VerifyHash(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> password)
Expand Down Expand Up @@ -96,8 +99,7 @@ private static void ThrowIfInvalidHashPrefix(ReadOnlySpan<byte> hash)

private static void ThrowIfInvalidHashPrefix(string hash)
{
if (!hash.StartsWith(HashPrefix))
{
if (!hash.StartsWith(HashPrefix)) {
throw new FormatException("Invalid encoded password hash prefix.");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Geralt/Interop/Interop.Argon2id.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal static partial class Libsodium

[LibraryImport(DllName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static unsafe partial int crypto_pwhash_str_alg(sbyte* hash, ReadOnlySpan<byte> password, ulong passwordLength, ulong iterations, nuint memorySize, int algorithm);
internal static partial int crypto_pwhash_str_alg(nint hash, ReadOnlySpan<byte> password, ulong passwordLength, ulong iterations, nuint memorySize, int algorithm);

[LibraryImport(DllName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
Expand Down

0 comments on commit a6d77c3

Please sign in to comment.