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 } }