43 lines
1.7 KiB
C#
43 lines
1.7 KiB
C#
using System.Text;
|
|||
|
|
using System.Text.Json;
|
||
|
|
using VoiceCat.Crypto;
|
||
|
|
|
||
|
|
namespace VoiceCat.Tests;
|
||
|
|
|
||
|
|
public sealed class PasswordTests
|
||
|
|
{
|
||
|
|
[Fact]
|
||
|
|
public void VerifiesLibsodiumHashesWithoutPasswordNormalization()
|
||
|
|
{
|
||
|
|
var hasher = new PasswordHasher();
|
||
|
|
using var fixture = JsonDocument.Parse(File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "Fixtures", "cpp-passwords.json")));
|
||
|
|
foreach (var item in fixture.RootElement.GetProperty("hashes").EnumerateArray())
|
||
|
|
{
|
||
|
|
string encodedPassword = item.GetProperty("passwordBase64").GetString()!;
|
||
|
|
string password = Encoding.UTF8.GetString(Convert.FromBase64String(encodedPassword.PadRight((encodedPassword.Length + 3) / 4 * 4, '=')));
|
||
|
|
string hash = item.GetProperty("hash").GetString()!;
|
||
|
|
Assert.True(hasher.Verify(password, hash));
|
||
|
|
Assert.False(hasher.Verify(password + "!", hash));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void FreshHashesUseRandomSaltAndNativePhcFormat()
|
||
|
|
{
|
||
|
|
var hasher = new PasswordHasher();
|
||
|
|
string first = hasher.Hash("hello");
|
||
|
|
string second = hasher.Hash("hello");
|
||
|
|
Assert.NotEqual(first, second);
|
||
|
|
Assert.StartsWith("$argon2id$v=19$m=65536,t=2,p=1$", first);
|
||
|
|
Assert.True(hasher.Verify("hello", first));
|
||
|
|
Assert.False(hasher.Verify("wrong", first));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Theory]
|
||
|
|
[InlineData("$argon2id$v=19$m=999999999,t=2,p=1$c2FsdA$aGFzaA")]
|
||
|
|
[InlineData("$argon2id$v=19$m=65536,t=99999,p=1$c2FsdA$aGFzaA")]
|
||
|
|
[InlineData("$argon2id$v=16$m=65536,t=2,p=1$c2FsdA$aGFzaA")]
|
||
|
|
[InlineData("$argon2id$v=19$m=65536,t=2,p=1$!!!$!!!")]
|
||
|
|
public void MalformedOrExcessiveHashesFailClosed(string hash) => Assert.False(new PasswordHasher().Verify("hello", hash));
|
||
|
|
}
|