remade into 1 project

This commit is contained in:
2026-03-14 18:33:38 -04:00
parent ee37ddf2b8
commit eb927b3038
75 changed files with 2020 additions and 1981 deletions

109
PasswordHasher.cs Normal file
View File

@@ -0,0 +1,109 @@
using System;
using System.Security.Cryptography;
using System.Text;
using Konscious.Security.Cryptography;
namespace PasswordHasher
{
/// <summary>
/// Provides secure password hashing functionality using Argon2id algorithm
/// </summary>
public class PasswordHasher
{
/// <summary>
/// Size of the salt in bytes
/// </summary>
private const int SaltSize = 16;
/// <summary>
/// Size of the hash in bytes
/// </summary>
private const int HashSize = 32;
/// <summary>
/// Number of threads to use for parallel computation
/// </summary>
private const int DegreeOfParallelism = 1;
/// <summary>
/// Number of iterations for the Argon2id algorithm
/// </summary>
private const int Iterations = 2;
/// <summary>
/// Memory size in KB to use
/// </summary>
private const int MemorySize = 19456; // 19 MB
/// <summary>
/// Generates a secure hash of a password using Argon2id with a random salt
/// </summary>
/// <param name="password">The plain text password to hash</param>
/// <returns>A Base64 string containing the combined salt and hash</returns>
/// <exception cref="ArgumentNullException">Thrown when password is null</exception>
public string HashPassword(string password)
{
// Generate a random salt
byte[] salt = new byte[SaltSize];
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
// Create hash
byte[] hash = HashPassword(password, salt);
// Combine salt and hash
var combinedBytes = new byte[salt.Length + hash.Length];
Array.Copy(salt, 0, combinedBytes, 0, salt.Length);
Array.Copy(hash, 0, combinedBytes, salt.Length, hash.Length);
// Convert to base64 for storage
return Convert.ToBase64String(combinedBytes);
}
/// <summary>
/// Generates a password hash using Argon2id with a specific salt
/// </summary>
/// <param name="password">The plain text password</param>
/// <param name="salt">The salt to use for hashing</param>
/// <returns>A byte array containing the password hash</returns>
private byte[] HashPassword(string password, byte[] salt)
{
var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password))
{
Salt = salt,
DegreeOfParallelism = DegreeOfParallelism,
Iterations = Iterations,
MemorySize = MemorySize
};
return argon2.GetBytes(HashSize);
}
/// <summary>
/// Verifies if a password matches a stored hash
/// </summary>
/// <param name="password">The plain text password to verify</param>
/// <param name="hashedPassword">The stored hash in Base64 format</param>
/// <returns>True if the password matches the hash, false otherwise</returns>
/// <exception cref="ArgumentNullException">Thrown when password or hashedPassword are null</exception>
/// <exception cref="FormatException">Thrown when hashedPassword is not in valid Base64 format</exception>
public bool VerifyPassword(string password, string hashedPassword)
{
// Decode the stored hash
byte[] combinedBytes = Convert.FromBase64String(hashedPassword);
// Extract salt and hash
byte[] salt = new byte[SaltSize];
byte[] hash = new byte[HashSize];
Array.Copy(combinedBytes, 0, salt, 0, SaltSize);
Array.Copy(combinedBytes, SaltSize, hash, 0, HashSize);
// Compute hash for the input password
byte[] newHash = HashPassword(password, salt);
// Compare the hashes
return CryptographicOperations.FixedTimeEquals(hash, newHash);
}
}
}