84 lines
4.0 KiB
C#
84 lines
4.0 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using adas_core.Domain.Models.GroupedObservations;
|
|
using MongoDB.Bson;
|
|
|
|
namespace adas_core.Domain.Utils;
|
|
|
|
/// <summary>
|
|
/// Provides a static container for cryptographic operations and utilities related to the Adas domain.
|
|
/// </summary>
|
|
public static class CryptoAdas
|
|
{
|
|
private static readonly Regex PassRegex = new("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
|
|
|
|
/// <summary>
|
|
/// Computes the MD5 hash of the specified input string and returns it as an uppercase hexadecimal string.
|
|
/// The hash bytes are iterated in reverse order before being formatted.
|
|
/// </summary>
|
|
/// <param name="input">The string to hash. Its ASCII byte representation is used as the input to the MD5 algorithm.</param>
|
|
/// <returns>The MD5 hash of <paramref name="input"/> formatted as an uppercase hexadecimal string.</returns>
|
|
public static string CreateMd5(string input)
|
|
{
|
|
using var md5 = MD5.Create();
|
|
var inputBytes = Encoding.ASCII.GetBytes(input);
|
|
var hashBytes = md5.ComputeHash(inputBytes);
|
|
|
|
var sb = new StringBuilder();
|
|
for (var i = hashBytes.Length - 1; i >= 0; i--) sb.Append(hashBytes[i].ToString("X2"));
|
|
|
|
var res = sb.ToString();
|
|
return res;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a deterministic MD5 hash that uniquely identifies a grouped field configuration for a specific patient.
|
|
/// Falls back to a single-element list containing the group's name (or empty string) when the <see cref="GroupedField.Names"/> collection is null or empty.
|
|
/// </summary>
|
|
/// <param name="gF">The grouped field whose names, max, since, regularity, and results are included in the hash input.</param>
|
|
/// <param name="patientId">The identifier of the patient whose data is being hashed.</param>
|
|
/// <returns>An MD5 hash string representing the combined patient and grouped field data.</returns>
|
|
public static string CreateMd5GroupedObs(GroupedField gF, ObjectId patientId)
|
|
{
|
|
var names = CollectionsUtils.IfEmptyOrNull(gF.Names, [gF.Name ?? string.Empty]);
|
|
|
|
return CreateMd5(patientId +
|
|
string.Join("+", names.Select(c => c.ToString())) +
|
|
gF.Max +
|
|
gF.Since +
|
|
gF.Regularity +
|
|
string.Join("+", gF.Result.Select(c => c.ToString())));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a BCrypt hash from the provided input string, typically used for securely storing passwords.
|
|
/// </summary>
|
|
/// <param name="input">The plain text string to be hashed.</param>
|
|
/// <returns>A BCrypt hashed representation of the input string.</returns>
|
|
public static string CreateBCrypt(string input)
|
|
{
|
|
return BCrypt.Net.BCrypt.HashPassword(input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifies that the provided plain text password matches the stored BCrypt password hash.
|
|
/// </summary>
|
|
/// <param name="loginPass">The plain text password entered by the user during login.</param>
|
|
/// <param name="passwordHash">The stored BCrypt hash to compare the password against.</param>
|
|
/// <returns><c>true</c> if the password matches the hash; otherwise, <c>false</c>.</returns>
|
|
public static bool VerifyPassword(string loginPass, string passwordHash)
|
|
{
|
|
return BCrypt.Net.BCrypt.Verify(loginPass, passwordHash);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether the specified password meets the strong password criteria defined by the password regex pattern.
|
|
/// </summary>
|
|
/// <param name="password">The password string to evaluate against the strong password requirements.</param>
|
|
/// <returns><c>true</c> if the password matches the strong password pattern; otherwise, <c>false</c>.</returns>
|
|
public static bool IsStrongPassword(string password)
|
|
{
|
|
return PassRegex.IsMatch(password);
|
|
}
|
|
} |