From e1d81f6aee1afa3887c51a446825732c9499df6e Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Mon, 7 Apr 2025 22:28:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=88=E6=9D=83=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CapMachine.Wpf/App.xaml.cs | 22 + CapMachine.Wpf/CapMachine.Wpf.csproj | 6 + CapMachine.Wpf/Key/License.txt | 1 + CapMachine.Wpf/Key/PublicKey.xml | 1 + .../SoftAuthorizeCore/AuthorizeInfo.cs | 34 ++ .../SoftAuthorizeCore/LicenseClient.cs | 529 ++++++++++++++++++ .../SoftAuthorizeCore/LicenseServer.cs | 317 +++++++++++ .../SoftAuthorizeCore/SoftAuthorizeHelper.cs | 397 +++++++++++++ 8 files changed, 1307 insertions(+) create mode 100644 CapMachine.Wpf/Key/License.txt create mode 100644 CapMachine.Wpf/Key/PublicKey.xml create mode 100644 CapMachine.Wpf/SoftAuthorizeCore/AuthorizeInfo.cs create mode 100644 CapMachine.Wpf/SoftAuthorizeCore/LicenseClient.cs create mode 100644 CapMachine.Wpf/SoftAuthorizeCore/LicenseServer.cs create mode 100644 CapMachine.Wpf/SoftAuthorizeCore/SoftAuthorizeHelper.cs 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 + + + + } +} +