diff --git a/KeyGen/LicenseManager.cs b/KeyGen/LicenseManager.cs new file mode 100644 index 0000000..d2f46ec --- /dev/null +++ b/KeyGen/LicenseManager.cs @@ -0,0 +1,119 @@ +using System.Text; + +namespace KeyGen +{ + 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 + } +} \ No newline at end of file diff --git a/KeyGen/TimeHelper.cs b/KeyGen/TimeHelper.cs new file mode 100644 index 0000000..1d14e63 --- /dev/null +++ b/KeyGen/TimeHelper.cs @@ -0,0 +1,46 @@ +using System.Windows.Shapes; + +namespace KeyGen +{ + internal static class TimeHelper + { + public static DateTime GetTrustedTime() + { + // 1. 尝试网络时间 (3秒超时) + try + { + var request = WebRequest.Create("http://www.baidu.com"); // 或 microsoft.com + request.Method = "HEAD"; + request.Timeout = 3000; + using (var response = request.GetResponse()) + { + string dateStr = response.Headers["Date"]; + if (DateTime.TryParseExact(dateStr, "ddd, dd MMM yyyy HH:mm:ss 'GMT'", + CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTime netTime)) + return netTime.ToLocalTime(); + } + } + catch { } + + // 2. 尝试文件系统痕迹校验 (防断网改时间) + DateTime localNow = DateTime.Now; + try + { + // 获取系统目录和临时目录的最后修改时间 + DateTime t1 = new DirectoryInfo(Environment.SystemDirectory).LastWriteTime; + DateTime t2 = new DirectoryInfo(Path.GetTempPath()).LastWriteTime; + DateTime latestFileTime = t1 > t2 ? t1 : t2; + + // 如果本地时间比系统文件时间还要早超过24小时,判定为作弊 + if (localNow < latestFileTime.AddHours(-24)) + { + return latestFileTime; // 强制使用文件时间 + } + } + catch { } + + // 3. 兜底 + return localNow; + } + } +} \ No newline at end of file diff --git a/DrfxFontFixer/App.config b/ShrlAlgoStudio/App.config similarity index 100% rename from DrfxFontFixer/App.config rename to ShrlAlgoStudio/App.config diff --git a/DrfxFontFixer/App.xaml b/ShrlAlgoStudio/App.xaml similarity index 100% rename from DrfxFontFixer/App.xaml rename to ShrlAlgoStudio/App.xaml diff --git a/DrfxFontFixer/App.xaml.cs b/ShrlAlgoStudio/App.xaml.cs similarity index 100% rename from DrfxFontFixer/App.xaml.cs rename to ShrlAlgoStudio/App.xaml.cs diff --git a/DrfxFontFixer/MainWindow.xaml b/ShrlAlgoStudio/DrfxFontFixer.xaml similarity index 99% rename from DrfxFontFixer/MainWindow.xaml rename to ShrlAlgoStudio/DrfxFontFixer.xaml index 629072d..5997751 100644 --- a/DrfxFontFixer/MainWindow.xaml +++ b/ShrlAlgoStudio/DrfxFontFixer.xaml @@ -3,7 +3,7 @@ Title="DaVinci Resolve drfx 字体替换" Width="1000" mc:Ignorable="d" - x:Class="DrfxFontFixer.MainWindow" + x:Class="ShrlAlgoStudio.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" diff --git a/DrfxFontFixer/MainWindow.xaml.cs b/ShrlAlgoStudio/DrfxFontFixer.xaml.cs similarity index 99% rename from DrfxFontFixer/MainWindow.xaml.cs rename to ShrlAlgoStudio/DrfxFontFixer.xaml.cs index 1b0dd44..3076c43 100644 --- a/DrfxFontFixer/MainWindow.xaml.cs +++ b/ShrlAlgoStudio/DrfxFontFixer.xaml.cs @@ -16,7 +16,7 @@ using System.Windows.Media; using Microsoft.Win32; using Newtonsoft.Json; -namespace DrfxFontFixer +namespace ShrlAlgoStudio { public class FullMapping : INotifyPropertyChanged { diff --git a/ShrlAlgoStudio/MainWindow.xaml b/ShrlAlgoStudio/MainWindow.xaml new file mode 100644 index 0000000..7de1eb9 --- /dev/null +++ b/ShrlAlgoStudio/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/ShrlAlgoStudio/MainWindow.xaml.cs b/ShrlAlgoStudio/MainWindow.xaml.cs new file mode 100644 index 0000000..48952b4 --- /dev/null +++ b/ShrlAlgoStudio/MainWindow.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows; + +namespace ShrlAlgoStudio +{ + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/DrfxFontFixer/Properties/Resources.Designer.cs b/ShrlAlgoStudio/Properties/Resources.Designer.cs similarity index 100% rename from DrfxFontFixer/Properties/Resources.Designer.cs rename to ShrlAlgoStudio/Properties/Resources.Designer.cs diff --git a/DrfxFontFixer/Properties/Resources.resx b/ShrlAlgoStudio/Properties/Resources.resx similarity index 100% rename from DrfxFontFixer/Properties/Resources.resx rename to ShrlAlgoStudio/Properties/Resources.resx diff --git a/DrfxFontFixer/Properties/Settings.Designer.cs b/ShrlAlgoStudio/Properties/Settings.Designer.cs similarity index 100% rename from DrfxFontFixer/Properties/Settings.Designer.cs rename to ShrlAlgoStudio/Properties/Settings.Designer.cs diff --git a/DrfxFontFixer/Properties/Settings.settings b/ShrlAlgoStudio/Properties/Settings.settings similarity index 100% rename from DrfxFontFixer/Properties/Settings.settings rename to ShrlAlgoStudio/Properties/Settings.settings diff --git a/ShrlAlgoStudio/ShrlAlgoStudio.csproj b/ShrlAlgoStudio/ShrlAlgoStudio.csproj new file mode 100644 index 0000000..ab1a647 --- /dev/null +++ b/ShrlAlgoStudio/ShrlAlgoStudio.csproj @@ -0,0 +1,16 @@ + + + net8.0-windows + WinExe + 13.0 + true + true + AnyCPU;x64 + + + + + + + + \ No newline at end of file