Cleaned up and refactored the code to make things much easier to understand.
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
|
||||
namespace SecureCore.Authentication
|
||||
{
|
||||
public class PasswordManager
|
||||
public static 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;
|
||||
@@ -22,10 +20,6 @@ namespace SecureCore.Authentication
|
||||
public static int MaxPasswordLength { get; } = 128;
|
||||
public static int MinPasswordLength { get; } = 16;
|
||||
|
||||
public PasswordManager()
|
||||
{
|
||||
}
|
||||
|
||||
public static (string Hash, string Salt) HashPassword(string password)
|
||||
{
|
||||
var salt = new byte[SaltSize];
|
||||
@@ -35,7 +29,7 @@ namespace SecureCore.Authentication
|
||||
return (GetHash(password, salt), Convert.ToBase64String(salt));
|
||||
}
|
||||
|
||||
public static (bool IsValid, string Message) PasswordIsValid(string password, string salt, string passwordHash)
|
||||
public static (bool IsValid, string Message) IsPasswordValid(string password, string salt, string passwordHash)
|
||||
{
|
||||
if (password.Length < MinPasswordLength) return (false, $"Your password is too short, it must be at least {MinPasswordLength} characters long and not exceed {MaxPasswordLength} characters.");
|
||||
if (password.Length > MaxPasswordLength) return (false, $"Your password is too long, it must not exceed {MaxPasswordLength} characters and must contain at least {MinPasswordLength} characters.");
|
||||
@@ -45,35 +39,53 @@ namespace SecureCore.Authentication
|
||||
if (passwordHash == GetHash(password, saltBytes))
|
||||
return (true, string.Empty);
|
||||
else
|
||||
return (false, string.Empty);
|
||||
return (false, "User name or password is not correct.");
|
||||
}
|
||||
|
||||
public static (string PasswordHash, string SaltHash) GetUserPasswordHash(int userId)
|
||||
public static void InsertPasswordResetRequest(string userName, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress, string connectionString)
|
||||
{
|
||||
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);
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
|
||||
connection.Open();
|
||||
using var command = new SqlCommand("LogPasswordResetRequest", connection) { CommandType = CommandType.StoredProcedure };
|
||||
|
||||
var reader = command.ExecuteReader();
|
||||
command.Parameters.AddWithValue("SessionToken", sessionToken);
|
||||
command.Parameters.AddWithValue("ExpirationDate", expirationDate);
|
||||
command.Parameters.AddWithValue("UserName", userName);
|
||||
command.Parameters.AddWithValue("UserAgent", userAgent);
|
||||
command.Parameters.AddWithValue("IpAddress", ipAddress);
|
||||
|
||||
if (!reader.HasRows) throw new MissingFieldException("No login records exist for this user.");
|
||||
connection.Open();
|
||||
|
||||
reader.Read();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
return (reader["Password Hash"].ToString(), reader["Salt Hash"].ToString());
|
||||
}
|
||||
}
|
||||
//TODO: Reset Password Function Here
|
||||
|
||||
public static (string PasswordHash, string Salt) GetPasswordHashAndSalt(string username, string connectionString)
|
||||
{
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
|
||||
using var command = new SqlCommand("SELECT [Password Hash], [Salt] FROM dbo.GetUserPasswordHashAndSalt(@Username)", connection);
|
||||
|
||||
command.Parameters.AddWithValue("Username", username);
|
||||
|
||||
connection.Open();
|
||||
|
||||
var reader = command.ExecuteReader();
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (!reader.HasRows) return (string.Empty, string.Empty);
|
||||
|
||||
return (reader["Password Hash"].ToString(), reader["Salt"].ToString());
|
||||
}
|
||||
|
||||
public static string HashStringData(string data, string salt = "")
|
||||
{
|
||||
var saltBytes = new byte[0];
|
||||
_ = new byte[0];
|
||||
byte[] saltBytes;
|
||||
|
||||
if(!string.IsNullOrEmpty(salt))
|
||||
if (!string.IsNullOrEmpty(salt))
|
||||
saltBytes = Convert.FromBase64String(salt);
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user