316 lines
11 KiB
C#
316 lines
11 KiB
C#
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
|
||
}
|
||
|
||
}
|