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; /// /// Provides a static container for cryptographic operations and utilities related to the Adas domain. /// public static class CryptoAdas { private static readonly Regex PassRegex = new("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"); /// /// 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. /// /// The string to hash. Its ASCII byte representation is used as the input to the MD5 algorithm. /// The MD5 hash of formatted as an uppercase hexadecimal string. 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; } /// /// 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 collection is null or empty. /// /// The grouped field whose names, max, since, regularity, and results are included in the hash input. /// The identifier of the patient whose data is being hashed. /// An MD5 hash string representing the combined patient and grouped field data. 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()))); } /// /// Creates a BCrypt hash from the provided input string, typically used for securely storing passwords. /// /// The plain text string to be hashed. /// A BCrypt hashed representation of the input string. public static string CreateBCrypt(string input) { return BCrypt.Net.BCrypt.HashPassword(input); } /// /// Verifies that the provided plain text password matches the stored BCrypt password hash. /// /// The plain text password entered by the user during login. /// The stored BCrypt hash to compare the password against. /// true if the password matches the hash; otherwise, false. public static bool VerifyPassword(string loginPass, string passwordHash) { return BCrypt.Net.BCrypt.Verify(loginPass, passwordHash); } /// /// Determines whether the specified password meets the strong password criteria defined by the password regex pattern. /// /// The password string to evaluate against the strong password requirements. /// true if the password matches the strong password pattern; otherwise, false. public static bool IsStrongPassword(string password) { return PassRegex.IsMatch(password); } }