using System; using System.Data.SqlClient; using Microsoft.AspNetCore.Cryptography.KeyDerivation; namespace SecureCore.Authentication { public class PasswordManager { //Add some pepper to the passwords for good measure: //https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html private static string Pepper { get; } = "rVk/OwQUw01qy76Q+5WimPk+NdqUMMghftMXyJzzckOj/+eFn056PDYzBD61E/ZNjRdgiMK6RhcHEcdfpJdbcw=="; private static string ConnectionString = @"Server=DESKTOP-OEDDVKC\SQLEXPRESS;Database=main;Integrated Security=true;"; private static int Iterations { get; } = 100000; private static KeyDerivationPrf KeyType { get; } = KeyDerivationPrf.HMACSHA512; private static int KeySize { get; } = 512 / 8; private static int SaltSize { get; } = 128 / 8; //128 bit salt public PasswordManager() { } public static (string Hash, string Salt) HashPassword(string password) { var salt = new byte[SaltSize]; ByteGenerator.GetRandomBytes(ref salt); return (GetHash(password, salt), Convert.ToBase64String(salt)); } public static bool PasswordIsValid(string password, string salt, string passwordHash) { var saltBytes = Convert.FromBase64String(salt); return passwordHash == GetHash(password, saltBytes); } public static (string PasswordHash, string SaltHash) GetUserPasswordHash(int userId) { using (var connection = new SqlConnection(ConnectionString)) { using (var command = new SqlCommand("SELECT [Password Hash], [Salt Hash] FROM Login WHERE [User Key] = @UserId", connection)) { command.Parameters.AddWithValue("UserId", userId); connection.Open(); var reader = command.ExecuteReader(); if (!reader.HasRows) throw new MissingFieldException("No login records exist for this user."); reader.Read(); return (reader["Password Hash"].ToString(), reader["Salt Hash"].ToString()); } } } public static string HashStringData(string data, byte[] salt = null) { return data; if (salt == null) salt = new byte[0]; return GetHash(data, salt); } public static string HashStringData(string data, string salt = "") { return data; var saltBytes = new byte[0]; if(!string.IsNullOrEmpty(salt)) saltBytes = Convert.FromBase64String(salt); return GetHash(data, saltBytes); } private static string GetHash(string password, byte[] salt) { return Convert.ToBase64String(KeyDerivation.Pbkdf2($"{password}{Pepper}", salt, KeyType, Iterations, KeySize)); } } }