近期由於工作調整的原因,很久沒有寫新的文章,很多朋友的留言也沒有回復,十分抱歉。
本篇隨筆主要依據一次應用對"非對稱加密"的常用領域進行介紹,已經很了解的同學請跳過本文,以免浪費你的時間。
1.問題的提出
寫這篇隨筆,主要是因為公司最近要發布一個小產品,幫助用戶進行一些資源預約,比如會議室什么的。這個所謂的產品是個Web網站,而這個網站客戶要求發布在局域網內部。
好的,這就是產品的現狀,現在老大說,這個玩意兒要收費了,幾千塊錢能讓用戶用三個月,到期后不續費就不能繼續使用。
博主所在的小組收到任務去實現這個收費功能,其實要實現這個功能有很多方案,給Web程序一個注冊號,使用WebService來驗證這個注冊號是否到期,這應該是最簡單的一種實現方式,但是由於這個Web網站是發布在局域網的,所以這個解決方案被PASS掉了
2.解決方案
最終我們提出的解決方案是:發給客戶一個注冊文件,該注冊文件中包含一個有效期,在Web程序中,我們訪問該注冊文件,如果注冊文件中的有效期已經到期,則阻止用戶繼續訪問。
當然,肯定有更好的解決方案,歡迎留言
針對我們提出的解決方案,我們很自然的想到幾個問題
首先想到的就是該注冊文件中信息的安全性,我們的程序必須能夠識別該信息的可靠性,確保注冊信息是我們發布的而不是用戶書寫的,這個任務可以由加密來完成,但是就像我們之前已經說過的,該程序是發布在用戶的局域網內部的,我們必須把加密的密鑰提供給Web程序,方便Web程序對注冊信息進行解密然后識別,但是提供給Web程序的密鑰會被用戶查看到,這樣他們就能自己加密一些注冊信息提供給Web程序,這樣肯定是不行的,到此我們就碰到的對稱加密最大的缺點,為了規避這個問題,非對稱加密隆重登場!!
3.非對稱加密
非對稱加密能夠提供一對密鑰,公鑰和私鑰,使用公鑰加密的內容無法使用公鑰進行解密,必須使用其對應的私鑰才能解密,反之亦然,正好符合我們的要求:
我們可以自己保留私鑰,把公鑰提供給Web程序,這樣注冊文件只能由私鑰生成而無法使用公鑰進行生成,用戶即使掌握了公鑰也無法生成注冊文件
簡單介紹一下我們使用的非對稱加密方法:RSA,該方法基於一個數學難題:大數的因子分解,該加密方法已經集成在.net的類庫中,想要了解具體實現方法的請參照:《RSA加密算法說明》和《RSA加密算法實現》 (實現算法使用C++和Java寫的,不過都無所謂)
在C#中我們可以使用RSACryptoServiceProvider類進行產生密鑰對,明文加密和密文解密的動作,具體寫法很簡單,不用過多討論,需要的朋友可以自己去MSDN,自己動手豐衣足食嘛^_^
在使用RSACryptoServiceProvider類的時候我們會發現,類庫要求我們進行加密的明文必須為128個字節,多於這個數量會引發異常,所以很多朋友在網上提出解決方案,比如把明文切斷,分別加密啦等等,其實我覺得這是一個誤區,要解釋這個誤區,我們得先從非對稱加密的常用領域說起
4.非對稱加密的常用領域
使用非對稱加密時我們一般會將私鑰保留,將公鑰分發給用戶,當然,具體的分發動作是通過證書還是怎么樣不在我們這次的討論范圍內
第一種場景:用戶使用公鑰進行加密,則 只能由我們自己的私鑰進行解密,就可以保證我們傳遞的信息是加密過的只有私鑰的持有人能夠對密文進行解密,其他人(包括公鑰的持有人)也是無法解密密文的,但是這同樣帶來一個問題,由於非對稱加密實現算法較為復雜,加密過程比較耗時,因此,我們一般將對稱加密和非對稱加密結合使用,即:使用對稱加密算法對明文進行加密,使用非對稱加密算法對對稱加密的密鑰進行加密,其實說到底,就是使用非對稱加密算法進行對稱加密密鑰的發布,這也是“一次一密”的一種實現方法。


第二種場景是我們使用私鑰進行加密,公鑰的持有人都可以使用公鑰進行解密,這樣,公鑰持有人就可以確認該內容是由私鑰的持有人發布出來的,同樣,由於非對稱加密和解密比較耗時的原因,我們可以對該實現方式進行改良,最常見的改良方式為:我們可以對明文進行散列操作,最終將明文散列為較短的一個散列碼,然后我們使用私鑰對該散列碼進行加密,在公鑰的持有人收到消息后,可以重復上面的操作,比對自己的散列碼和解析出的散列碼是否相同,如果相同,則可以證明該消息是由公鑰的持有人發布的,這就是我們常說的電子簽名,當然我們也可以將上面提到的對稱密鑰的發布過程也包含在電子簽名的過程中,以此來保證消息的內容只有公鑰的持有人能夠查看


通過上面兩種應用場景我們可以發現,非對稱加密算法只要能夠滿足128個字節的加密就能滿足所有的應用需求。
5.問題的解決
到此,我們的問題已經可以解決:
1.在注冊文件中寫入一個使用有效期,
2.使用散列算法(如MD5)對該有效期進行散列產生散列碼
3.使用私鑰對散列碼進行簽名,作為消息頭
這樣我們就能產生一個注冊文件
解析注冊文件的過程為
1.使用相同的散列算法對消息內容進行散列
2.使用公鑰對消息頭進行解密
3.比較解密后的消息頭和消息內容的散列碼是否一致
這樣我們既可以保證消息內容的可靠性又保證了消息內容的完整性,問題解決!!
6.使用MD5進行加密??
經常聽到有人說:“我們的用戶密碼使用MD5、SHA1進行加密”等等說法,其實我個人覺得,MD5和SHA1不能說是一種加密算法,更確切的說是一種散列(HASH)算法,理想狀態下,不同內容使用MD5/SHA1進行散列后的得到的散列碼是不一樣的,由於散列算法理論上來說是一種不可逆的算法,所以很多網站使用散列算法來對其用戶密碼進行保護,最常見的使用方法是:將用戶注冊時的密碼散列后保存到數據庫中,在用戶登錄時,將用戶輸入的密碼進行散列,和數據庫中的散列碼進行比較,如果二者相同,則可以正常登錄。網上流行的MD5的破解器其實也就是將常見的字符組合進行暴力破解,如果用戶的密碼足夠復雜,則使用散列算法進行密碼保護既可以免去保存密鑰的麻煩,又可以保證數據庫和網絡傳輸過程中密碼的安全性,不失為一種比較好的解決方案
