google centos Ubuntu nginx 开源 apache mysql Windows shell java linux Firefox Python Android 微软 云计算 php 程序员 编程 wordpress

通用軟件註冊功能之建立有效的軟件保護機制

 

 眾所周知,一些共享軟件往往提供給使用者的是一個功能不受限制的限時使用版,在試用期內使用者可以無限制的使用軟件的全部功能(只是可能會出現提示使用者註冊的窗口),試用期一過部分(或全部)功能失效,要想繼續使用只能向作者索取註冊碼(或註冊文件)完成對軟件的合法註冊,註冊後的軟件將解除一切使用限制。如果您也開發出一個有價值的作品,是否也希望為自己的軟件增加一個這樣的功能呢?當前對於.NET反編譯的問題不在本文討論之內,相關文章已經很多!本文我們就一起探討軟件註冊功能的實現。

       實現軟件的註冊功能方法很多,最需要考慮的就是不能輕易的讓使用者破解,在這裏,我就談談“.NET快速開發整合框架(RDIFramework.NET)”中平臺註冊功能的實現方法。在RDIFramework.NET中,註冊功能主要方法就是對計算機唯一硬件信息進行RSA數字簽名達到軟件註冊和保護的功能,該方法實現簡單,安全性相應較高。

       計算機唯一硬件信息(我們知道計算機中的關鍵部件如CPU,主板等在全球範圍內都有一個獨一無二的產品序列號,用戶通過註冊模塊獲取這些產品序列號(即傳統所說的:機器嗎)並將它發送給軟件開發商要求進行RSA數據簽名,軟件開發商獲得這些機器碼後利用手中的私鑰對這些信息進行RSA數字簽名,生成的簽名信息(即註冊碼)發回給用戶,用戶將收到的註冊碼輸入註冊模塊的註冊碼框,軟件即可利用公鑰執行簽名驗證,如果輸入的註冊碼被證明就是經過開發商數字簽名的機器碼,則完成註冊過程。

       註冊功能項目結構圖如下所示:

 

图1 注册功能项目结构

 

平臺服務端註冊碼生成主界面如下所示:

 

图2 注册文件管理器

通過“註冊文件管理器”,我們就可以根據用戶提供的信息來生成軟件的註冊文件。

客戶端的註冊主要就是根據我們提供的註冊文件與公鑰,來驗證註冊文件是否為當前客戶的有效註冊文件,如果有效,註冊成功,無效則註冊失敗!客戶端註冊功能設計參考如下所示:

 

图3 平台注册

用户单击“注册”按钮,成功注册提示:

 

图4注册成功

服務端註冊碼生成核心代碼:

一、     生成公/私鑰文件:

 

 1 private void btnGenerateKey_Click(object sender, EventArgs e)   2         {   3             if (MessageBox.Show("确定生成生成公/私钥对吗(是/否)?", "询问信息", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)    4                 == System.Windows.Forms.DialogResult.cancel)   5             {   6                 return;   7             }   8    9             RSACryptoServiceProvider crypt = new RSACryptoServiceProvider();  10            11             string publicKey = crypt.ToXmlString(true);  12             string privateKey   = crypt.ToXmlString(false);  13             crypt.clear();  14   15             //生成公钥  16             using (StreamWriter sw = new StreamWriter(KeyPath + "RDIFrameworkkey.key", false, UTF8Encoding.UTF8))  17             {  18                 sw.write(SecretHelper.AESEncrypt(publicKey));  19                 sw.Flush();  20             }  21   22             //生成私钥  23             using (StreamWriter sw = new StreamWriter(KeyPath + "RDIFrameworkPrivateKey.key", false, UTF8Encoding.UTF8))  24             {  25                 sw.Write(SecretHelper.AESEncrypt(privateKey));  26                 sw.Flush();  27             }             28             29             MessageBox.Show("成功生成公/私钥对!","提示信息",MessageBoxButtons.OK,MessageBoxIcon.Information);  30         }

二、     生成注册文件:

 1 private void btnGenerateRegisterFile_Click(object sender, EventArgs e)   2         {   3             if (string.IsNullOrEmpty(txtUserEmail.Text.Trim()))   4             {   5                 MessageBox.Show("用户邮箱不能为空!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);   6                 txtUserEmail.Focus();   7                 return;   8             }   9             else  10             {  11                 if (!RegexValidatorHelper.IsMatch(txtUserEmail.Text.Trim(), Pattern.EMAIL))  12                 {  13                     MessageBox.Show("邮箱格式不正确!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);  14                     txtUserEmail.SelectAll();  15                     return;  16                 }  17             }  18   19             if (string.IsNullOrEmpty(txtCPUSerialNo.Text.Trim()))  20             {  21                 MessageBox.Show("CPU序列号不能为空!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);  22                 return;  23             }  24   25             if (!string.IsNullOrEmpty(txtUseLimited.Text.Trim()))  26             {  27                 if (!RegexValidatorHelper.IsMatch(txtUseLimited.Text.Trim(), Pattern.INTEGER))  28                 {  29                     MessageBox.Show("使用次数应该为数值型!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);  30                     txtUseLimited.SelectAll();  31                     return;  32                 }  33             }  34   35             //读取私钥  36             StreamReader sr = new StreamReader(KeyPath + "RDIFrameworkPrivateKey.key", UTF8Encoding.UTF8);              37             string keypair = sr.ReadToEnd();  38             sr.Close();  39   40             //用私钥参数初始化RSACryptoServiceProvider类的实例crypt。  41             RSACryptoServiceProvider crypt = new RSACryptoServiceProvider();  42   43             crypt.FromXmlString(SecretHelper.AESDecrypt(keypair));  44   45             UTF8Encoding enc = new UTF8Encoding();  46   47             string trialTime = "30";//试用次数(默认:30数,0:表示永久)  48             if (!string.IsNullOrEmpty(txtUseLimited.Text.Trim()))  49             {  50                 trialTime = txtUseLimited.Text.Trim();  51             }  52             string regInfo = txtUserEmail.Text.Trim() + ";" + txtMAC.Text.Trim() + ";" + txtCPUSerialNo.Text.Trim() + ";" + trialTime;  53   54             byte[] bytes = enc.GetBytes(regInfo);//格式:邮箱地址;MAC;CPU序列号;试用时间  55             //对用户信息加密  56             bytes = crypt.Encrypt(bytes, false);  57               58             //生成注册数据,对二进制字节进行Base64编码,但采用注册文件的形式的进修也可以不做此转化。  59             string encrytText = System.Convert.ToBase64String(bytes, 0, bytes.Length);  60   61             //将注册码写入文件  62             using (StreamWriter sw = new StreamWriter(KeyPath + "RDIFramework_reg_file.lic", false, UTF8Encoding.UTF8))  63             {  64                 sw.Write(encrytText);  65                 sw.Flush();  66             }  67   68             MessageBox.Show("注册文件:RDIFramework_reg_file.lic生成成功!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);           69         }

三、     验证注册文件:

 

 1 private void btnCheckRegistr_Click(object sender, EventArgs e)   2         {   3             //读取注册数据文件   4             StreamReader sr = new StreamReader(KeyPath + "RDIFramework_reg_file.lic", UTF8Encoding.UTF8);   5             string encrytText = sr.ReadToEnd();   6             sr.Close();   7    8    9             //读取公钥  10             StreamReader srPublickey = new StreamReader(KeyPath + "RDIFrameworkkey.key", UTF8Encoding.UTF8);  11             string publicKey = srPublickey.ReadToEnd();  12             srPublickey.Close();  13   14             //用公钥初化始RSACryptoServiceProvider类实例crypt。  15             RSACryptoServiceProvider crypt = new RSACryptoServiceProvider();  16             crypt.FromXmlString(SecretHelper.AESDecrypt(publicKey));  17             UTF8Encoding enc = new UTF8Encoding();  18             byte[] decryptByte;  19             try  20             {  21                 byte[] newBytes;  22                 newBytes = System.Convert.FromBase64CharArray(encrytText.ToCharArray(), 0, encrytText.Length);  23                 decryptByte = crypt.Decrypt(newBytes, false);  24                 string decrypttext = enc.GetString(decryptByte);  25                 //  26                 //TODO:在此处添加验证逻辑  27                 //  28                 MessageBox.Show(decrypttext);  29             }  30             catch(Exception ex)  31             {  32                 MessageBox.Show(ex.Message);  33             }  34         }

 

至此,軟件的註冊功能就完成了,當然還有其他很多方法,比如:

一、 采用加密狗的方式(最安全的方式)。    二、 在線驗證註冊信息(用戶需能上網),這種方式也比較可靠。    三、 其他方法,歡迎大家討論。    四、  ......
 

 

延伸阅读

    评论