HTTP協議下保證密碼不被獲取更健壯方式

轉載自:https://www.cnblogs.com/intsmaze/p/6009648.html,評論也很有意思,可以看看

說到在http協議下用戶登錄如何保證密碼安全這個問題:
    小白可能第一想法就是,用戶在登錄頁面輸入密碼進行登錄時,前臺頁面對用戶輸入的密碼進行加密,然後把加密後的密碼作爲http請求參數通過網絡發到服務器。
    這樣做是無法保證用戶的賬戶安全的,因爲稍微懂一點編程知識的人就可以通過你發送的http請求知道了你的密碼,小白又說了,我密碼加密了,它拿到的也是加密後的密碼,它不知道我的原始密碼它是無法從登錄頁面登錄的。

原文和作者一起討論:http://www.cnblogs.com/intsmaze/p/6009648.html
    但是小白啊,你有沒有想過,有時候我僅僅知道你加密後的密文就夠了,我可以自己僞造http請求,把密文加在請求參數裏面,一樣可以登錄系統的。
    大白這時候有話說了,大白:我可以對密碼進行加鹽。好,我們先看加鹽是什麼,加鹽簡單說就是程序對用戶設置的原始密碼後面追加隨機數來加強用戶密碼的複雜性,然後再對組合後的密碼進行加密進行存儲,用戶每一次登錄,前端先對用戶輸入密碼進行加密傳輸到後端,然後後端獲得用戶賬號到數據庫找到該用戶的鹽,再和傳來的明文組合一起進行一次加密後與數據庫中的密碼進行對比來判斷是否是符合用戶。但是啊,大白,你看,這樣做,並無法控制其他人通過你http請求獲得密文,獲得後,人家照樣大搖大擺使用你的身份登錄系統進行操作。
    好,大白讓我跟你講講加鹽的真正意義:加鹽的意義不是爲了保證密碼在網絡傳輸的安全性,而是防止數據庫被人入侵後,由於原始密碼太過簡單,被人分析出來,進而知道了密碼。直接對密碼進行MD5處理後,反向解密確實難度很大,但還是可以找出破綻的 例如:兩個人或多個人的密碼相同,通過md5加密後保存會得到相同的結果。破一個就可以破一片的密碼。如果用戶可以查看數據庫,那麼他可以觀察到自己的密碼和別人的密碼加密後的結果都是一樣,那麼,別人用的和自己就是同一個密碼,這樣,就可以利用別人的身份登錄了。那麼我們以前的加密方法是否對這種行爲失效了呢?其實只要稍微混淆一下就能防範住了,這在加密術語中稱爲“加鹽”。具體來說就是在原有材料(用戶自定義密碼)中加入其它成分(一般是用戶自有且不變的因素),以此來增加系統複雜度。當這種鹽和用戶密碼相結合後,再通過摘要處理,就能得到隱蔽性更強的摘要值。
    小黑說:你說的這些我都懂,我來告訴你最終的方案吧:在用戶輸入完賬號後,後臺ajax發送用戶的賬號到服務器,這個時候服務器爲該賬號生成一個隨機數驗證碼,響應給前端登錄頁面。
    當用戶輸入密碼後,前端頁面對用戶輸入的密碼進行加密,然後把加密後的密文和獲得服務器返回的驗證碼組合在一起再一次進行加密。然後把該信息發送到服務器,服務器session中保存這這個賬號的驗證碼,服務器會從數據庫獲取該用戶的密碼和驗證碼進行組合再次加密與前端傳來的明文進行對比判斷。
好,接着讓我們分析爲什麼安全,因爲驗證碼是一次性的,, 所以,你在網絡層拿到本次的請求之後,無法做重放攻擊, 因爲驗證碼是不正確的.而當你獲取新的驗證碼, 但你並不知道 組合之前的內容[md5(md5(密碼) + 用戶的QQ號)] 是什麼 , 所以你無法重新發送本次請求實現登陸的目的.32位MD5 + 4位驗證碼 總計 36位的字符串, 你去破解吧. 估計等你掛了你也破解不出來.至於服務端的校驗, 只要將記錄下來的MD5值(而不是記錄的密文), 進行同樣的運算, 得到的結果與提交上來的一樣, 即密碼正確.驗證碼的內容是服務器下發的,而且是一次性的,所以 客戶端無法僞造, 也無法重用.
下面是QQ之前網頁的源代碼片段:
Q 網頁上的登陸模塊(全程HTTP/GET請求).
QQ 在登陸時,對用戶輸入的密碼加密的JS代碼爲:

