diff --git a/CapMachine.Wpf/App.xaml.cs b/CapMachine.Wpf/App.xaml.cs
index fd1991c..083e2bc 100644
--- a/CapMachine.Wpf/App.xaml.cs
+++ b/CapMachine.Wpf/App.xaml.cs
@@ -4,6 +4,7 @@ using CapMachine.Core.IService;
using CapMachine.Wpf.MapperProfile;
using CapMachine.Wpf.Models;
using CapMachine.Wpf.Services;
+using CapMachine.Wpf.SoftAuthorizeCore;
using CapMachine.Wpf.ViewModels;
using CapMachine.Wpf.Views;
using FreeSql;
@@ -33,6 +34,7 @@ namespace CapMachine.Wpf
private ILogService LogService { get; set; }
private static System.Threading.Mutex mutex;
+ private SoftAuthorizeHelper SoftAuthorizeHelper { get; set; } = SoftAuthorizeHelper.GetInstance();
public App()
{
@@ -83,6 +85,26 @@ namespace CapMachine.Wpf
this.Shutdown();
}
+
+ //验证文档
+ try
+ {
+ var MachineCode = SoftAuthorizeHelper.GetMachineCode();
+ SoftAuthorizeHelper.WriteMachineCodeToFile(MachineCode, "");
+ var PublicKey = SoftAuthorizeHelper.GetPublicKeyDataByFilePath("");
+ var Lience = SoftAuthorizeHelper.GetLienceDataByFilePath("");
+ var IsOK = SoftAuthorizeHelper.CheckLience(MachineCode, PublicKey, Lience);
+ if (!IsOK)
+ {
+ LogService.Error("授权失败");
+ this.Shutdown();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw;
+ }
+
//base.OnStartup(e);
}
diff --git a/CapMachine.Wpf/CapMachine.Wpf.csproj b/CapMachine.Wpf/CapMachine.Wpf.csproj
index 78cc039..601c025 100644
--- a/CapMachine.Wpf/CapMachine.Wpf.csproj
+++ b/CapMachine.Wpf/CapMachine.Wpf.csproj
@@ -738,6 +738,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/CapMachine.Wpf/Key/License.txt b/CapMachine.Wpf/Key/License.txt
new file mode 100644
index 0000000..1322558
--- /dev/null
+++ b/CapMachine.Wpf/Key/License.txt
@@ -0,0 +1 @@
+4YAnXbKQ4mYv98fudLHlX+v6Ch+bdIjCoBKjtVYjZE1iPTysc4+zSUmoGIOX9AVjgAAGb7PWhXmsi6uCFmqeIMCt36tI+wzc3DBLOZ1f7zMVV5NagnxTqAAEzx1bUjJq9RK7LKdEoyIJhlddzRMRyZbVgLkCpToHcCGslOuMV6zvcdY0qUpvGeQGvwD7OxEBMXeJu8JGXjlZBjcDAknRCgFSDCtuuEVnXKnE2GjaggpjuTiz7gnMtT2rvnIKSnh9F8IVRWt+Ypbc++WjJiSksePrMidnkvbKK7rAMuUDTbtuZv+7oupWhFHLVlXd7ZGs5lKlfX64kmjJbeVZDU7MD52bbKcnxLJ9JU/bzoPHXxZXhy3Md2N46ZRPC275EsNPMatk5NU/GmGVkzrNDJ0yfH02VTEgi2JQoSgZl+kIWjw72yFfL90vABPh//HmYEYbelvc+K1VArJjgRNh0mpZ6qpK
diff --git a/CapMachine.Wpf/Key/PublicKey.xml b/CapMachine.Wpf/Key/PublicKey.xml
new file mode 100644
index 0000000..e996864
--- /dev/null
+++ b/CapMachine.Wpf/Key/PublicKey.xml
@@ -0,0 +1 @@
+2avWQrPnade3HmX7dGML8n/YD5aTA3C7hhaFRETpBiV8/KEQnG6M0If2WgTiUNAyFjXI6cYUro8Q1NDy6PSmqgoQbCDyMGiT22K9DlMdcBC3SSot+pA+Wr9A1tOnuyQibFi43BFL1ZBgsn39rNbklUehncrZbyT7Rnl+q3jxYyE=AQAB
diff --git a/CapMachine.Wpf/SoftAuthorizeCore/AuthorizeInfo.cs b/CapMachine.Wpf/SoftAuthorizeCore/AuthorizeInfo.cs
new file mode 100644
index 0000000..0e2680a
--- /dev/null
+++ b/CapMachine.Wpf/SoftAuthorizeCore/AuthorizeInfo.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.SoftAuthorizeCore
+{
+ ///
+ /// 授权信息
+ ///
+ public class AuthorizeInfo
+ {
+ ///
+ /// 开始时间
+ ///
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 最近登录时间
+ ///
+ public DateTime LastTime { get; set; }
+
+ ///
+ /// 机器码 序列号
+ ///
+ public string MachineCode { get; set; }
+ }
+}
diff --git a/CapMachine.Wpf/SoftAuthorizeCore/LicenseClient.cs b/CapMachine.Wpf/SoftAuthorizeCore/LicenseClient.cs
new file mode 100644
index 0000000..dfb158f
--- /dev/null
+++ b/CapMachine.Wpf/SoftAuthorizeCore/LicenseClient.cs
@@ -0,0 +1,529 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.SoftAuthorizeCore
+{
+ ///
+ /// Lience客户端
+ ///
+ public class LicenseClient
+ {
+ ///
+ /// 根据硬件信息生成机器序列号
+ ///
+ ///
+ public static string GenSerialNo()
+ {
+ try
+ {
+ //获取硬件信息
+ string info = string.Empty;
+ string cpu = GetCPUInfo();
+ string gpu = GetGPUInfo();
+ string baseBoard = GetBaseBoardInfo();
+ string bios = GetBIOSInfo();
+ string mac = GetMACInfo();
+ info = string.Concat(cpu, gpu, baseBoard, bios, mac);
+
+ //AES加密
+ using (Aes tempAES = Aes.Create())
+ {
+ byte[] encrypted = EncryptStringToBytes(info, tempAES.Key, tempAES.IV);
+ byte[] dataCnt = BitConverter.GetBytes(Convert.ToInt16(encrypted.Length));
+
+ byte[] res = new byte[tempAES.Key.Length
+ + tempAES.IV.Length
+ + dataCnt.Length
+ + encrypted.Length];
+
+ //拼接AES密钥 32+16 bytes
+ Buffer.BlockCopy(tempAES.Key, 0, res, 0, tempAES.Key.Length);
+ Buffer.BlockCopy(tempAES.IV, 0, res, tempAES.Key.Length, tempAES.IV.Length);
+ //拼接加密数据
+ Buffer.BlockCopy(dataCnt, 0, res, tempAES.Key.Length + tempAES.IV.Length, dataCnt.Length);
+ Buffer.BlockCopy(encrypted, 0, res, tempAES.Key.Length + tempAES.IV.Length + dataCnt.Length, encrypted.Length);
+
+ //生成机器序列号
+ info = Convert.ToBase64String(res);
+ }
+ return info;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ }
+
+ ///
+ /// 校验授权文件
+ ///
+ ///
+ ///
+ ///
+ public static bool VerifyLicense(string license, string publicKey)
+ {
+ try
+ {
+ byte[] lic = Convert.FromBase64String(license);
+
+ //获取AES密钥信息
+ byte[] aesKey = lic.Skip(0).Take(32).ToArray();
+ byte[] aesIV = lic.Skip(32).Take(16).ToArray();
+
+ //获取加密数据长度
+ int dataCnt = BitConverter.ToInt16(lic, 48);
+
+ //获取加密数据
+ byte[] data = lic.Skip(50).Take(dataCnt).ToArray();
+
+ //获取签名
+ byte[] sign = lic.Skip(50 + dataCnt).Take(128).ToArray();
+ string signStr = Convert.ToBase64String(sign);
+ //Console.WriteLine("get sign: " + signStr);
+
+ //获取时间
+ byte[] times = lic.Skip(48 + 2 + dataCnt + 128).ToArray();
+ string[] timeStrs = DecryptStringFromBytes(times, aesKey, aesIV).Split('|');
+ //byte[] start = lic.Skip(50 + dataCnt+128).Take(8).ToArray();
+ //byte[] end = lic.Skip(50 + dataCnt + 128+8).Take(8).ToArray();
+ //byte[] last = lic.Skip(50 + dataCnt + 128+16).Take(8).ToArray();
+
+
+ //获取签名的对象
+ byte[] sn = lic.Skip(0).Take(50 + dataCnt).ToArray();
+ string snStr = Convert.ToBase64String(sn);
+ //Console.WriteLine("get sn: " + snStr);
+
+ //验签
+ if (VerifySign(snStr, signStr, publicKey) == false)
+ return false;
+
+ //校验机器序列号
+ if (CheckHardware(snStr, aesKey, aesIV) == false)
+ return false;
+
+ //校验授权时间
+ if (CheckTime(timeStrs[0], timeStrs[1], timeStrs[2]) == false)
+ return false;
+
+ return true;
+ }
+ catch (Exception)
+ {
+
+ return false;
+ }
+
+ }
+
+
+
+ ///
+ /// 更新登录时间
+ ///
+ ///
+ ///
+ ///
+ public static bool UpdateVerifyTime(string license, string path)
+ {
+ try
+ {
+ byte[] lic = Convert.FromBase64String(license);
+
+ byte[] now = BitConverter.GetBytes(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds());
+ int dataCnt = BitConverter.ToInt16(lic, 48);
+ byte[] aesKey = lic.Skip(0).Take(32).ToArray();
+ byte[] aesIV = lic.Skip(32).Take(16).ToArray();
+ byte[] times = lic.Skip(48 + 2 + dataCnt + 128).ToArray();
+ string[] timeStr = DecryptStringFromBytes(times, aesKey, aesIV).Split('|');
+
+ long nowTime = BitConverter.ToInt64(now, 0);
+ long lastTime = Convert.ToInt64(timeStr[2]);
+
+ //时间只能递增
+ if (lastTime >= nowTime)
+ return true;
+
+
+ timeStr[2] = nowTime.ToString();
+ byte[] newtimes = EncryptStringToBytes(timeStr[0] + "|" + timeStr[1] + "|" + timeStr[2], aesKey, aesIV);
+ byte[] newlic = new byte[48 + 2 + dataCnt + 128 + newtimes.Length];
+ Buffer.BlockCopy(lic, 0, newlic, 0, 48 + 2 + dataCnt + 128);
+ Buffer.BlockCopy(newtimes, 0, newlic, 48 + 2 + dataCnt + 128, newtimes.Length);
+
+ license = Convert.ToBase64String(newlic);
+ using (StreamWriter writer = new StreamWriter(path))
+ {
+ writer.WriteLine(license);
+ }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ }
+
+
+
+ #region private methods
+
+ ///
+ /// 检查硬件信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static bool CheckHardware(string sn, byte[] key, byte[] Iv)
+ {
+ //获取硬件信息
+ string info = string.Empty;
+ string cpu = GetCPUInfo();
+ string gpu = GetGPUInfo();
+ string baseBoard = GetBaseBoardInfo();
+ string bios = GetBIOSInfo();
+ string mac = GetMACInfo();
+ info = string.Concat(cpu, gpu, baseBoard, bios, mac);
+
+ //AES加密
+ byte[] encrypted = EncryptStringToBytes(info, key, Iv);
+ byte[] dataCnt = BitConverter.GetBytes(Convert.ToInt16(encrypted.Length));
+
+ byte[] res = new byte[key.Length
+ + Iv.Length
+ + dataCnt.Length
+ + encrypted.Length];
+
+ //拼接AES密钥 32+16 bytes
+ Buffer.BlockCopy(key, 0, res, 0, key.Length);
+ Buffer.BlockCopy(Iv, 0, res, key.Length, Iv.Length);
+ //拼接加密数据
+ Buffer.BlockCopy(dataCnt, 0, res, key.Length + Iv.Length, dataCnt.Length);
+ Buffer.BlockCopy(encrypted, 0, res, key.Length + Iv.Length + dataCnt.Length, encrypted.Length);
+
+ //生成机器序列号
+ info = Convert.ToBase64String(res);
+
+ if (info != sn)
+ return false;
+ return true;
+ }
+
+
+ ///
+ /// 检查授权时间
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static bool CheckTime(string startTime, string endTime, string lastTime)
+ {
+ long now = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
+ long start = Convert.ToInt64(startTime);
+ long end = Convert.ToInt64(endTime);
+ long last = Convert.ToInt64(lastTime);
+
+ if (end <= start)
+ return false;
+ if (now < start || now >= end)
+ return false;
+ if (now <= last)
+ return false;
+
+ return true;
+ }
+
+
+
+ ///
+ /// 最大解密长度
+ ///
+ private const int MAX_DECRYPT_BLOCK = 256;
+
+
+ ///
+ /// 公钥解密
+ ///
+ ///
+ ///
+ ///
+ private static string Decrypt(string xmlPublicKey, string content)
+ {
+ //加载公钥
+ RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();
+ publicRsa.FromXmlString(xmlPublicKey);
+ RSAParameters rp = publicRsa.ExportParameters(false);
+
+ //转换密钥
+ AsymmetricKeyParameter pbk = DotNetUtilities.GetRsaPublicKey(rp);
+
+ IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
+ //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
+ c.Init(false, pbk);
+
+ byte[] DataToDecrypt = Convert.FromBase64String(content);
+
+ byte[] cache;
+ int time = 0;//次数
+ int inputLen = DataToDecrypt.Length;
+ int offSet = 0;
+ MemoryStream outStream = new MemoryStream();
+ while (inputLen - offSet > 0)
+ {
+ if (inputLen - offSet > MAX_DECRYPT_BLOCK)
+ {
+ cache = c.DoFinal(DataToDecrypt, offSet, MAX_DECRYPT_BLOCK);
+ }
+ else
+ {
+ cache = c.DoFinal(DataToDecrypt, offSet, inputLen - offSet);
+ }
+ //写入
+ outStream.Write(cache, 0, cache.Length);
+
+ time++;
+ offSet = time * MAX_DECRYPT_BLOCK;
+ }
+ byte[] resData = outStream.ToArray();
+
+ string strDec = Encoding.UTF8.GetString(resData);
+ return strDec;
+
+ }
+
+
+ ///
+ /// 公钥验签
+ ///
+ /// 待验证的字符串
+ /// 加签之后的字符串
+ /// 签名是否符合
+ private static bool VerifySign(string str, string sign, string publicKey)
+ {
+
+ byte[] bt = Convert.FromBase64String(str);
+ byte[] rgbHash = null;
+
+ var csp = new SHA256CryptoServiceProvider();
+ rgbHash = csp.ComputeHash(bt);
+
+ RSACryptoServiceProvider key = new RSACryptoServiceProvider();
+ key.FromXmlString(publicKey);
+ RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
+ deformatter.SetHashAlgorithm("SHA256");
+ byte[] rgbSignature = Convert.FromBase64String(sign);
+ if (deformatter.VerifySignature(rgbHash, rgbSignature))
+ return true;
+ return false;
+ }
+
+
+ ///
+ /// AES加密
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (plainText == null || plainText.Length <= 0)
+ throw new ArgumentNullException("plainText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+ byte[] encrypted;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create an encryptor to perform the stream transform.
+ ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for encryption.
+ using (MemoryStream msEncrypt = new MemoryStream())
+ {
+ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+ {
+ using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
+ {
+ //Write all data to the stream.
+ swEncrypt.Write(plainText);
+ }
+ encrypted = msEncrypt.ToArray();
+ }
+ }
+ }
+
+ // Return the encrypted bytes from the memory stream.
+ return encrypted;
+ }
+
+
+
+
+ ///
+ /// AES解密
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (cipherText == null || cipherText.Length <= 0)
+ throw new ArgumentNullException("cipherText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+
+ // Declare the string used to hold
+ // the decrypted text.
+ string plaintext = null;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create a decryptor to perform the stream transform.
+ ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for decryption.
+ using (MemoryStream msDecrypt = new MemoryStream(cipherText))
+ {
+ using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ {
+ using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+ {
+
+ // Read the decrypted bytes from the decrypting stream
+ // and place them in a string.
+ plaintext = srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ }
+
+ return plaintext;
+ }
+
+
+
+ ///
+ /// 获取CPU序列号
+ ///
+ ///
+ private static string GetCPUInfo()
+ {
+ var info = string.Empty;
+ var mc = new ManagementClass("Win32_Processor");
+ var moc = mc.GetInstances();
+ foreach (var o in moc)
+ {
+ var mo = (ManagementObject)o;
+ info = mo.Properties["ProcessorId"].Value.ToString();
+ }
+ return info;
+ }
+
+ ///
+ /// 获取显卡序列号
+ ///
+ ///
+ private static string GetGPUInfo()
+ {
+ var info = "";
+ var mos = new ManagementObjectSearcher("Select * from Win32_VideoController");
+ foreach (var o in mos.Get())
+ {
+ var mo = (ManagementObject)o;
+ info = mo["PNPDeviceID"].ToString();
+ }
+ return info;
+ }
+
+ ///
+ /// 获取主板序列号
+ ///
+ ///
+ private static string GetBaseBoardInfo()
+ {
+ var info = string.Empty;
+ var mos = new ManagementObjectSearcher("Select * from Win32_BaseBoard");
+ foreach (var o in mos.Get())
+ {
+ var mo = (ManagementObject)o;
+ info = mo["SerialNumber"].ToString();
+ }
+ return info;
+ }
+
+ ///
+ /// 获取BIOS序列号
+ ///
+ ///
+ private static string GetBIOSInfo()
+ {
+ var info = string.Empty;
+ var mos = new ManagementObjectSearcher("Select * from Win32_BIOS");
+ foreach (var o in mos.Get())
+ {
+ var mo = (ManagementObject)o;
+ info = mo["SerialNumber"].ToString();
+ }
+ return info;
+ }
+
+
+ ///
+ /// 获取MAC地址
+ ///
+ ///
+ private static string GetMACInfo()
+ {
+ var info = string.Empty;
+ var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
+ var moc = mc.GetInstances();
+ foreach (var o in moc)
+ {
+ var mo = (ManagementObject)o;
+ if (!(bool)mo["IPEnabled"]) continue;
+ info = mo["MacAddress"].ToString();
+ break;
+ }
+ return info;
+ }
+
+ #endregion
+
+
+ }
+}
+
+
diff --git a/CapMachine.Wpf/SoftAuthorizeCore/LicenseServer.cs b/CapMachine.Wpf/SoftAuthorizeCore/LicenseServer.cs
new file mode 100644
index 0000000..2d63800
--- /dev/null
+++ b/CapMachine.Wpf/SoftAuthorizeCore/LicenseServer.cs
@@ -0,0 +1,317 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.SoftAuthorizeCore
+{
+ ///
+ /// LienceServer
+ ///
+ public class LicenseServer
+ {
+ ///
+ /// 生成公钥和私钥(xml)
+ ///
+ public static string[] GenXmlKey()
+ {
+ try
+ {
+ using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
+ {
+ string publicKey = rsa.ToXmlString(false); // 公钥
+ string privateKey = rsa.ToXmlString(true); // 私钥
+
+ return new string[] { publicKey, privateKey };
+ }
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ }
+
+
+
+ ///
+ /// 根据机器序列号生成授权License
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string GenLicense(string SerialNo, string privateKey, long startTime, long endTime)
+ {
+ try
+ {
+ //生成序列号签名
+ byte[] sign = Sign(SerialNo, privateKey);
+
+ //签名
+ byte[] sn = Convert.FromBase64String(SerialNo);
+
+ //AES加密授权时间
+ byte[] aesKey = sn.Skip(0).Take(32).ToArray();
+ byte[] aesIV = sn.Skip(32).Take(16).ToArray();
+ byte[] time = EncryptStringToBytes(startTime.ToString() + "|" + endTime.ToString() + "|" + startTime.ToString(), aesKey, aesIV);
+
+ //序列号 + 序列号签名 + 授权时间
+ byte[] lic = new byte[sn.Length + sign.Length + time.Length];
+ Buffer.BlockCopy(sn, 0, lic, 0, sn.Length);
+ Buffer.BlockCopy(sign, 0, lic, sn.Length, sign.Length);
+ Buffer.BlockCopy(time, 0, lic, sn.Length + sign.Length, time.Length);
+
+ //生成License
+ string license = string.Empty;
+ license = Convert.ToBase64String(lic);
+ return license;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ }
+
+
+
+
+ ///
+ /// 获取license的详细信息,包括机器序列号和授权时间
+ ///
+ ///
+ ///
+ public static string[] GetLicenseDetail(string license)
+ {
+ try
+ {
+ byte[] lic = Convert.FromBase64String(license);
+
+ //获取加密数据长度
+ int dataCnt = BitConverter.ToInt16(lic, 48);
+
+ //获取机器码
+ byte[] sn = lic.Skip(0).Take(50 + dataCnt).ToArray();
+
+ //获取时间
+ byte[] aesKey = sn.Skip(0).Take(32).ToArray();
+ byte[] aesIV = sn.Skip(32).Take(16).ToArray();
+ byte[] times = lic.Skip(48 + 2 + dataCnt + 128).ToArray();
+ string[] timeStr = DecryptStringFromBytes(times, aesKey, aesIV).Split('|');
+
+
+ //依次返回机器码和三个时间
+ return new string[]
+ {
+ Convert.ToBase64String(sn),
+ timeStr[0],
+ timeStr[1],
+ timeStr[2]
+ };
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+
+
+ #region private methods
+
+ ///
+ /// 最大加密长度
+ ///
+ private const int MAX_ENCRYPT_BLOCK = 245;
+
+
+ ///
+ /// 用私钥进行RSA加密
+ ///
+ /// 私钥(XML格式字符串)
+ /// 要加密的数据
+ /// 加密后的数据
+ private static string Encrypt(string xmlPrivateKey, string content)
+ {
+ //加载私钥
+ RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();
+ privateRsa.FromXmlString(xmlPrivateKey);
+
+ //转换密钥
+ AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);
+ IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding"); //使用RSA/ECB/PKCS1Padding格式
+
+ c.Init(true, keyPair.Private);//第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
+ byte[] dataToEncrypt = Encoding.UTF8.GetBytes(content);//获取字节
+
+ byte[] cache;
+ int time = 0;//次数
+ int inputLen = dataToEncrypt.Length;
+ int offSet = 0;
+
+ MemoryStream outStream = new MemoryStream();
+ while (inputLen - offSet > 0)
+ {
+ if (inputLen - offSet > MAX_ENCRYPT_BLOCK)
+ {
+ cache = c.DoFinal(dataToEncrypt, offSet, MAX_ENCRYPT_BLOCK);
+ }
+ else
+ {
+ cache = c.DoFinal(dataToEncrypt, offSet, inputLen - offSet);
+ }
+ //写入
+ outStream.Write(cache, 0, cache.Length);
+
+ time++;
+ offSet = time * MAX_ENCRYPT_BLOCK;
+ }
+
+ byte[] resData = outStream.ToArray();
+
+ string strBase64 = Convert.ToBase64String(resData);
+ outStream.Close();
+ return strBase64;
+ }
+
+
+ ///
+ /// 签名
+ ///
+ /// 需签名的数据
+ /// 签名后的值
+ private static byte[] Sign(string str, string privateKey)
+ {
+ //根据需要加签时的哈希算法转化成对应的hash字符节
+ byte[] bt = Convert.FromBase64String(str);
+ byte[] rgbHash = null;
+
+ //SHA256
+ var csp = new SHA256CryptoServiceProvider();
+ rgbHash = csp.ComputeHash(bt);
+
+ RSACryptoServiceProvider key = new RSACryptoServiceProvider();
+ key.FromXmlString(privateKey);
+ RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
+ //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
+ formatter.SetHashAlgorithm("SHA256");
+ byte[] inArray = formatter.CreateSignature(rgbHash);
+
+ return inArray;
+ }
+
+
+ ///
+ /// AES加密
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (plainText == null || plainText.Length <= 0)
+ throw new ArgumentNullException("plainText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+ byte[] encrypted;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create an encryptor to perform the stream transform.
+ ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for encryption.
+ using (MemoryStream msEncrypt = new MemoryStream())
+ {
+ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+ {
+ using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
+ {
+ //Write all data to the stream.
+ swEncrypt.Write(plainText);
+ }
+ encrypted = msEncrypt.ToArray();
+ }
+ }
+ }
+
+ // Return the encrypted bytes from the memory stream.
+ return encrypted;
+ }
+
+
+
+
+ ///
+ /// AES解密
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (cipherText == null || cipherText.Length <= 0)
+ throw new ArgumentNullException("cipherText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+
+ // Declare the string used to hold
+ // the decrypted text.
+ string plaintext = null;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create a decryptor to perform the stream transform.
+ ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for decryption.
+ using (MemoryStream msDecrypt = new MemoryStream(cipherText))
+ {
+ using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ {
+ using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+ {
+
+ // Read the decrypted bytes from the decrypting stream
+ // and place them in a string.
+ plaintext = srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ }
+
+ return plaintext;
+ }
+
+ #endregion
+ }
+
+}
+
+
diff --git a/CapMachine.Wpf/SoftAuthorizeCore/SoftAuthorizeHelper.cs b/CapMachine.Wpf/SoftAuthorizeCore/SoftAuthorizeHelper.cs
new file mode 100644
index 0000000..17614e9
--- /dev/null
+++ b/CapMachine.Wpf/SoftAuthorizeCore/SoftAuthorizeHelper.cs
@@ -0,0 +1,397 @@
+using HslCommunication.BasicFramework;
+using HslCommunication;
+using HslCommunication.Profinet.Melsec;
+using HslCommunication.Profinet.Siemens;
+using System.IO;
+using System.Windows.Forms;
+using SixLabors.ImageSharp.Drawing;
+using System.ComponentModel;
+using System.Security.Cryptography.X509Certificates;
+using System.Windows.Documents;
+using SharpCompress.Common;
+
+namespace CapMachine.Wpf.SoftAuthorizeCore
+{
+ ///
+ /// 程序的软授权
+ ///
+ public class SoftAuthorizeHelper
+ {
+ //private HslCommunication.BasicFramework.SoftAuthorize softAuthorize = null;
+
+ // 定义一个静态变量来保存类的实例
+ private static SoftAuthorizeHelper Instance;
+
+ ///
+ /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
+ ///
+ ///
+ public static SoftAuthorizeHelper GetInstance()
+ {
+ // 如果类的实例不存在则创建,否则直接返回
+ if (Instance == null)
+ {
+ Instance = new SoftAuthorizeHelper();
+ }
+ return Instance;
+ }
+
+
+ ///
+ /// 初始化
+ ///
+ public void Init()
+ {
+ // 或者使用类型的完全限定名
+
+
+ }
+
+
+ ///
+ /// 获取机器码
+ ///
+ ///
+ public string GetMachineCode()
+ {
+ return LicenseClient.GenSerialNo();
+ }
+
+ ///
+ /// 写机器码到指定的文件中
+ ///
+ ///
+ /// 路径
+ ///
+ public bool WriteMachineCodeToFile(string MachineCode, string TxtFilePath)
+ {
+ //暂时是固定的
+ TxtFilePath = MachineCodePath;
+
+ // 参数验证
+ if (string.IsNullOrEmpty(MachineCode) || string.IsNullOrEmpty(TxtFilePath))
+ {
+ return false;
+ }
+
+ try
+ {
+ // 确保目录存在
+ string directoryPath = System.IO.Path.GetDirectoryName(TxtFilePath);
+ if (!Directory.Exists(directoryPath))
+ {
+ Directory.CreateDirectory(directoryPath);
+ }
+
+ // 写入文件
+ using (StreamWriter writer = new StreamWriter(TxtFilePath))
+ {
+ writer.WriteLine(MachineCode);
+ }
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+
+ ///
+ /// Key文件的存放路径
+ ///
+ private string KeyFile { get; set; } = System.AppDomain.CurrentDomain.BaseDirectory + @"Key";
+
+ ///
+ /// Lience文件的存放路径
+ ///
+ private string LiencePath { get; set; } = System.AppDomain.CurrentDomain.BaseDirectory + @"Key\License.txt";
+
+ ///
+ /// 机器码文件的存放路径
+ ///
+ private string MachineCodePath { get; set; } = System.AppDomain.CurrentDomain.BaseDirectory + @"Key\MachineCode.txt";
+
+ ///
+ /// 当前的授权信息
+ ///
+ public AuthorizeInfo CurAuthorizeInfo { get; set; } = new AuthorizeInfo();
+
+ ///
+ /// 获取Xml Key 文件
+ ///
+ public void GetXmlKey()
+ {
+ var key = LicenseServer.GenXmlKey();
+ if (key == null)
+ {
+ //MessageBox.Show("生成密钥失败!", "提示");
+ return;
+ }
+
+ try
+ {
+ ////写入文件
+ //using (FolderBrowserDialog dialog = new FolderBrowserDialog())
+ //{
+ // if (dialog.ShowDialog() == DialogResult.OK)
+ // {
+
+ string savePath = KeyFile;
+ using (StreamWriter writer = new StreamWriter(System.IO.Path.Combine(savePath, "PublicKey.xml")))
+ {
+ writer.WriteLine(key[0]);
+ }
+ using (StreamWriter writer = new StreamWriter(System.IO.Path.Combine(savePath, "PrivateKey.xml")))
+ {
+ writer.WriteLine(key[1]);
+ }
+
+ // }
+ // else
+ // return;
+ //}
+ }
+ catch (Exception)
+ {
+
+ MessageBox.Show("保存密钥失败!", "提示");
+ }
+
+ }
+
+ ///
+ /// 授权检验
+ /// 需要:
+ /// 1)机器码
+ /// 2)公钥
+ /// 3)授权文件
+ ///
+ ///
+ public bool CheckLience(string MachineCode, string PublicKey, string Lience)
+ {
+ //授权测试需要 机器序列号+公钥
+ if (MachineCode == string.Empty)
+ {
+ //MessageBox.Show("授权测试需要目标机器的序列号!", "提示");
+ return false;
+ }
+ if (PublicKey == string.Empty)
+ {
+ //MessageBox.Show("授权测试需要使用公钥!", "提示");
+ return false;
+ }
+
+ //无论授权是否通过,都更新校验时间
+ if (LicenseClient.VerifyLicense(Lience, PublicKey) == false)
+ {
+ LicenseClient.UpdateVerifyTime(Lience, LiencePath);
+ //MessageBox.Show("授权文件无效!", "提示");
+ return false;
+
+ }
+ else
+ {
+ LicenseClient.UpdateVerifyTime(Lience, LiencePath);
+ //MessageBox.Show("授权文件有效!", "提示");
+ return true;
+ }
+ }
+
+
+ ///
+ /// 获取公匙详细信息
+ ///
+ ///
+ public string GetPublicKeyDataByFilePath(string Path)
+ {
+ try
+ {
+ //using (OpenFileDialog dialog = new OpenFileDialog())
+ //{
+ // if (dialog.ShowDialog() == DialogResult.OK)
+ // {
+
+ //string filePath = dialog.FileName;
+
+ var filePath = KeyFile + @"\PublicKey.xml";
+
+ using (StreamReader reader = new StreamReader(filePath))
+ {
+ return reader.ReadToEnd();
+ }
+
+ // }
+ //}
+ }
+ catch (Exception)
+ {
+ return "";
+ //MessageBox.Show("配置公钥失败!", "提示");
+ }
+ }
+
+ ///
+ /// 获取授权文件详细信息
+ ///
+ ///
+ ///
+ public string GetLienceDataByFilePath(string Path)
+ {
+ try
+ {
+ //using (OpenFileDialog dialog = new OpenFileDialog())
+ //{
+ // if (dialog.ShowDialog() == DialogResult.OK)
+ // {
+
+ //string filePath = dialog.FileName;
+
+ var filePath = KeyFile + @"\License.txt";
+
+ using (StreamReader reader = new StreamReader(filePath))
+ {
+ return reader.ReadToEnd();
+ }
+
+ // }
+ //}
+ }
+ catch (Exception)
+ {
+ return "";
+ //MessageBox.Show("配置公钥失败!", "提示");
+ }
+ }
+
+ ///
+ /// 加载授权文件
+ ///
+ public AuthorizeInfo LoadLienceFile(string LiencePath)
+ {
+ try
+ {
+ //using (OpenFileDialog dialog = new OpenFileDialog())
+ //{
+ // if (dialog.ShowDialog() == DialogResult.OK)
+ // {
+
+ //string filePath = dialog.FileName;
+ //licPath = filePath;
+
+ var LienceData = "";
+ AuthorizeInfo authorizeInfo = new AuthorizeInfo();
+
+ using (StreamReader reader = new StreamReader(LiencePath))
+ {
+ //显示授权码
+ LienceData = reader.ReadToEnd();
+
+ //显示机器码和时间
+ var strs = LicenseServer.GetLicenseDetail(LienceData);
+ if (strs == null)
+ return null;
+
+ try
+ {
+ authorizeInfo.MachineCode = strs[0];
+
+ //北京为东8区,比UTC快8小时,转换时要加上这8小时
+ authorizeInfo.StartTime = new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(Convert.ToInt64(strs[1]));
+ authorizeInfo.EndTime = new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(Convert.ToInt64(strs[2]));
+ authorizeInfo.LastTime = new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(Convert.ToInt64(strs[3]));
+
+ return authorizeInfo;
+
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("授权文件无效!", "提示");
+ return null;
+ }
+ }
+
+ // }
+ //}
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("加载授权文件失败!", "提示");
+ return null;
+ }
+ }
+
+
+ #region 生成Lience文件
+
+ ///
+ /// 生成Lience文件
+ /// 生成授权文件需要:机器序列号(用户提供)+私钥(自己保密信息)+授权时间(自己控制信息)
+ ///
+ ///
+ public string GetLience(string MachineCode, string PrivateKey, DateTime startTime, DateTime endTime)
+ {
+ //生成授权文件需要:机器序列号+私钥+授权时间
+ if (MachineCode == string.Empty)
+ {
+ MessageBox.Show("生成授权文件需要目标机器的序列号!", "提示");
+ return "";
+ }
+ if (PrivateKey == string.Empty)
+ {
+ MessageBox.Show("生成授权文件需要使用私钥!", "提示");
+ return "";
+ }
+
+ //new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString();
+ long start = new DateTimeOffset(startTime).ToUnixTimeSeconds();
+ long end = new DateTimeOffset(endTime).ToUnixTimeSeconds();
+ if (end <= start)
+ {
+ MessageBox.Show("授权的终止时间必须大于起始时间!", "提示");
+ return "";
+ }
+
+ string lic = string.Empty;
+
+ lic = LicenseServer.GenLicense(MachineCode, PrivateKey, start, end);
+ if (lic == null)
+ {
+ MessageBox.Show("生成授权文件失败!", "提示");
+ return "";
+ }
+
+ return lic;
+
+ //try
+ //{
+ // using (FolderBrowserDialog dialog = new FolderBrowserDialog())
+ // {
+ // if (dialog.ShowDialog() == DialogResult.OK)
+ // {
+ // string savePath = dialog.SelectedPath;
+ // using (StreamWriter writer = new StreamWriter(Path.Combine(savePath, "License.txt")))
+ // {
+ // writer.WriteLine(lic);
+ // }
+ // licPath = Path.Combine(savePath, "License.txt");
+ // }
+ // }
+ //}
+ //catch (Exception)
+ //{
+ // MessageBox.Show("保存授权文件失败!", "提示");
+ // return;
+ //}
+
+ //licence = lic;
+ //tbLic.Text = lic;
+ }
+
+ #endregion
+
+
+
+ }
+}
+