168 lines
5.6 KiB
C#
168 lines
5.6 KiB
C#
|
|
using System.IO;
|
|||
|
|
using System.Management;
|
|||
|
|
using System.Security.Cryptography;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Windows;
|
|||
|
|
using System.Windows.Controls;
|
|||
|
|
using System.Windows.Data;
|
|||
|
|
using System.Windows.Documents;
|
|||
|
|
using System.Windows.Input;
|
|||
|
|
using System.Windows.Media;
|
|||
|
|
using System.Windows.Media.Imaging;
|
|||
|
|
using System.Windows.Navigation;
|
|||
|
|
using Melskin.Controls;
|
|||
|
|
|
|||
|
|
namespace KeyGen;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Interaction logic for MainWindow.xaml
|
|||
|
|
/// </summary>
|
|||
|
|
public partial class MainWindow
|
|||
|
|
{
|
|||
|
|
private static string _privateKey = string.Empty;
|
|||
|
|
public MainWindow()
|
|||
|
|
{
|
|||
|
|
InitializeComponent();
|
|||
|
|
}
|
|||
|
|
private void LicenseClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
_privateKey = PrivateKeyTextBox.Text;
|
|||
|
|
LicenseManager.PublicKey = PublicKeyTextBox.Text;
|
|||
|
|
DateTime issueDate = DateTime.Now;
|
|||
|
|
//DateTime expiryDate = issueDate.AddYears(1);
|
|||
|
|
DateTime expiryDate = ExpiryDatePicker.DisplayDate;
|
|||
|
|
if (expiryDate < issueDate)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show("授权到期时间有误,应比发码日期晚");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
string mCode = MachineCodeTextBox.Text.Trim().ToUpper();
|
|||
|
|
if (string.IsNullOrEmpty(mCode))
|
|||
|
|
{
|
|||
|
|
MessageBox.Show("请先获取机器码");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
string key = CreateLicense(mCode, issueDate, expiryDate);
|
|||
|
|
LicenseTextBox.Text = key;
|
|||
|
|
Clipboard.SetText(key);
|
|||
|
|
MessageBox.Show("激活码已复制!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private string CreateLicense(string machineCode, DateTime issue, DateTime expiry)
|
|||
|
|
{
|
|||
|
|
string issueStr = issue.ToString("yyyyMMdd");
|
|||
|
|
string expiryStr = expiry.ToString("yyyyMMdd");
|
|||
|
|
|
|||
|
|
// 签名原始数据:机器码 + 发码日期 + 过期日期
|
|||
|
|
string dataToSign = $"{machineCode}|{issueStr}|{expiryStr}";
|
|||
|
|
|
|||
|
|
using (var rsa = new RSACryptoServiceProvider())
|
|||
|
|
{
|
|||
|
|
rsa.FromXmlString(_privateKey);
|
|||
|
|
var formatter = new RSAPKCS1SignatureFormatter(rsa);
|
|||
|
|
formatter.SetHashAlgorithm("SHA256");
|
|||
|
|
|
|||
|
|
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSign);
|
|||
|
|
using (var sha = SHA256.Create())
|
|||
|
|
{
|
|||
|
|
byte[] hash = sha.ComputeHash(dataBytes);
|
|||
|
|
string signature = Convert.ToBase64String(formatter.CreateSignature(hash));
|
|||
|
|
|
|||
|
|
// 最终格式:签名|机器码|发码日期|过期日期
|
|||
|
|
return $"{signature}|{machineCode}|{issueStr}|{expiryStr}";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void GenerateKeyClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
using var rsa = new RSACryptoServiceProvider(2048);
|
|||
|
|
PublicKeyTextBox.Text = rsa.ToXmlString(false); // 放在插件里
|
|||
|
|
PrivateKeyTextBox.Text = rsa.ToXmlString(true); // 自己妥善保存
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ValidateClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
var result = LicenseManager.Validate();
|
|||
|
|
MessageBox.Show(result.msg);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void RemoveLicenseClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
LicenseManager.RemoveLicense();
|
|||
|
|
MessageBox.Show("授权已注销");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ActivateClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
LicenseManager.Activate(LicenseTextBox.Text);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void MachineCodeClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
MachineCodeTextBox.Text = HardwareInfo.GetMachineCode();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SaveKeysClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
VistaFolderBrowserDialog dialog = new VistaFolderBrowserDialog();
|
|||
|
|
if (dialog.ShowDialog())
|
|||
|
|
{
|
|||
|
|
string publicKeyPath = System.IO.Path.Combine(dialog.SelectedPath, "PublicKey.txt");
|
|||
|
|
File.WriteAllText(publicKeyPath, PublicKeyTextBox.Text);
|
|||
|
|
string privateKeyPath = System.IO.Path.Combine(dialog.SelectedPath, "PrivateKey.txt");
|
|||
|
|
File.WriteAllText(privateKeyPath, PrivateKeyTextBox.Text);
|
|||
|
|
MessageBox.Show($"公私密钥已保存到:{dialog.SelectedPath}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SaveLicenseClick(object sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
VistaFolderBrowserDialog dialog = new VistaFolderBrowserDialog();
|
|||
|
|
if (dialog.ShowDialog())
|
|||
|
|
{
|
|||
|
|
string path = System.IO.Path.Combine(dialog.SelectedPath, "license.txt");
|
|||
|
|
File.WriteAllText(path, LicenseTextBox.Text);
|
|||
|
|
MessageBox.Show($"激活码已保存到:{path}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public static class HardwareInfo
|
|||
|
|
{
|
|||
|
|
public static string GetMachineCode()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string cpu = GetWmiInfo("Win32_Processor", "ProcessorId");
|
|||
|
|
string board = GetWmiInfo("Win32_BaseBoard", "SerialNumber");
|
|||
|
|
string disk = GetWmiInfo("Win32_PhysicalMedia", "SerialNumber"); // 物理硬盘序列号
|
|||
|
|
|
|||
|
|
// 拼接并哈希,只取前16位,方便复制
|
|||
|
|
string raw = $"{cpu}@{board}@{disk}";
|
|||
|
|
using (var sha = SHA256.Create())
|
|||
|
|
{
|
|||
|
|
byte[] bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(raw));
|
|||
|
|
return BitConverter.ToString(bytes).Replace("-", "").Substring(0, 16).ToUpper();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
return "ERROR-HARDWARE-ID";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string GetWmiInfo(string table, string prop)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
using (var mc = new ManagementClass(table))
|
|||
|
|
foreach (var mo in mc.GetInstances())
|
|||
|
|
{
|
|||
|
|
string val = mo[prop]?.ToString();
|
|||
|
|
if (!string.IsNullOrWhiteSpace(val)) return val.Trim();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch { }
|
|||
|
|
return "UNKNOWN";
|
|||
|
|
}
|
|||
|
|
}
|