using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Management; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace LicenseClient { /// /// Vollständige Lizenzserver-Integration für .NET-Anwendungen /// public class LicenseManager : IDisposable { private readonly HttpClient httpClient; private readonly string apiKey; private readonly string appVersion; private readonly string serverUrl = "https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com"; private readonly string cacheFilePath; private string licenseKey; private int? activationId; private DateTime? expiresAt; private bool isValid; private Timer heartbeatTimer; private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); public LicenseManager(string apiKey, string appVersion = "1.0.0") { this.apiKey = apiKey; this.appVersion = appVersion; // HttpClient Setup var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true // Für Entwicklung }; httpClient = new HttpClient(handler); httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}"); httpClient.Timeout = TimeSpan.FromSeconds(30); // Cache-Verzeichnis string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); string appFolder = Path.Combine(appDataPath, "MyApp", "License"); Directory.CreateDirectory(appFolder); cacheFilePath = Path.Combine(appFolder, "license.json"); } /// /// Eindeutige Maschinen-ID generieren /// private string GetMachineId() { try { // CPU-ID abrufen string cpuId = ""; using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor")) { foreach (ManagementObject obj in searcher.Get()) { cpuId = obj["ProcessorId"]?.ToString() ?? ""; break; } } // Motherboard Serial Number string motherboardId = ""; using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard")) { foreach (ManagementObject obj in searcher.Get()) { motherboardId = obj["SerialNumber"]?.ToString() ?? ""; break; } } return $"{cpuId}-{motherboardId}"; } catch { // Fallback: Machine Name + User return $"{Environment.MachineName}-{Environment.UserName}"; } } /// /// Hardware-Fingerprint erstellen /// private string GetHardwareHash() { var components = new List { GetMachineId(), Environment.MachineName, Environment.OSVersion.ToString(), Environment.ProcessorCount.ToString() }; // MAC-Adressen hinzufügen try { using (var searcher = new ManagementObjectSearcher("SELECT MACAddress FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL")) { foreach (ManagementObject obj in searcher.Get()) { string mac = obj["MACAddress"]?.ToString(); if (!string.IsNullOrEmpty(mac)) components.Add(mac); } } } catch { } string combined = string.Join("-", components); using (SHA256 sha256 = SHA256.Create()) { byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined)); return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); } } /// /// Lizenz-Cache speichern /// private async Task SaveLicenseCacheAsync() { var cacheData = new { license_key = licenseKey, activation_id = activationId, expires_at = expiresAt?.ToString("O"), hardware_hash = GetHardwareHash(), last_verified = DateTime.UtcNow.ToString("O") }; string json = JsonSerializer.Serialize(cacheData, new JsonSerializerOptions { WriteIndented = true }); await File.WriteAllTextAsync(cacheFilePath, json); } /// /// Lizenz-Cache laden /// private async Task LoadLicenseCacheAsync() { if (!File.Exists(cacheFilePath)) return null; try { string json = await File.ReadAllTextAsync(cacheFilePath); return JsonSerializer.Deserialize(json); } catch { return null; } } /// /// Lizenz aktivieren /// public async Task<(bool Success, string Message)> ActivateLicenseAsync(string licenseKey) { await semaphore.WaitAsync(); try { var requestData = new { license_key = licenseKey, machine_id = GetMachineId(), hardware_hash = GetHardwareHash(), os_info = new { os = "Windows", version = Environment.OSVersion.Version.ToString(), platform = Environment.OSVersion.Platform.ToString(), service_pack = Environment.OSVersion.ServicePack }, app_version = appVersion }; var json = JsonSerializer.Serialize(requestData); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync($"{serverUrl}/api/license/activate", content); var responseContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { var result = JsonSerializer.Deserialize(responseContent); if (result.success) { this.licenseKey = licenseKey; this.activationId = result.activation_id; this.isValid = true; if (!string.IsNullOrEmpty(result.expires_at)) this.expiresAt = DateTime.Parse(result.expires_at); await SaveLicenseCacheAsync(); StartHeartbeat(); return (true, result.message ?? "Lizenz erfolgreich aktiviert"); } else { return (false, result.message ?? "Aktivierung fehlgeschlagen"); } } else { return (false, $"Server-Fehler: {response.StatusCode}"); } } catch (HttpRequestException ex) { return (false, $"Verbindungsfehler: {ex.Message}"); } catch (Exception ex) { return (false, $"Fehler: {ex.Message}"); } finally { semaphore.Release(); } } /// /// Lizenz verifizieren (Heartbeat) /// public async Task<(bool Valid, string Message)> VerifyLicenseAsync() { if (string.IsNullOrEmpty(licenseKey) || !activationId.HasValue) return (false, "Keine aktive Lizenz"); await semaphore.WaitAsync(); try { var requestData = new { license_key = licenseKey, machine_id = GetMachineId(), hardware_hash = GetHardwareHash(), activation_id = activationId.Value }; var json = JsonSerializer.Serialize(requestData); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync($"{serverUrl}/api/license/verify", content); var responseContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { var result = JsonSerializer.Deserialize(responseContent); isValid = result.valid; if (isValid) { await SaveLicenseCacheAsync(); if (result.requires_update) { OnUpdateAvailable?.Invoke(result.update_url); } } return (isValid, result.message ?? ""); } else { return (false, $"Server-Fehler: {response.StatusCode}"); } } catch (HttpRequestException) { // Offline-Verifizierung return await VerifyOfflineAsync(); } catch (Exception ex) { return (false, $"Fehler: {ex.Message}"); } finally { semaphore.Release(); } } /// /// Offline-Verifizierung mit Grace Period /// private async Task<(bool Valid, string Message)> VerifyOfflineAsync() { var cache = await LoadLicenseCacheAsync(); if (cache == null) return (false, "Keine gecachte Lizenz vorhanden"); // Hardware-Hash prüfen if (cache.hardware_hash != GetHardwareHash()) { // Grace Period bei Hardware-Änderung var lastVerified = DateTime.Parse(cache.last_verified); var gracePeriod = TimeSpan.FromDays(7); if (DateTime.UtcNow - lastVerified > gracePeriod) return (false, "Hardware geändert - Grace Period abgelaufen"); } // Ablaufdatum prüfen if (!string.IsNullOrEmpty(cache.expires_at)) { var expiresAt = DateTime.Parse(cache.expires_at); if (DateTime.UtcNow > expiresAt) return (false, "Lizenz abgelaufen"); } licenseKey = cache.license_key; activationId = cache.activation_id; isValid = true; return (true, "Offline-Modus (gecachte Lizenz)"); } /// /// Nach Updates suchen /// public async Task CheckForUpdatesAsync() { if (string.IsNullOrEmpty(licenseKey)) return null; try { var requestData = new { current_version = appVersion, license_key = licenseKey }; var json = JsonSerializer.Serialize(requestData); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync($"{serverUrl}/api/version/check", content); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(responseContent); } } catch { } return null; } /// /// Heartbeat starten /// private void StartHeartbeat() { heartbeatTimer?.Dispose(); // Alle 15 Minuten heartbeatTimer = new Timer(async _ => { var (valid, message) = await VerifyLicenseAsync(); if (!valid) { OnLicenseInvalid?.Invoke(message); } }, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15)); } /// /// Lizenz-Informationen abrufen /// public LicenseInfo GetLicenseInfo() { return new LicenseInfo { IsValid = isValid, LicenseKey = string.IsNullOrEmpty(licenseKey) ? null : licenseKey.Substring(0, 4) + "****", ExpiresAt = expiresAt, MachineId = GetMachineId() }; } // Events public event Action OnUpdateAvailable; public event Action OnLicenseInvalid; public void Dispose() { heartbeatTimer?.Dispose(); httpClient?.Dispose(); semaphore?.Dispose(); } } // Hilfsklassen public class LicenseCache { public string license_key { get; set; } public int? activation_id { get; set; } public string expires_at { get; set; } public string hardware_hash { get; set; } public string last_verified { get; set; } } public class ActivationResponse { public bool success { get; set; } public string message { get; set; } public int? activation_id { get; set; } public string expires_at { get; set; } } public class VerificationResponse { public bool valid { get; set; } public string message { get; set; } public string expires_at { get; set; } public bool requires_update { get; set; } public string update_url { get; set; } } public class UpdateInfo { public string latest_version { get; set; } public string current_version { get; set; } public bool update_available { get; set; } public bool is_mandatory { get; set; } public string download_url { get; set; } public string release_notes { get; set; } } public class LicenseInfo { public bool IsValid { get; set; } public string LicenseKey { get; set; } public DateTime? ExpiresAt { get; set; } public string MachineId { get; set; } } // Beispiel-Anwendung class Program { static async Task Main(string[] args) { // API-Key aus Umgebungsvariable oder Konfiguration string apiKey = Environment.GetEnvironmentVariable("LICENSE_API_KEY") ?? "your-api-key-here"; using (var licenseManager = new LicenseManager(apiKey, "1.0.0")) { // Event-Handler registrieren licenseManager.OnUpdateAvailable += url => Console.WriteLine($"Update verfügbar: {url}"); licenseManager.OnLicenseInvalid += msg => Console.WriteLine($"Lizenz ungültig: {msg}"); // Lizenz prüfen/aktivieren var cache = await licenseManager.LoadLicenseCacheAsync(); if (cache != null) { Console.WriteLine("Gecachte Lizenz gefunden, verifiziere..."); var (valid, message) = await licenseManager.VerifyLicenseAsync(); if (!valid) { Console.WriteLine($"Lizenz ungültig: {message}"); await ActivateNewLicense(licenseManager); } else { Console.WriteLine($"✓ Lizenz gültig: {message}"); } } else { await ActivateNewLicense(licenseManager); } // Update-Check var updateInfo = await licenseManager.CheckForUpdatesAsync(); if (updateInfo?.update_available == true) { Console.WriteLine($"Update verfügbar: {updateInfo.latest_version}"); if (updateInfo.is_mandatory) Console.WriteLine("⚠️ Dies ist ein Pflicht-Update!"); } // Lizenz-Info anzeigen var info = licenseManager.GetLicenseInfo(); Console.WriteLine($"\nLizenz-Status:"); Console.WriteLine($"- Gültig: {info.IsValid}"); Console.WriteLine($"- Ablauf: {info.ExpiresAt}"); Console.WriteLine($"- Maschine: {info.MachineId}"); // App läuft... Console.WriteLine("\n✓ Anwendung gestartet"); Console.WriteLine("Drücken Sie eine Taste zum Beenden..."); Console.ReadKey(); } } static async Task ActivateNewLicense(LicenseManager licenseManager) { Console.Write("Bitte Lizenzschlüssel eingeben: "); string licenseKey = Console.ReadLine(); var (success, message) = await licenseManager.ActivateLicenseAsync(licenseKey); if (success) { Console.WriteLine($"✓ {message}"); } else { Console.WriteLine($"✗ {message}"); Environment.Exit(1); } } } }