Files
CapMachine/CapMachine.Wpf/SoftAuthorizeCore/LicenseServer.cs
2025-05-13 14:35:58 +08:00

316 lines
11 KiB
C#
Raw 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.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.SoftAuthorizeCore
{
/// <summary>
/// LienceServer
/// </summary>
public class LicenseServer
{
/// <summary>
/// 生成公钥和私钥xml
/// </summary>
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;
}
}
/// <summary>
/// 根据机器序列号生成授权License
/// </summary>
/// <param name="SerialNo"></param>
/// <param name="privateKey"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 获取license的详细信息包括机器序列号和授权时间
/// </summary>
/// <param name="license"></param>
/// <returns></returns>
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
/// <summary>
/// 最大加密长度
/// </summary>
private const int MAX_ENCRYPT_BLOCK = 245;
/// <summary>
/// 用私钥进行RSA加密
/// </summary>
/// <param name="xmlPrivateKey"> 私钥(XML格式字符串)</param>
/// <param name="content">要加密的数据</param>
/// <returns> 加密后的数据 </returns>
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;
}
/// <summary>
/// 签名
/// </summary>
/// <param name="str">需签名的数据</param>
/// <returns>签名后的值</returns>
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;
}
/// <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;
}
#endregion
}
}