Files
SzmediTools/KeyGen/MainWindow.xaml.cs
2026-01-16 17:07:43 +08:00

190 lines
7.2 KiB
C#

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using iNKORE.UI.WPF.Modern;
using Microsoft.Win32;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace KeyGen
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void LicenseClick(object sender, RoutedEventArgs e)
{
DateTime issueDate = DateTime.Now;
//DateTime expiryDate = issueDate.AddYears(1);
var expiryDate = ExpiryDatePicker.SelectedDate;
if (expiryDate == null)
{
Message.Text = ("请选择授权到期时间");
return;
}
if (expiryDate < issueDate)
{
Message.Text = ("授权到期时间有误,应比发码日期晚");
return;
}
string mCode = MachineCodeTextBox.Text.Trim().ToUpper();
if (string.IsNullOrEmpty(mCode))
{
Message.Text = ("请先获取机器码");
return;
}
string key = SignData(mCode, issueDate, expiryDate, PrivateKeyTextBox.Text);
LicenseTextBox.Text = key;
Clipboard.SetText(key);
Message.Text = "激活码已复制!";
}
private void GenerateKeyClick(object sender, RoutedEventArgs e)
{
//using (var rsa = new RSACryptoServiceProvider(2048))
//{
// PublicKeyTextBox.Text = rsa.ToXmlString(false); // 放在插件里
// PrivateKeyTextBox.Text = rsa.ToXmlString(true); // 自己妥善保存
//}
// 1. 生成 RSA 密钥对
RsaKeyPairGenerator generator = new RsaKeyPairGenerator();
generator.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();
// 2. 导出公钥为 PEM 格式 (SubjectPublicKeyInfo - OpenSSL 兼容)
using (StringWriter sw = new StringWriter())
{
PemWriter pemWriter = new PemWriter(sw);
pemWriter.WriteObject(keyPair.Public);
PublicKeyTextBox.Text = sw.ToString();
}
// 3. 导出私钥为 PEM 格式 (PKCS#1 格式)
using (StringWriter sw = new StringWriter())
{
PemWriter pemWriter = new PemWriter(sw);
pemWriter.WriteObject(keyPair.Private);
PrivateKeyTextBox.Text = sw.ToString();
}
}
public string SignData(string machineCode, DateTime issue, DateTime? expiry, string privateKeyPem)
{
if (expiry == null)
{
throw new ArgumentNullException(nameof(expiry), "Expiry date cannot be null.");
}
// 1. 严格格式化日期
string issueStr = issue.ToString("yyyy-MM-dd");
string expiryStr = expiry?.ToString("yyyy-MM-dd");
// 2. 拼接原始数据 (必须带上 |)
string dataToSign = $"{machineCode}{issueStr}{expiryStr}";
// 3. 使用 BouncyCastle 签名
ISigner signer = SignerUtilities.GetSigner("SHA-256withRSA");
using (StringReader sr = new StringReader(privateKeyPem))
{
PemReader pr = new PemReader(sr);
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
signer.Init(true, keyPair.Private);
}
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSign);
signer.BlockUpdate(dataBytes, 0, dataBytes.Length);
byte[] sigBytes = signer.GenerateSignature();
string signature = Convert.ToBase64String(sigBytes);
// 4. 返回最终激活码
return $"{signature}|{machineCode}|{issueStr}|{expiryStr}";
}
private string CreateLicense(string machineCode, DateTime issue, DateTime expiry)
{
string issueStr = issue.ToString("yyyy-MM-dd");
string expiryStr = expiry.ToString("yyyy-MM-dd");
// 签名原始数据:机器码 + 发码日期 + 过期日期
string dataToSign = $"{machineCode}|{issueStr}|{expiryStr}";
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(PrivateKeyTextBox.Text);
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 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);
Message.Text = ($"公私密钥已保存到:{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);
Message.Text = ($"激活码已保存到:{path}");
}
}
private void ImportPrivateKeyClick(object sender, RoutedEventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog()
{
Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*"
};
if (dialog.ShowDialog() == true)
{
string privateKey = File.ReadAllText(dialog.FileName);
PrivateKeyTextBox.Text = privateKey;
Message.Text = ($"导入文件私钥完成");
}
}
private void Button_ToggleTheme_Click(object sender, RoutedEventArgs e)
{
if (ThemeManager.Current.ApplicationTheme == ApplicationTheme.Dark)
{
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
}
else
{
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
}
}
}
}