using System.Security.Cryptography; using System.Text; namespace PSLauncher.Core.Security; public sealed class SettingsLockService : ISettingsLockService { private string? _expectedHashHex; private bool _unlocked; public bool HasLockConfigured => !string.IsNullOrWhiteSpace(_expectedHashHex); public bool IsLocked => HasLockConfigured && !_unlocked; public bool TryUnlock(string password) { if (!HasLockConfigured) { _unlocked = true; return true; } if (string.IsNullOrEmpty(password)) return false; var inputHash = HashHex(password); var match = string.Equals(inputHash, _expectedHashHex, StringComparison.OrdinalIgnoreCase); if (match) _unlocked = true; return match; } public void Lock() => _unlocked = false; public void SetPasswordHash(string? hash) { _expectedHashHex = string.IsNullOrWhiteSpace(hash) ? null : hash.Trim(); // Si le hash change (admin a modifié le password backoffice), on re-verrouille. _unlocked = false; } /// SHA-256 hex lowercase d'une string UTF-8. Format attendu par le backoffice. public static string HashHex(string input) { var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input)); var sb = new StringBuilder(bytes.Length * 2); foreach (var b in bytes) sb.Append(b.ToString("x2")); return sb.ToString(); } }