using System; using System.Reflection; using System.Security.Cryptography; using System.Text; using Microsoft.Win32; namespace ShrlAlgoStudio { internal class LicenseManager { // 【重要】替换为你生成的公钥 public static string PublicKey = @"rd5+EjU6QxaTY/AalU9g6ugAquN0ahJSgeahnf2CrfvUAWFNJ+SH7Qr0RcvOTyAbWfvLWoBDACKaPsg+8nRQcO3EZdFyjJ9oycLNrw38+gSB2+/79Axys/8MHtSXVUw9WN2e9LxeHOQGtcaoSsp+bPGaXswthovQ2CkvBTmCokcAOX6UaR7Av4npaXyEoGCUsZLEiSydMsNbQ+wLsumVg1H2o/cpkO0s4DiJHoF66zUuxA+pYSjSCn5KTUsOemf+gBsob6Sw+7WOToyiOkMdO9Op6esf8yL7DJ1Yd40XaKd5IeLQmEX/b+n1EV2JEkGO0p9q9MQRp6NrEc9LvfMJWQ==AQAB"; private static string RegPath = @$"Software\{Assembly.GetExecutingAssembly().GetName()}\License"; /// /// 校验结果枚举 /// public enum AuthStatus { Valid, Expired, HardwareMismatch, TimeTampered, InvalidSignature, NoLicense } /// /// 核心验证方法 /// public static (AuthStatus status, string msg) Validate() { string licenseKey = LoadReg("Key"); if (string.IsNullOrEmpty(licenseKey)) return (AuthStatus.NoLicense, "未激活"); try { // 格式:签名|机器码|发码日期|过期日期 var parts = licenseKey.Split('|'); if (parts.Length != 4) return (AuthStatus.InvalidSignature, "授权格式错误"); string signature = parts[0]; string mCode = parts[1]; string issueDateStr = parts[2]; string expiryDateStr = parts[3]; // 1. 硬件校验 if (mCode != HardwareInfo.GetMachineCode()) return (AuthStatus.HardwareMismatch, "机器码不匹配,请联系管理员"); // 2. RSA 签名校验 (防止篡改日期) string dataVerify = $"{mCode}|{issueDateStr}|{expiryDateStr}"; if (!VerifyRSA(dataVerify, signature)) return (AuthStatus.InvalidSignature, "非法授权 (签名无效)"); // 3. 时间逻辑校验 DateTime issueDate = DateTime.ParseExact(issueDateStr, "yyyyMMdd", null); DateTime expiryDate = DateTime.ParseExact(expiryDateStr, "yyyyMMdd", null); DateTime now = TimeHelper.GetTrustedTime(); // 获取可信时间 // 3.1 检查是否早于发码日期 (防极度回滚) if (now < issueDate) return (AuthStatus.TimeTampered, "系统时间异常:早于授权发码时间"); // 3.2 检查上次运行记录 T (防短期回滚) long lastRunTicks = 0; long.TryParse(LoadReg("T"), out lastRunTicks); if (lastRunTicks > 0) { DateTime lastRun = new DateTime(lastRunTicks); // 允许1小时的误差 if (now < lastRun.AddHours(-1)) return (AuthStatus.TimeTampered, "系统时间异常:检测到时间倒流"); } // 3.3 检查过期 if (now.Date > expiryDate.Date) return (AuthStatus.Expired, $"授权已于 {expiryDate:yyyy-MM-dd} 到期"); // --- 验证通过 --- SaveReg("T", now.Ticks.ToString()); // 更新痕迹 return (AuthStatus.Valid, $"授权有效,到期时间为{expiryDate:yyyy-MM-dd}"); } catch { return (AuthStatus.InvalidSignature, "授权解析异常"); } } // 保存激活码 public static void Activate(string keyInput) { SaveReg("Key", keyInput); } // RSA 验签辅助 private static bool VerifyRSA(string data, string signature) { try { using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(PublicKey); var formatter = new RSAPKCS1SignatureDeformatter(rsa); formatter.SetHashAlgorithm("SHA256"); byte[] dataBytes = Encoding.UTF8.GetBytes(data); byte[] signBytes = Convert.FromBase64String(signature); using (var sha = SHA256.Create()) { return formatter.VerifySignature(sha.ComputeHash(dataBytes), signBytes); } } } catch { return false; } } #region 注册表底层 private static void SaveReg(string key, string val) { using (var r = Registry.CurrentUser.CreateSubKey(RegPath)) r.SetValue(key, val); } private static string LoadReg(string key) { using (var r = Registry.CurrentUser.OpenSubKey(RegPath)) return r?.GetValue(key)?.ToString(); } public static void RemoveLicense() { using (var r = Registry.CurrentUser.OpenSubKey(RegPath, true)) r?.DeleteValue("Key", false); } #endregion } }