C#软件license管理(简单软件注册机制)

 

最近做了一个绿色免安装软件,领导临时要求加个注册机制,不能让现场工程师随意复制。事出突然,只能在现场开发(离开现场软件就不受我们控了)。花了不到两个小时实现了简单的注册机制,稍作整理。
        基本原理:1.软件一运行就把计算机的CPU、主板、BIOS、MAC地址记录下来,然后加密(key=key1)生成文件;2.注册机将该文件内容MD5加密后再进行一次加密(key=key2)保存成注册文件;3.注册验证的逻辑,计算机信息加密后(key=key1)加密md5==注册文件解密(key=key2);
另外,采用ConfuserEx将可执行文件加密;这样别人要破解也就需要点力气了(没打算防破解,本意只想防复制的),有能力破解的人也不在乎破解这个软件了(开发这个软件前后只花了一周时间而已);

        技术上主要三个模块:1.获取电脑相关硬件信息(可参考);2.加密解密;3.读写文件;

        1.获取电脑相关硬件信息代码:

 

  1. public class ComputerInfo  
  2. {  
  3.     public static string GetComputerInfo()  
  4.     {  
  5.         string info = string.Empty;  
  6.         string cpu = GetCPUInfo();  
  7.         string baseBoard = GetBaseBoardInfo();  
  8.         string bios = GetBIOSInfo();  
  9.         string mac = GetMACInfo();  
  10.         info = string.Concat(cpu, baseBoard, bios, mac);  
  11.         return info;  
  12.     }  
  13.   
  14.     private static string GetCPUInfo()  
  15.     {  
  16.         string info = string.Empty;  
  17.         info = GetHardWareInfo("Win32_Processor", "ProcessorId");  
  18.         return info;  
  19.     }  
  20.     private static string GetBIOSInfo()  
  21.     {  
  22.         string info = string.Empty;  
  23.         info = GetHardWareInfo("Win32_BIOS", "SerialNumber");  
  24.         return info;  
  25.     }  
  26.     private static string GetBaseBoardInfo()  
  27.     {  
  28.         string info = string.Empty;  
  29.         info = GetHardWareInfo("Win32_BaseBoard", "SerialNumber");  
  30.         return info;  
  31.     }  
  32.     private static string GetMACInfo()  
  33.     {  
  34.         string info = string.Empty;  
  35.         info = GetHardWareInfo("Win32_BaseBoard", "SerialNumber");  
  36.         return info;  
  37.     }  
  38.     private static string GetHardWareInfo(string typePath, string key)  
  39.     {  
  40.         try  
  41.         {  
  42.             ManagementClass managementClass = new ManagementClass(typePath);  
  43.             ManagementObjectCollection mn = managementClass.GetInstances();  
  44.             PropertyDataCollection properties = managementClass.Properties;  
  45.             foreach (PropertyData property in properties)  
  46.             {  
  47.                 if (property.Name == key)  
  48.                 {  
  49.                     foreach (ManagementObject m in mn)  
  50.                     {  
  51.                         return m.Properties[property.Name].Value.ToString();  
  52.                     }  
  53.                 }  
  54.   
  55.             }  
  56.         }  
  57.         catch (Exception ex)  
  58.         {  
  59.             //这里写异常的处理    
  60.         }  
  61.         return string.Empty;  
  62.     }  
  63.     private static string GetMacAddressByNetworkInformation()  
  64.     {  
  65.         string key = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";  
  66.         string macAddress = string.Empty;  
  67.         try  
  68.         {  
  69.             NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();  
  70.             foreach (NetworkInterface adapter in nics)  
  71.             {  
  72.                 if (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet  
  73.                     && adapter.GetPhysicalAddress().ToString().Length != 0)  
  74.                 {  
  75.                     string fRegistryKey = key + adapter.Id + "\\Connection";  
  76.                     RegistryKey rk = Registry.LocalMachine.OpenSubKey(fRegistryKey, false);  
  77.                     if (rk != null)  
  78.                     {  
  79.                         string fPnpInstanceID = rk.GetValue("PnpInstanceID", "").ToString();  
  80.                         int fMediaSubType = Convert.ToInt32(rk.GetValue("MediaSubType", 0));  
  81.                         if (fPnpInstanceID.Length > 3 &&  
  82.                             fPnpInstanceID.Substring(0, 3) == "PCI")  
  83.                         {  
  84.                             macAddress = adapter.GetPhysicalAddress().ToString();  
  85.                             for (int i = 1; i < 6; i++)  
  86.                             {  
  87.                                 macAddress = macAddress.Insert(3 * i - 1, ":");  
  88.                             }  
  89.                             break;  
  90.                         }  
  91.                     }  
  92.   
  93.                 }  
  94.             }  
  95.         }  
  96.         catch (Exception ex)  
  97.         {  
  98.             //这里写异常的处理    
  99.         }  
  100.         return macAddress;  
  101.     }  
  102. }  

 

        2.加密解密代码;

 

 

  1. public enum EncryptionKeyEnum  
  2. {  
  3.     KeyA,  
  4.     KeyB  
  5. }  
  6. public class EncryptionHelper  
  7. {  
  8.     string encryptionKeyA = "pfe_Nova";  
  9.     string encryptionKeyB = "WorkHard";  
  10.     string md5Begin = "Hello";  
  11.     string md5End = "World";  
  12.     string encryptionKey = string.Empty;  
  13.     public EncryptionHelper()  
  14.     {  
  15.         this.InitKey();  
  16.     }  
  17.     public EncryptionHelper(EncryptionKeyEnum key)  
  18.     {  
  19.         this.InitKey(key);  
  20.     }  
  21.     private void InitKey(EncryptionKeyEnum key = EncryptionKeyEnum.KeyA)  
  22.     {  
  23.         switch (key)  
  24.         {  
  25.             case EncryptionKeyEnum.KeyA:  
  26.                 encryptionKey = encryptionKeyA;  
  27.                 break;  
  28.             case EncryptionKeyEnum.KeyB:  
  29.                 encryptionKey = encryptionKeyB;  
  30.                 break;  
  31.         }  
  32.     }  
  33.   
  34.     public string EncryptString(string str)  
  35.     {  
  36.         return Encrypt(str, encryptionKey);  
  37.     }  
  38.     public string DecryptString(string str)  
  39.     {  
  40.         return Decrypt(str, encryptionKey);  
  41.     }  
  42.     public string GetMD5String(string str)  
  43.     {  
  44.         str = string.Concat(md5Begin, str, md5End);  
  45.         MD5 md5 = new MD5CryptoServiceProvider();  
  46.         byte[] fromData = Encoding.Unicode.GetBytes(str);  
  47.         byte[] targetData = md5.ComputeHash(fromData);  
  48.         string md5String = string.Empty;  
  49.         foreach (var b in targetData)  
  50.             md5String += b.ToString("x2");  
  51.         return md5String;  
  52.     }  
  53.   
  54.     private string Encrypt(string str, string sKey)  
  55.     {  
  56.         DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  57.         byte[] inputByteArray = Encoding.Default.GetBytes(str);  
  58.         des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);  
  59.         des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);  
  60.         MemoryStream ms = new MemoryStream();  
  61.         CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);  
  62.         cs.Write(inputByteArray, 0, inputByteArray.Length);  
  63.         cs.FlushFinalBlock();  
  64.         StringBuilder ret = new StringBuilder();  
  65.         foreach (byte b in ms.ToArray())  
  66.         {  
  67.             ret.AppendFormat("{0:X2}", b);  
  68.         }  
  69.         ret.ToString();  
  70.         return ret.ToString();  
  71.     }  
  72.     private string Decrypt(string pToDecrypt, string sKey)  
  73.     {  
  74.         DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  75.         byte[] inputByteArray = new byte[pToDecrypt.Length / 2];  
  76.         for (int x = 0; x < pToDecrypt.Length / 2; x++)  
  77.         {  
  78.             int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));  
  79.             inputByteArray[x] = (byte)i;  
  80.         }  
  81.         des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);  
  82.         des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);  
  83.         MemoryStream ms = new MemoryStream();  
  84.         CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);  
  85.         cs.Write(inputByteArray, 0, inputByteArray.Length);  
  86.         cs.FlushFinalBlock();  
  87.         StringBuilder ret = new StringBuilder();  
  88.         return System.Text.Encoding.Default.GetString(ms.ToArray());  
  89.     }  
  90. }  

        注:这边在MD5时前后各加了一段字符,这样增加一点破解难度。

 

        3.读写文件

 

  1. public class RegistFileHelper  
  2. {  
  3.     public static string ComputerInfofile = "ComputerInfo.key";  
  4.     public static string RegistInfofile = "RegistInfo.key";  
  5.     public static void WriteRegistFile(string info)  
  6.     {  
  7.         WriteFile(info, RegistInfofile);  
  8.     }  
  9.     public static void WriteComputerInfoFile(string info)  
  10.     {  
  11.         WriteFile(info, ComputerInfofile);  
  12.     }  
  13.     public static string ReadRegistFile()  
  14.     {  
  15.         return ReadFile(RegistInfofile);  
  16.     }  
  17.     public static string ReadComputerInfoFile()  
  18.     {  
  19.         return ReadFile(ComputerInfofile);  
  20.     }  
  21.     public static bool ExistComputerInfofile()  
  22.     {  
  23.         return File.Exists(ComputerInfofile);  
  24.     }  
  25.     public static bool ExistRegistInfofile()  
  26.     {  
  27.         return File.Exists(RegistInfofile);  
  28.     }  
  29.     private static void WriteFile(string info, string fileName)  
  30.     {  
  31.         try  
  32.         {  
  33.             using (StreamWriter sw = new StreamWriter(fileName, false))  
  34.             {  
  35.                 sw.Write(info);  
  36.                 sw.Close();  
  37.             }  
  38.         }  
  39.         catch (Exception ex)  
  40.         {  
  41.         }  
  42.     }  
  43.     private static string ReadFile(string fileName)  
  44.     {  
  45.         string info = string.Empty;  
  46.         try  
  47.         {  
  48.             using (StreamReader sr = new StreamReader(fileName))  
  49.             {  
  50.                 info = sr.ReadToEnd();  
  51.                 sr.Close();  
  52.             }  
  53.         }  
  54.         catch (Exception ex)  
  55.         {  
  56.         }  
  57.         return info;  
  58.     }  
  59. }  

 

        4.其他界面代码:

        主界面代码:

 

 

  1. public partial class FormMain : Form  
  2. {  
  3.     private string encryptComputer = string.Empty;  
  4.     private bool isRegist = false;  
  5.     private const int timeCount = 30;  
  6.     public FormMain()  
  7.     {  
  8.         InitializeComponent();  
  9.         Control.CheckForIllegalCrossThreadCalls = false;  
  10.     }  
  11.     private void FormMain_Load(object sender, EventArgs e)  
  12.     {  
  13.         string computer = ComputerInfo.GetComputerInfo();  
  14.         encryptComputer = new EncryptionHelper().EncryptString(computer);  
  15.         if (CheckRegist() == true)  
  16.         {  
  17.             lbRegistInfo.Text = "已注册";  
  18.         }  
  19.         else  
  20.         {  
  21.             lbRegistInfo.Text = "待注册,运行十分钟后自动关闭";  
  22.             RegistFileHelper.WriteComputerInfoFile(encryptComputer);  
  23.             TryRunForm();  
  24.         }  
  25.     }  
  26.     /// <summary>  
  27.     /// 试运行窗口  
  28.     /// </summary>  
  29.     private void TryRunForm()  
  30.     {  
  31.         Thread threadClose = new Thread(CloseForm);  
  32.         threadClose.IsBackground = true;  
  33.         threadClose.Start();  
  34.     }  
  35.     private bool CheckRegist()  
  36.     {  
  37.         EncryptionHelper helper = new EncryptionHelper();  
  38.         string md5key = helper.GetMD5String(encryptComputer);  
  39.         return CheckRegistData(md5key);  
  40.     }  
  41.     private bool CheckRegistData(string key)  
  42.     {  
  43.         if (RegistFileHelper.ExistRegistInfofile() == false)  
  44.         {  
  45.             isRegist = false;  
  46.             return false;  
  47.         }  
  48.         else  
  49.         {  
  50.             string info = RegistFileHelper.ReadRegistFile();  
  51.             var helper = new EncryptionHelper(EncryptionKeyEnum.KeyB);  
  52.             string registData = helper.DecryptString(info);  
  53.             if (key == registData)  
  54.             {  
  55.                 isRegist = true;  
  56.                 return true;  
  57.             }  
  58.             else  
  59.             {  
  60.                 isRegist = false;  
  61.                 return false;  
  62.             }  
  63.         }  
  64.     }  
  65.     private void CloseForm()  
  66.     {  
  67.         int count = 0;  
  68.         while (count < timeCount && isRegist == false)  
  69.         {  
  70.             if (isRegist == true)  
  71.             {  
  72.                 return;  
  73.             }  
  74.             Thread.Sleep(1 * 1000);  
  75.             count++;  
  76.         }  
  77.         if (isRegist == true)  
  78.         {  
  79.             return;  
  80.         }  
  81.         else  
  82.         {  
  83.             this.Close();  
  84.         }  
  85.     }  
  86.   
  87.     private void btnRegist_Click(object sender, EventArgs e)  
  88.     {  
  89.         if (lbRegistInfo.Text == "已注册")  
  90.         {  
  91.             MessageBox.Show("已经注册~");  
  92.             return;  
  93.         }  
  94.         string fileName = string.Empty;  
  95.         OpenFileDialog openFileDialog = new OpenFileDialog();  
  96.         if (openFileDialog.ShowDialog() == DialogResult.OK)  
  97.         {  
  98.             fileName = openFileDialog.FileName;  
  99.         }  
  100.         else  
  101.         {  
  102.             return;  
  103.         }  
  104.         string localFileName = string.Concat(  
  105.             Environment.CurrentDirectory,  
  106.             Path.DirectorySeparatorChar,  
  107.             RegistFileHelper.RegistInfofile);  
  108.         if (fileName != localFileName)  
  109.             File.Copy(fileName, localFileName, true);  
  110.   
  111.         if (CheckRegist() == true)  
  112.         {  
  113.             lbRegistInfo.Text = "已注册";  
  114.             MessageBox.Show("注册成功~");  
  115.         }  
  116.     }  
  117. }  

        注册机代码:

 

 

  1. public partial class FormMain : Form  
  2. {  
  3.     public FormMain()  
  4.     {  
  5.         InitializeComponent();  
  6.     }  
  7.   
  8.     private void btnRegist_Click(object sender, EventArgs e)  
  9.     {  
  10.         string fileName = string.Empty;  
  11.         OpenFileDialog openFileDialog = new OpenFileDialog();  
  12.         if (openFileDialog.ShowDialog() == DialogResult.OK)  
  13.         {  
  14.             fileName = openFileDialog.FileName;  
  15.         }  
  16.         else  
  17.         {  
  18.             return;  
  19.         }  
  20.         string localFileName = string.Concat(  
  21.             Environment.CurrentDirectory,  
  22.             Path.DirectorySeparatorChar,  
  23.             RegistFileHelper.ComputerInfofile);  
  24.   
  25.         if (fileName != localFileName)  
  26.             File.Copy(fileName, localFileName, true);  
  27.         string computer = RegistFileHelper.ReadComputerInfoFile();  
  28.         EncryptionHelper help = new EncryptionHelper(EncryptionKeyEnum.KeyB);  
  29.         string md5String = help.GetMD5String(computer);  
  30.         string registInfo = help.EncryptString(md5String);  
  31.         RegistFileHelper.WriteRegistFile(registInfo);  
  32.         MessageBox.Show("注册码已生成");  
  33.     }  
  34. }  

        最后采用ConfuserEx将可执行文件加密(ConfuserEx介绍),这样就不能反编译获得源码。

 

        至此全部完成,只是个人的一些实践,对自己是一个记录,同时希望也能对别人有些帮助,如果有什么错误,还望不吝指出,共同进步,转载请保留原文地址

posted @ 2022-02-22 19:28  浅绿色i  阅读(1098)  评论(0编辑  收藏  举报