Files
CapMachine/CapMachine.Wpf/SoftAuthorizeCore/LicenseClient.cs

528 lines
18 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// Lience客户端
/// </summary>
public class LicenseClient
{
/// <summary>
/// 根据硬件信息生成机器序列号
/// </summary>
/// <returns></returns>
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;
}
}
/// <summary>
/// 校验授权文件
/// </summary>
/// <param name="license"></param>
/// <param name="publicKey"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 更新登录时间
/// </summary>
/// <param name="license"></param>
/// <param name="path"></param>
/// <returns></returns>
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
/// <summary>
/// 检查硬件信息
/// </summary>
/// <param name="sn"></param>
/// <param name="key"></param>
/// <param name="Iv"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 检查授权时间
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="last"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 最大解密长度
/// </summary>
private const int MAX_DECRYPT_BLOCK = 256;
/// <summary>
/// 公钥解密
/// </summary>
/// <param name="xmlPublicKey"></param>
/// <param name="content"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 公钥验签
/// </summary>
/// <param name="str">待验证的字符串</param>
/// <param name="sign">加签之后的字符串</param>
/// <returns>签名是否符合</returns>
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;
}
/// <summary>
/// AES加密
/// </summary>
/// <param name="plainText"></param>
/// <param name="Key"></param>
/// <param name="IV"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
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;
}
/// <summary>
/// AES解密
/// </summary>
/// <param name="cipherText"></param>
/// <param name="Key"></param>
/// <param name="IV"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
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;
}
/// <summary>
/// 获取CPU序列号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取显卡序列号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取主板序列号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取BIOS序列号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取MAC地址
/// </summary>
/// <returns></returns>
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
}
}