190 lines
7.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|