function getEncryption(password, uin, vcode, isMd5) {
        var str1 = hexchar2bin(isMd5 ? password : md5(password));
        var str2 = md5(str1 + uin);
        var str3 = md5(str2 + vcode.toUpperCase());
        return str3
    }

白話就是: md5(md5(md5(密碼) + 用戶的QQ號) + 驗證碼)
現在你知道如何在http協議下保證密碼安全性了沒有。

 

然後我們在說說用戶登錄後,我們是否要把用戶的密碼保存到session中。

以前同事寫的密碼修改部分代碼,發現將用戶登錄的密碼存在session中,然後判斷原密碼時直接從session中讀取。

把密碼存在session中安全嗎?
session的保存方式相對來說比較安全,因爲信息存儲在服務器的 
而cookie的方式由於對服務器端來說是不可控的,始終對用戶信息泄露是一個危險,但是也有很多采用cookie存儲用戶信息的,通常是採用加密的方式來進行處理。
我們經常看到很多網站設置記住用戶名密碼,就是採用cookie的方式 

可行性上,我不建議這麼做。就連sun公司在是設置password的時候,都用transient 來管理, private transient String password;都不希望password序列化掉, 所以我們跟不能爲了方便而把密碼存入session中來爲了方便。 

 

最後我們談談加密的本質:它其實是對原有內容的混淆,目的是提高從表面結果反推達到目的的成本。
在網頁提交(其實所有的通信都有這個問題)密碼這個問題上,需要有幾個維度來保證安全,

 

首先是切面的安全性,對於一次提交首先保護的是密碼本身,從最早的Base64到MD5或是SHA都可以做到這一點,但是Base64是可逆的,對於密碼本身的保護是很弱的,哈希算法解決了這個問題,將不同長度的數據轉換成統一長度的大數字,而理論上這個數字對應無窮多解,但限於密碼的輸入有限制,其實是可逆的,所以從1次混淆的MD5變成了3次混淆的SHA,但是隨着現代計算機技術的進步,逆運算的成本不斷降低,人們不得已要使用更大的數字來提高這個難度,但是爲了向成本和發展妥協,人們不得已使用統一的算法,在CS時代由於很難侵入到CS兩端,所以相對的雙方使用的算法是保密的,破解難度相對比較大,BS由於爲了保證開放性,特別是js本身就是明文算法,所以其實只能說防君子不妨小人,所以就有了安全控件,控件的唯一目的是用2進制代碼來隱藏加密的算法,不知道算法,也就很難破解密文。
 

第二維度就是時間,如果密碼一樣加密結果也會一樣,那麼在不使用明文的情況下,可以使用加密過後的數據來模擬用戶登錄的動作也是可以的,所以純粹對密碼的加密其實不能解決這個問題,所以有了鹽值,讓同一個數據在不同情況下結果依舊不一致,但是鹽值需要約定,總會被人找出規律,只是成本又高了點,所以還是不安全,這就引發了通訊安全的問題。所以出現了https使用非對稱加密來保護數據通路上的安全,讓通訊變得不可窺視。但是還有個東西叫木馬,所以人們在輸入上繼續做文章,包括混淆輸入,就是軟鍵盤,好的控件不會把明文存在內存裏,這很重要,以前的VB、Dephi密碼控件都僅僅看不到,實際內存裏面都是明文,很容易被病毒和木馬利用,所以一般來說現在最安全的bs系統使用控件保護輸入,隱藏自己的HASH算法,用HTTPS保護通訊。


 

更多關於加鹽的介紹可以參考這篇文章:http://blog.jobbole.com/61872/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章