diff --git a/HIR-Activate.sln b/HIR-Activate.sln
new file mode 100644
index 0000000..06cc5fc
--- /dev/null
+++ b/HIR-Activate.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35514.174 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HIR-Activate", "HIR-Activate\HIR-Activate.csproj", "{01A02918-32D7-4EFF-8F04-4E1A80DBD646}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {01A02918-32D7-4EFF-8F04-4E1A80DBD646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {01A02918-32D7-4EFF-8F04-4E1A80DBD646}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {01A02918-32D7-4EFF-8F04-4E1A80DBD646}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {01A02918-32D7-4EFF-8F04-4E1A80DBD646}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/HIR-Activate/Encryption/AesEncryption.cs b/HIR-Activate/Encryption/AesEncryption.cs
new file mode 100644
index 0000000..ed71d8b
--- /dev/null
+++ b/HIR-Activate/Encryption/AesEncryption.cs
@@ -0,0 +1,153 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace IRaCIS.Core.Infrastructure.Encryption;
+
+public class AesEncryption
+{
+ // AES 加密(不带 IV)
+ public static string Encrypt(string plainText, string key)
+ {
+ var keyBytes = Encoding.UTF8.GetBytes(key);
+
+ // 使用 AES 引擎 + PKCS7 填充
+ var engine = new AesEngine();
+ var blockCipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
+ blockCipher.Init(true, new KeyParameter(keyBytes)); // true 表示加密
+
+ var inputBytes = Encoding.UTF8.GetBytes(plainText);
+ var encryptedBytes = ProcessCipher(blockCipher, inputBytes);
+
+ // 返回 Base64 编码的加密字符串
+ return Convert.ToBase64String(encryptedBytes);
+ }
+
+ // AES 解密(不带 IV)
+ public static string Decrypt(string encryptedText, string key)
+ {
+ var keyBytes = Encoding.UTF8.GetBytes(key);
+ var cipherBytes = Convert.FromBase64String(encryptedText);
+
+ // 使用 AES 引擎 + PKCS7 填充
+ var engine = new AesEngine();
+ var blockCipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
+ blockCipher.Init(false, new KeyParameter(keyBytes)); // false 表示解密
+
+ var decryptedBytes = ProcessCipher(blockCipher, cipherBytes);
+ return Encoding.UTF8.GetString(decryptedBytes);
+ }
+
+ // AES 加密(带 IV)
+ ///
+ /// AES 密钥的长度必须是以下之一:128 位(16 字节)192 位(24 字节)256 位(32 字节)
+ /// IV must be 16 bytes
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string Encrypt(string plainText, string key, string iv)
+ {
+ var keyBytes = Encoding.UTF8.GetBytes(key.PadRight(32, '0').Substring(0, 32));
+ var ivBytes = Encoding.UTF8.GetBytes(iv.PadRight(16, '0').Substring(0, 16));
+
+ // 使用 AES 引擎 + PKCS7 填充 + CBC 模式
+ var engine = new AesEngine();
+ var blockCipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
+ blockCipher.Init(true, new ParametersWithIV(new KeyParameter(keyBytes), ivBytes)); // true 表示加密
+
+ var inputBytes = Encoding.UTF8.GetBytes(plainText);
+ var encryptedBytes = ProcessCipher(blockCipher, inputBytes);
+
+ // 返回 Base64 编码的加密字符串
+ return Convert.ToBase64String(encryptedBytes);
+ }
+
+ // AES 解密(带 IV)
+ public static string Decrypt(string encryptedText, string key, string iv)
+ {
+ var keyBytes = Encoding.UTF8.GetBytes(key.PadRight(32, '0').Substring(0, 32));
+ var ivBytes = Encoding.UTF8.GetBytes(iv.PadRight(16, '0').Substring(0, 16));
+ var cipherBytes = Convert.FromBase64String(encryptedText);
+
+ // 使用 AES 引擎 + PKCS7 填充 + CBC 模式
+ var engine = new AesEngine();
+ var blockCipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
+ blockCipher.Init(false, new ParametersWithIV(new KeyParameter(keyBytes), ivBytes)); // false 表示解密
+
+ var decryptedBytes = ProcessCipher(blockCipher, cipherBytes);
+ return Encoding.UTF8.GetString(decryptedBytes);
+ }
+
+ // 处理加密/解密数据
+ private static byte[] ProcessCipher(IBufferedCipher cipher, byte[] input)
+ {
+ var output = new byte[cipher.GetOutputSize(input.Length)];
+ int length = cipher.ProcessBytes(input, 0, input.Length, output, 0);
+ length += cipher.DoFinal(output, length);
+ Array.Resize(ref output, length); // 调整输出数组大小以适应实际数据长度
+ return output;
+ }
+
+ public static string DefaultKey = "12345678901234567890123456789012";
+
+ public static string EncryptPartial(string plainText, int unencryptedPrefixLength)
+ {
+ if (plainText.Length <= unencryptedPrefixLength)
+ {
+ return Encrypt(plainText, DefaultKey); // 如果文本太短,直接加密
+ }
+
+ var prefix = plainText.Substring(0, unencryptedPrefixLength);
+ var suffix = plainText.Substring(unencryptedPrefixLength);
+
+ return prefix + Encrypt(suffix, DefaultKey); // 前缀保留,后缀加密
+ }
+
+ public static string DecryptPartial(string encryptedText, int unencryptedPrefixLength)
+ {
+ if (encryptedText.Length <= unencryptedPrefixLength)
+ {
+ return Decrypt(encryptedText, DefaultKey); // 如果文本太短,直接解密
+ }
+
+ var prefix = encryptedText.Substring(0, unencryptedPrefixLength);
+ var suffix = encryptedText.Substring(unencryptedPrefixLength);
+
+ return prefix + Decrypt(suffix, DefaultKey); // 前缀保留,后缀解密
+ }
+
+ //public static string Encrypt(string plainText)
+ //{
+ // using var aes = Aes.Create();
+ // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey);
+ // aes.Mode = CipherMode.ECB; // 根据需要选择加密模式,这里使用 ECB 模式
+ // aes.Padding = PaddingMode.PKCS7;
+
+ // var encryptor = aes.CreateEncryptor();
+ // var plainBytes = Encoding.UTF8.GetBytes(plainText);
+ // var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
+
+ // return Convert.ToBase64String(encryptedBytes);
+ //}
+
+ //public static string Decrypt(string encryptedText)
+ //{
+ // using var aes = Aes.Create();
+ // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey);
+ // aes.Mode = CipherMode.ECB;
+ // aes.Padding = PaddingMode.PKCS7;
+
+ // var decryptor = aes.CreateDecryptor();
+ // var encryptedBytes = Convert.FromBase64String(encryptedText);
+ // var decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
+
+ // return Encoding.UTF8.GetString(decryptedBytes);
+ //}
+}
diff --git a/HIR-Activate/Encryption/RSAEncryption.cs b/HIR-Activate/Encryption/RSAEncryption.cs
new file mode 100644
index 0000000..3f7d00c
--- /dev/null
+++ b/HIR-Activate/Encryption/RSAEncryption.cs
@@ -0,0 +1,94 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using System;
+using System.IO;
+using System.Text;
+
+namespace IRaCIS.Core.Infrastructure.Encryption;
+
+///
+/// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
+///
+public class RSAEncryption
+{
+
+ public static AsymmetricCipherKeyPair GenerateRSAKeyPair(int keySize)
+ {
+ var keyGenerationParameters = new KeyGenerationParameters(new SecureRandom(), keySize);
+ var keyPairGenerator = new RsaKeyPairGenerator();
+ keyPairGenerator.Init(keyGenerationParameters);
+ return keyPairGenerator.GenerateKeyPair();
+ }
+
+ public static string ExportPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ using (StringWriter sw = new StringWriter())
+ {
+ PemWriter pw = new PemWriter(sw);
+ pw.WriteObject(publicKey);
+ pw.Writer.Flush();
+ return sw.ToString();
+ }
+ }
+
+ public static string ExportPrivateKey(AsymmetricKeyParameter privateKey)
+ {
+ using (StringWriter sw = new StringWriter())
+ {
+ PemWriter pw = new PemWriter(sw);
+ pw.WriteObject(privateKey);
+ pw.Writer.Flush();
+ return sw.ToString();
+ }
+ }
+
+ ///
+ /// RSA解密
+ ///
+ /// 私钥
+ /// 待解密的字符串(Base64)
+ /// 解密后的字符串
+ public static string Decrypt(string privateKey, string decryptstring)
+ {
+ using (TextReader reader = new StringReader(privateKey))
+ {
+ dynamic key = new PemReader(reader).ReadObject();
+ var rsaDecrypt = new Pkcs1Encoding(new RsaEngine());
+ if (key is AsymmetricKeyParameter)
+ {
+ key = (AsymmetricKeyParameter)key;
+ }
+ else if (key is AsymmetricCipherKeyPair)
+ {
+ key = ((AsymmetricCipherKeyPair)key).Private;
+ }
+ rsaDecrypt.Init(false, key); //这里加密是true;解密是false
+
+ byte[] entData = Convert.FromBase64String(decryptstring);
+ entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length);
+ return Encoding.UTF8.GetString(entData);
+ }
+ }///
+
+ /// 加密
+ ///
+ /// 公钥
+ /// 待加密的字符串
+ /// 加密后的Base64
+ public static string Encrypt(string publicKey, string encryptstring)
+ {
+ using (TextReader reader = new StringReader(publicKey))
+ {
+ AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter;
+ Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine());
+ pkcs1.Init(true, key);//加密是true;解密是false;
+ byte[] entData = Encoding.UTF8.GetBytes(encryptstring);
+ entData = pkcs1.ProcessBlock(entData, 0, entData.Length);
+ return Convert.ToBase64String(entData);
+ }
+ }
+}
diff --git a/HIR-Activate/Form1.Designer.cs b/HIR-Activate/Form1.Designer.cs
new file mode 100644
index 0000000..86d1830
--- /dev/null
+++ b/HIR-Activate/Form1.Designer.cs
@@ -0,0 +1,123 @@
+namespace HIR_Activate
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ label1 = new Label();
+ txtFilePath = new TextBox();
+ btn_select = new Button();
+ btn_activate = new Button();
+ label2 = new Label();
+ txtActivateFilePath = new TextBox();
+ SuspendLayout();
+ //
+ // label1
+ //
+ label1.AutoSize = true;
+ label1.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ label1.Location = new Point(12, 57);
+ label1.Name = "label1";
+ label1.Size = new Size(138, 21);
+ label1.TabIndex = 0;
+ label1.Text = "选择项目激活文件";
+ //
+ // txtFilePath
+ //
+ txtFilePath.Location = new Point(167, 55);
+ txtFilePath.Name = "txtFilePath";
+ txtFilePath.ReadOnly = true;
+ txtFilePath.Size = new Size(462, 23);
+ txtFilePath.TabIndex = 1;
+ //
+ // btn_select
+ //
+ btn_select.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ btn_select.Location = new Point(650, 49);
+ btn_select.Name = "btn_select";
+ btn_select.Size = new Size(100, 33);
+ btn_select.TabIndex = 2;
+ btn_select.Text = "选择";
+ btn_select.UseVisualStyleBackColor = true;
+ btn_select.Click += btn_select_Click;
+ //
+ // btn_activate
+ //
+ btn_activate.Font = new Font("Microsoft YaHei UI", 15F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ btn_activate.Location = new Point(230, 236);
+ btn_activate.Name = "btn_activate";
+ btn_activate.Size = new Size(307, 57);
+ btn_activate.TabIndex = 3;
+ btn_activate.Text = "生成激活文件";
+ btn_activate.UseVisualStyleBackColor = true;
+ btn_activate.Click += btn_activate_Click;
+ //
+ // label2
+ //
+ label2.AutoSize = true;
+ label2.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ label2.Location = new Point(12, 133);
+ label2.Name = "label2";
+ label2.Size = new Size(106, 21);
+ label2.TabIndex = 4;
+ label2.Text = "生成文件路径";
+ //
+ // txtActivateFilePath
+ //
+ txtActivateFilePath.Location = new Point(167, 131);
+ txtActivateFilePath.Name = "txtActivateFilePath";
+ txtActivateFilePath.ReadOnly = true;
+ txtActivateFilePath.Size = new Size(591, 23);
+ txtActivateFilePath.TabIndex = 5;
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(800, 542);
+ Controls.Add(txtActivateFilePath);
+ Controls.Add(label2);
+ Controls.Add(btn_activate);
+ Controls.Add(btn_select);
+ Controls.Add(txtFilePath);
+ Controls.Add(label1);
+ Name = "Form1";
+ Text = "HIR 激活码";
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label label1;
+ private TextBox txtFilePath;
+ private Button btn_select;
+ private Button btn_activate;
+ private Label label2;
+ private TextBox txtActivateFilePath;
+ }
+}
diff --git a/HIR-Activate/Form1.cs b/HIR-Activate/Form1.cs
new file mode 100644
index 0000000..5062b14
--- /dev/null
+++ b/HIR-Activate/Form1.cs
@@ -0,0 +1,218 @@
+using IRaCIS.Core.Infrastructure.Encryption;
+using Newtonsoft.Json;
+
+namespace HIR_Activate
+{
+ public partial class Form1 : Form
+ {
+ public Form1()
+ {
+ InitializeComponent();
+ }
+
+ private void btn_select_Click(object sender, EventArgs e)
+ {
+ using (OpenFileDialog openFileDialog = new OpenFileDialog())
+ {
+ openFileDialog.Filter = "Request Files (*.req)|*.req";
+ if (openFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ txtFilePath.Text = openFileDialog.FileName;
+ }
+ }
+ }
+
+ private void btn_activate_Click(object sender, EventArgs e)
+ {
+ string filePath = txtFilePath.Text;
+ var fileName=Path.GetFileNameWithoutExtension(filePath);
+ if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
+ {
+ MessageBox.Show("ѡһЧļ·", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ try
+ {
+ // ȡļ
+ string authorizationCode = File.ReadAllText(filePath);
+
+ // Base64
+ byte[] base64DecodedBytes = Convert.FromBase64String(authorizationCode);
+ string decodedText = System.Text.Encoding.UTF8.GetString(base64DecodedBytes);
+
+ var authorizationInfo = JsonConvert.DeserializeObject(decodedText);
+
+ if (authorizationInfo == null)
+ {
+ MessageBox.Show("ܽĿȨ룡", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
+
+ return;
+ }
+ else
+ {
+ //һڼ
+ authorizationInfo.ActiveDeadLineDate = DateTime.Now.Date.AddDays(8).AddSeconds(-1);
+
+ var licenseContent = AesEncryption.Encrypt($"{JsonConvert.SerializeObject(authorizationInfo)}", "HIR_System_AES_Key_Info", "Trial_AuthorizationEncrypt");
+
+ Console.WriteLine("HIR_System_AES_Key_Info".PadRight(32, '0').Substring(0, 32) + " " + "Trial_AuthorizationEncrypt".PadRight(16, '0').Substring(0, 16));
+
+ //var dd = AesEncryption.Decrypt(info, "HIR_System_AES_Key_Info", "Trial_AuthorizationEncrypt");
+
+ // ֤ļ
+ string licensePath = Path.Combine(Path.GetDirectoryName(filePath), $"{fileName}_Activation_Code.lic");
+ File.WriteAllText(licensePath, licenseContent);
+
+ txtActivateFilePath.Text = licensePath;
+
+ MessageBox.Show($"֤ɳɹ", "ɹ", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"֤ʧܣ{ex.Message}", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+
+ public class TrialAuthorizationInfo
+ {
+ public Guid TrialId { get; set; }
+ public Guid CreateUserId { get; set; }
+ public string TrialCode { get; set; }
+
+ public string HospitalName { get; set; }
+
+ public string HospitalCode { get; set; }
+
+ public int PurchaseDuration { get; set; }
+
+
+
+ public List CriterionTypeList { get; set; }
+
+ public DateTime? AuthorizationDeadLineDate { get; set; }
+
+ public DateTime? ActiveDeadLineDate { get; set; }
+
+ public DateTime? ActiveTime { get; set; }
+
+ }
+
+ ///
+ ///
+ ///
+ public enum CriterionType
+ {
+ NoCriterion = -1,
+
+ //Զ
+ SelfDefine = 0,
+
+ ///
+ /// RECIST 1.1
+ ///
+ RECIST1Point1 = 1,
+
+
+
+ ///
+ /// Lugano 2014
+ ///
+ Lugano2014 = 2,
+
+ ///
+ /// iRECIST1Point1
+ ///
+ IRECIST1Point1 = 3,
+
+ ///
+ /// RANO-BM
+ ///
+ RANO_BM = 4,
+
+ ///
+ /// RANO
+ ///
+ RANO = 5,
+
+ ///
+ /// IWCLL 2018
+ ///
+ IWCLL2018 = 6,
+
+ ///
+ /// mRECIST HCC
+ ///
+ mRECISTHCC = 7,
+
+ ///
+ /// Cheson 2007
+ ///
+ Cheson2007 = 8,
+
+ ///
+ /// IMWG 2016
+ ///
+ IMWG2016 = 9,
+
+ ///
+ /// PCWG3
+ ///
+ PCWG3 = 10,
+
+ ///
+ /// mRECIST Mesothelioma
+ ///
+ mRECISTMesothelioma = 11,
+
+ ///
+ /// RECIL
+ ///
+ RECIL = 12,
+
+ ///
+ /// RECIST 1.0
+ ///
+ RECIST1Point0 = 13,
+
+ ///
+ /// WHO
+ ///
+ WHO = 14,
+
+ ///
+ /// PERCIST
+ ///
+ PERCIST = 15,
+
+ ///
+ /// Forrest
+ ///
+ Forrest = 16,
+
+ ///
+ /// RECIST 1.1-BM
+ ///
+ RECIST1Pointt1_MB = 17,
+
+ ///
+ /// Lugano 2014 Without PET
+ ///
+ Lugano2014WithoutPET = 18,
+
+ ///
+ /// IVUS
+ ///
+ IVUS = 19,
+
+ ///
+ /// OCT
+ ///
+ OCT = 20,
+ }
+
+}
diff --git a/HIR-Activate/Form1.resx b/HIR-Activate/Form1.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/HIR-Activate/Form1.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/HIR-Activate/HIR-Activate.csproj b/HIR-Activate/HIR-Activate.csproj
new file mode 100644
index 0000000..079c726
--- /dev/null
+++ b/HIR-Activate/HIR-Activate.csproj
@@ -0,0 +1,17 @@
+
+
+
+ WinExe
+ net8.0-windows
+ HIR_Activate
+ enable
+ true
+ enable
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HIR-Activate/Program.cs b/HIR-Activate/Program.cs
new file mode 100644
index 0000000..fbb7fb8
--- /dev/null
+++ b/HIR-Activate/Program.cs
@@ -0,0 +1,17 @@
+namespace HIR_Activate
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new Form1());
+ }
+ }
+}
\ No newline at end of file