using System.Security.Cryptography; using System.Text.Json; namespace LehrerApp.Core.Services; internal class AppLockConfig { public bool Enabled { get; set; } public string? Salt { get; set; } public string? PasswordHash { get; set; } public int TimeoutMinutes { get; set; } = 10; } /// /// App-Sperre nach Inaktivität: eigenes Passwort (unabhängig von einer eventuellen /// Datenbank-Verschlüsselung), als gesalzener Hash in <AppData>/LehrerApp/applock.json /// abgelegt. Das Klartext-Passwort wird nie gespeichert. /// public class AppLockService { private const int Pbkdf2Iterations = 100_000; private readonly string _configPath; private AppLockConfig _config; public bool IsEnabled => _config.Enabled; public int TimeoutMinutes => _config.TimeoutMinutes; public bool HasPassword => !string.IsNullOrEmpty(_config.PasswordHash); public AppLockService(string appDataPath) { _configPath = Path.Combine(appDataPath, "applock.json"); _config = Load(); } public void Configure(bool enabled, int timeoutMinutes) { _config.Enabled = enabled; _config.TimeoutMinutes = Math.Max(1, timeoutMinutes); Save(); } public void SetPassword(string password) { var salt = RandomNumberGenerator.GetBytes(16); _config.Salt = Convert.ToBase64String(salt); _config.PasswordHash = Hash(password, salt); Save(); } public bool VerifyPassword(string password) { if (string.IsNullOrEmpty(_config.PasswordHash) || string.IsNullOrEmpty(_config.Salt)) return false; var salt = Convert.FromBase64String(_config.Salt); return _config.PasswordHash == Hash(password, salt); } private static string Hash(string password, byte[] salt) => Convert.ToBase64String(Rfc2898DeriveBytes.Pbkdf2(password, salt, Pbkdf2Iterations, HashAlgorithmName.SHA256, 32)); private AppLockConfig Load() { try { if (File.Exists(_configPath)) return JsonSerializer.Deserialize(File.ReadAllText(_configPath)) ?? new AppLockConfig(); } catch { /* beschädigte Konfiguration -> Standardwerte, Sperre bleibt deaktiviert */ } return new AppLockConfig(); } private void Save() => File.WriteAllText(_configPath, JsonSerializer.Serialize(_config)); }