From 5ceb654eb826ecf56e25a1e8cd700dca559efca4 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 11 Oct 2024 21:01:32 -0700 Subject: [PATCH] #22 testing benchmark password hashers --- .../PasswordHasherBenchmarks.cs | 62 +++++++++++++++++++ cas-dotnet-benchmarks/Program.cs | 4 ++ cas-dotnet-benchmarks/Util.cs | 26 ++++++++ .../cas-dotnet-benchmarks.csproj | 19 ++++++ cas-dotnet-sdk.sln | 6 ++ 5 files changed, 117 insertions(+) create mode 100644 cas-dotnet-benchmarks/PasswordHasherBenchmarks.cs create mode 100644 cas-dotnet-benchmarks/Program.cs create mode 100644 cas-dotnet-benchmarks/Util.cs create mode 100644 cas-dotnet-benchmarks/cas-dotnet-benchmarks.csproj diff --git a/cas-dotnet-benchmarks/PasswordHasherBenchmarks.cs b/cas-dotnet-benchmarks/PasswordHasherBenchmarks.cs new file mode 100644 index 0000000..fc54f12 --- /dev/null +++ b/cas-dotnet-benchmarks/PasswordHasherBenchmarks.cs @@ -0,0 +1,62 @@ +using BenchmarkDotNet.Attributes; +using CasDotnetSdk.PasswordHashers; + +namespace cas_dotnet_benchmarks +{ + public class PasswordHasherBenchmarks + { + private string _password { get; set; } + private string _argon2Hash { get; set; } + private string _bcryptHash { get; set; } + private string _scryptHash { get; set; } + private Argon2Wrapper _argon2 { get; set; } + private BcryptWrapper _bcrypt { get; set; } + private SCryptWrapper _scrypt { get; set; } + public PasswordHasherBenchmarks() + { + this._password = Util.GeneratePassword(15); + this._argon2 = new Argon2Wrapper(); + this._scrypt = new SCryptWrapper(); + this._bcrypt = new BcryptWrapper(); + this._argon2Hash = this._argon2.HashPassword(this._password); + this._bcryptHash = this._bcrypt.HashPassword(this._password); + this._scryptHash = this._scrypt.HashPassword(this._password); + } + + [Benchmark] + public string Argon2Hash() + { + return this._argon2.HashPassword(this._password); + } + + [Benchmark] + public bool Argon2Verify() + { + return this._argon2.Verify(this._argon2Hash, this._password); + } + + [Benchmark] + public string BCryptHash() + { + return this._bcrypt.HashPassword(this._password); + } + + [Benchmark] + public bool BCryptVerify() + { + return this._bcrypt.Verify(this._bcryptHash, this._password); + } + + [Benchmark] + public string SCryptHash() + { + return this._bcrypt.HashPassword(this._password); + } + + [Benchmark] + public bool SCryptVerify() + { + return this._scrypt.Verify(this._scryptHash, this._password); + } + } +} diff --git a/cas-dotnet-benchmarks/Program.cs b/cas-dotnet-benchmarks/Program.cs new file mode 100644 index 0000000..dbd12fe --- /dev/null +++ b/cas-dotnet-benchmarks/Program.cs @@ -0,0 +1,4 @@ +using BenchmarkDotNet.Running; +using cas_dotnet_benchmarks; + +var summary = BenchmarkRunner.Run(); \ No newline at end of file diff --git a/cas-dotnet-benchmarks/Util.cs b/cas-dotnet-benchmarks/Util.cs new file mode 100644 index 0000000..21a0a74 --- /dev/null +++ b/cas-dotnet-benchmarks/Util.cs @@ -0,0 +1,26 @@ +using System.Security.Cryptography; + +namespace cas_dotnet_benchmarks +{ + public static class Util + { + public static string GeneratePassword(int length) + { + const string validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()"; + char[] passwordChars = new char[length]; + + using (var rng = RandomNumberGenerator.Create()) + { + byte[] randomBytes = new byte[length]; + rng.GetBytes(randomBytes); + + for (int i = 0; i < length; i++) + { + passwordChars[i] = validChars[randomBytes[i] % validChars.Length]; + } + } + + return new string(passwordChars); + } + } +} diff --git a/cas-dotnet-benchmarks/cas-dotnet-benchmarks.csproj b/cas-dotnet-benchmarks/cas-dotnet-benchmarks.csproj new file mode 100644 index 0000000..1311d77 --- /dev/null +++ b/cas-dotnet-benchmarks/cas-dotnet-benchmarks.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + cas_dotnet_benchmarks + enable + enable + + + + + + + + + + + diff --git a/cas-dotnet-sdk.sln b/cas-dotnet-sdk.sln index be99c74..4f3d534 100644 --- a/cas-dotnet-sdk.sln +++ b/cas-dotnet-sdk.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cas-dotnet-sdk", "cas-dotne EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cas-dotnet-sdk-tests", "cas-dotnet-sdk-tests\cas-dotnet-sdk-tests.csproj", "{4904E91B-5A0D-41E9-92CA-0E1BCE987FAE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cas-dotnet-benchmarks", "cas-dotnet-benchmarks\cas-dotnet-benchmarks.csproj", "{E6C12EB3-ABBD-4014-8091-BEFAE84D77C5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {4904E91B-5A0D-41E9-92CA-0E1BCE987FAE}.Debug|Any CPU.Build.0 = Debug|Any CPU {4904E91B-5A0D-41E9-92CA-0E1BCE987FAE}.Release|Any CPU.ActiveCfg = Release|Any CPU {4904E91B-5A0D-41E9-92CA-0E1BCE987FAE}.Release|Any CPU.Build.0 = Release|Any CPU + {E6C12EB3-ABBD-4014-8091-BEFAE84D77C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6C12EB3-ABBD-4014-8091-BEFAE84D77C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6C12EB3-ABBD-4014-8091-BEFAE84D77C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6C12EB3-ABBD-4014-8091-BEFAE84D77C5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE