using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Security.Cryptography; using System.Management; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace KeyNexus { /// /// KeyNexus .NET SDK Client /// public class KeyNexusClient : IDisposable { private readonly HttpClient _httpClient; private readonly string _appId; private readonly string _secretKey; private readonly string _apiUrl; private string _sessionToken; private string _hwid; /// /// Initialize KeyNexus client /// /// Your application ID from KeyNexus dashboard /// Your secret key (keep this secure!) /// API base URL (default: https://keynexus.es/api) /// Automatically generate HWID (default: true) public KeyNexusClient(string appId, string secretKey, string apiUrl = "https://keynexus.es/api", bool autoHwid = true) { _appId = appId ?? throw new ArgumentNullException(nameof(appId)); _secretKey = secretKey ?? throw new ArgumentNullException(nameof(secretKey)); _apiUrl = apiUrl.TrimEnd('/'); _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; if (autoHwid) { _hwid = GenerateHWID(); } } /// /// Generate a unique hardware ID for this machine /// /// Hardware ID string public static string GenerateHWID() { try { var info = new StringBuilder(); // Get processor ID using (var searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor")) { foreach (var obj in searcher.Get()) { info.Append(obj["ProcessorId"]?.ToString() ?? ""); } } // Get motherboard serial using (var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard")) { foreach (var obj in searcher.Get()) { info.Append(obj["SerialNumber"]?.ToString() ?? ""); } } // Get MAC address using (var searcher = new ManagementObjectSearcher("SELECT MACAddress FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL")) { foreach (var obj in searcher.Get()) { var mac = obj["MACAddress"]?.ToString(); if (!string.IsNullOrEmpty(mac)) { info.Append(mac); break; } } } // Create hash using (var sha256 = SHA256.Create()) { var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(info.ToString())); return BitConverter.ToString(hash).Replace("-", "").ToLower(); } } catch { // Fallback to machine name hash using (var sha256 = SHA256.Create()) { var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(Environment.MachineName + Guid.NewGuid())); return BitConverter.ToString(hash).Replace("-", "").ToLower(); } } } /// /// Initialize application and verify it's active /// /// Your application version /// Initialization result public async Task> InitializeAsync(string version = "1.0.0") { var data = new { action = "init", appId = _appId, secretKey = _secretKey, version }; var response = await PostAsync("/client", data); return response; } /// /// Validate a license key /// /// The license key to validate /// Hardware ID (uses auto-generated if not provided) /// Validation result with license info public async Task> ValidateLicenseAsync(string licenseKey, string hwid = null) { var data = new { action = "license", appId = _appId, secretKey = _secretKey, key = licenseKey, hwid = hwid ?? _hwid }; var response = await PostAsync("/client", data); // Store session token if provided if (response.Success && response.Data?.SessionToken != null) { _sessionToken = response.Data.SessionToken; } return response; } /// /// Login with username/password /// /// User's username or email /// User's password /// Hardware ID (uses auto-generated if not provided) /// Login result with user info and session token public async Task> LoginWithPasswordAsync(string username, string password, string hwid = null) { var data = new { applicationId = _appId, username, password, hwid = hwid ?? _hwid }; var response = await PostAsync("/client/auth", data); // Store session token if (response.Success && response.Data?.Token != null) { _sessionToken = response.Data.Token; } return response; } /// /// Get current user information /// /// Session token (uses stored token if not provided) /// User information public async Task> GetUserInfoAsync(string token = null) { var tokenToUse = token ?? _sessionToken; if (string.IsNullOrEmpty(tokenToUse)) { throw new InvalidOperationException("No active session. Please login first."); } _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokenToUse); try { var response = await _httpClient.GetAsync($"{_apiUrl}/client/me"); var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject>(content); } finally { _httpClient.DefaultRequestHeaders.Authorization = null; } } /// /// Logout current session /// /// Logout result public async Task> LogoutAsync() { if (string.IsNullOrEmpty(_sessionToken)) { throw new InvalidOperationException("No active session"); } _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _sessionToken); try { var response = await _httpClient.PostAsync($"{_apiUrl}/client/logout", null); var content = await response.Content.ReadAsStringAsync(); // Clear session token _sessionToken = null; return JsonConvert.DeserializeObject>(content); } finally { _httpClient.DefaultRequestHeaders.Authorization = null; } } /// /// Get the current hardware ID /// /// Current HWID public string GetHWID() => _hwid ?? GenerateHWID(); /// /// Manually set the hardware ID /// /// Hardware ID to use public void SetHWID(string hwid) => _hwid = hwid; private async Task> PostAsync(string endpoint, object data) { try { var json = JsonConvert.SerializeObject(data); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync($"{_apiUrl}{endpoint}", content); var responseContent = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject>(responseContent); } catch (HttpRequestException ex) { return new KeyNexusResponse { Success = false, Message = $"Network error: {ex.Message}" }; } catch (TaskCanceledException) { return new KeyNexusResponse { Success = false, Message = "Request timeout" }; } } public void Dispose() { _httpClient?.Dispose(); } } #region Response Models public class KeyNexusResponse { [JsonProperty("success")] public bool Success { get; set; } [JsonProperty("message")] public string Message { get; set; } [JsonProperty("data")] public T Data { get; set; } } public class AppInfo { [JsonProperty("version")] public string Version { get; set; } [JsonProperty("status")] public string Status { get; set; } } public class LicenseInfo { [JsonProperty("license")] public License License { get; set; } [JsonProperty("sessionToken")] public string SessionToken { get; set; } } public class License { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("expiresAt")] public DateTime? ExpiresAt { get; set; } [JsonProperty("daysLeft")] public int? DaysLeft { get; set; } } public class UserInfo { [JsonProperty("user")] public UserData User { get; set; } [JsonProperty("token")] public string Token { get; set; } } public class UserData { [JsonProperty("username")] public string Username { get; set; } [JsonProperty("email")] public string Email { get; set; } [JsonProperty("subscriptionExpiry")] public DateTime? SubscriptionExpiry { get; set; } [JsonProperty("hwid")] public string HWID { get; set; } } #endregion }