對于 Web 應(yīng)用程序,安全登錄是很重要的。但是目前大多數(shù) Web 系統(tǒng)在發(fā)送登錄密碼時是發(fā)送的明文,這樣很容易被入侵者監(jiān)聽到密碼。當(dāng)然,通過 SSL 來實現(xiàn)安全連接是個不錯的方法,但是很多情況下我們沒辦法將服務(wù)器設(shè)置為帶有 SSL 的 Web 服務(wù)器。因此如果在登錄系統(tǒng)中加入安全登錄機制,則可以在沒有 SSL 的 Web 服務(wù)器上實現(xiàn)安全登錄。
要實現(xiàn)安全登錄,可以采用下面三種方法,一種基于非對稱加密算法,一種基于對稱加密算法,最后一種基于散列算法。下面我們來分別討論這三種方法。
非對稱加密算法中,目前最常用的是 RSA 算法和 ECC(橢圓曲線加密)算法。要采用非對稱加密算法實現(xiàn)安全登錄的話,首先需要在客戶端向服務(wù)器端請求登錄頁面時,服務(wù)器生成公鑰和私鑰,然后將公鑰隨登錄頁面一起傳遞給客戶端瀏覽器,當(dāng)用戶輸入完用戶名密碼點擊登錄時,登錄頁面中的 JavaScript 調(diào)用非對稱加密算法對用戶名和密碼用用公鑰進行加密。然后再提交到服務(wù)器端,服務(wù)器端利用私鑰進行解密,再跟數(shù)據(jù)庫中的用戶名密碼進行比較,如果一致,則登錄成功,否則登錄失敗。
看上去很簡單,但是這里有這樣幾個問題。目前 RSA 算法中,1024-2048 位的密鑰被認(rèn)為是安全的。如果密鑰長度小于這個長度,則認(rèn)為可以被破解。但這樣的長度超過了程序設(shè)計語言本身所允許的數(shù)字運算范圍,需要通過模擬來實現(xiàn)大數(shù)運算。而在 Web 系統(tǒng)的客戶端,如果通過 JavaScript 來模擬大數(shù)運行的話,效率將會是很低的,因此要在客戶端采用這樣的密鑰來加密數(shù)據(jù)的話,許多瀏覽器會發(fā)出執(zhí)行時間過長,停止運行的警告。然而,解密或者密鑰生成的時間相對于加密來說要更長。雖然解密和密鑰生成是在服務(wù)器端執(zhí)行的,但是如果服務(wù)器端是 PHP、ASP 這樣的腳本語言的話,它們也將很難勝任這樣的工作。ECC 算法的密鑰長度要求比 RSA 算法要低一些,ECC 算法中 160 位的密鑰長度被認(rèn)為與 RSA 算法中 1024 位的密鑰長度的安全性是等價的。雖然仍然要涉及的模擬大數(shù)運算,但 ECC 算法的密鑰長度的運算量還算是可以接受的,但是 ECC 算法比 RSA 算法要復(fù)雜的多,因此實現(xiàn)起來也很困難。
對稱加密算法比非對稱加密算法要快得多,但是對稱加密算法需要數(shù)據(jù)發(fā)送方和接受方共用一個密鑰,密鑰是不能通過不安全的網(wǎng)絡(luò)直接傳遞的,否則密鑰和加密以后的數(shù)據(jù)如果同時監(jiān)聽到的話,入侵者就可以直接利用監(jiān)聽到的密鑰來對加密后的信息進行解密了。
那是不是就不能通過對稱加密算法實現(xiàn)安全登錄呢?其實只要通過密鑰交換算法就可以實現(xiàn)安全登錄了,常用的密鑰交換算法是 Diffie-Hellman 密鑰交換算法。我們可以這樣來實現(xiàn)密鑰的安全傳遞,首先在客戶端向服務(wù)器端請求登錄頁面時,服務(wù)器端生成一個大素數(shù) p,它的本原根 g,另外生成一個隨機數(shù) Xa,然后計算出 Ya = gXa mod p,將 p、g、Ya 連同登錄頁面一起發(fā)送給客戶端,然后客戶端也生成一個隨機數(shù) Xb,計算 Yb = gXb mod p,然后再計算 K = YaXb mod p,現(xiàn)在 K 就是密鑰,接下來就可以用 K 作密鑰,用對稱加密算法對用戶輸入進行加密了,然后將加密后的信息連同計算出來的 Yb 一同發(fā)送給服務(wù)器端,服務(wù)器端計算 K = YbXa mod p,這樣就可以得到跟客戶端相同的密鑰 K 了,最后用客戶端加密算法的相應(yīng)解密算法,就可以在服務(wù)器端將加密信息進行解密了,信息解密以后進行比較,一致則登錄成功,否則登錄失敗。需要注意的時候,這里服務(wù)器端生成的隨機數(shù) Xa 和 客戶端生成的隨機數(shù) Xb 都不傳遞給對方。傳遞的數(shù)據(jù)只有 p、g、Ya、Yb 和加密后的數(shù)據(jù)。
但是如果我們不采用加密算法而采用散列算法對登錄密碼進行處理的話,可以避免被直接解密出原文,但是如果直接采用 MD5 或者 SHA1 來對登錄密碼進行處理后提交的話,一旦入侵者監(jiān)聽到散列后的密碼,則不需要解密出原文,直接將監(jiān)聽到的數(shù)據(jù)提交給服務(wù)器,就可以實現(xiàn)入侵的目的了。而且,目前 MD5 算法已被破解,SHA1 算法則被證明從理論上可破解,就算采用離線碰撞,也可以找出與原密碼等價的密碼來。所以直接采用 MD5 或者 SHA1 來對密碼進行散列處理也是不可行的。
但是如果在散列算法中加入了密鑰,情況就不一樣了。hmac 算法正好作了這樣的事情,下面我們來看看如何用 hmac 算法實現(xiàn)安全登錄。首先在客戶端向服務(wù)器端請求登錄頁面時,服務(wù)器端生成一個隨機字符串,連同登錄頁面一同發(fā)送給客戶端瀏覽器,當(dāng)用戶輸入完用戶名密碼后,將密碼采用 MD5 或者 SHA1 來生成散列值作為密鑰,服務(wù)器端發(fā)送來的隨機字符串作為消息數(shù)據(jù),進行 hmac 運算。然后將結(jié)果提交給服務(wù)器。之所以要對用戶輸入的密碼進行散列后再作為密鑰,而不是直接作為密鑰,是為了保證密鑰足夠長,而又不會太長。服務(wù)器端接受到客戶端提交的數(shù)據(jù)后,將保存在服務(wù)器端的隨機字符串和用戶密碼進行相同的運算,然后進行比較,如果結(jié)果一致,則認(rèn)為登錄成功,否則登錄失敗。當(dāng)然如果不用 hmac 算法,直接將密碼和服務(wù)器端生成的隨機數(shù)合并以后再做 MD5 或者 SHA1,應(yīng)該也是可以的。
這里客戶端每次請求時服務(wù)器端發(fā)送的隨機字符串都是不同的,因此即使入侵者監(jiān)聽到了這個隨機字符串和加密后的提交的數(shù)據(jù),它也無法再次提交相同的數(shù)據(jù)通過驗證。而且通過監(jiān)聽到的數(shù)據(jù)也無法計算出密鑰,所以也就無法偽造登錄信息了。
對稱和非對稱加密算法不僅適用于登錄驗證,還適合用于最初的密碼設(shè)置和以后密碼修改的過程中,而散列算法僅適用于登錄驗證。但是散列算法要比對稱和非對稱加密算法效率高。
出處:CoolCode.CN
責(zé)任編輯:moby
◎進入論壇網(wǎng)絡(luò)編程版塊參加討論
|