您好,登錄后才能下訂單哦!
推薦+1置頂+1(分享、討論、實現)
通用軟件注冊功能之建立有效的軟件保護機制
眾所周知,一些共享軟件往往提供給使用者的是一個功能不受限制的限時使用版,在試用期內使用者可以無限制的使用軟件的全部功能(只是可能會出現提示使用者注冊的窗口),試用期一過部分(或全部)功能失效,要想繼續使用只能向作者索取注冊碼(或注冊文件)完成對軟件的合法注冊,注冊后的軟件將解除一切使用限制。如果您也開發出一個有價值的作品,是否也希望為自己的軟件增加一個這樣的功能呢?當前對于.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 }
至此,軟件的注冊功能就完成了,當然還有其他很多方法,比如:
一、 采用加密狗的方式(最安全的方式)。 二、 在線驗證注冊信息(用戶需能上網),這種方式也比較可靠。 三、 其他方法,歡迎大家討論。 四、 ......
作者: EricHu 出處: http://blog.csdn.net/chinahuyong 微博: 騰訊 Email: 406590790@qq.com QQ 交流:406590790 平臺博客: 【CSDN】http://blog.csdn.net/chinahuyong 【CNBLOGS】http://www.cnblogs.com/huyong 關于作者:高級工程師、信息系統項目管理師、DBA。專注于微軟平臺項目架構、管理和企業解決方案,多年項目開發與管理經驗,曾多次組織并開發多個大型項目,精通DotNet,DB(SqlServer、Oracle等)技術。熟悉Java、Delhpi及Linux操作系統,有扎實的網絡知識。在面向對象、面向服務以及數據庫領域有一定的造詣。現從事DB管理與開發、WinForm、WCF、WebService、網頁數據抓取以及ASP.NET等項目管理、開發、架構等工作。 如有問題或建議,請多多賜教! 本文版權歸作者和CNBLOGS博客共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,可以通過郵箱或QQ 聯系我,非常感謝。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。