Posted on 2011-11-29 09:40
陳小東 閱讀(1008)
評論(2) 編輯 收藏
摘要:
1 加Salt散列
2 ASP.NET 2.0 Membership中與密碼散列有關(guān)的代碼
聲明:本文所羅列之源代碼均通過Reflector取自.NET Framework類庫,引用這些代碼僅出于學(xué)習(xí)和研究的目的。
其實,對密碼進(jìn)行散列存儲不是一個新鮮話題了,解決起來也不是很難,但很多人還是不大了解。這個小文只是強調(diào)一下“加Salt散列”這個簡單的技術(shù),并給出ASP.NET Membership所使用的代碼。
本來打算寫一篇介紹如何實現(xiàn)用戶登錄功能的文章的,但因為時間有限,所以先介紹一下密碼的散列,下一篇再介紹用戶登錄。
----
1 密碼必須散列存儲
(內(nèi)容略)
2 加Salt散列
我們知道,如果直接對密碼進(jìn)行散列,那么黑客(統(tǒng)稱那些有能力竊取用戶數(shù)據(jù)并企圖得到用戶密碼的人)可以對一個已知密碼進(jìn)行散列,然后通過對比散列值得到某用戶的密碼。換句話說,雖然黑客不能取得某特定用戶的密碼,但他可以知道使用特定密碼的用戶有哪些。
加Salt可以一定程度上解決這一問題。所謂加Salt,就是加點“佐料”。其基本想法是這樣的——當(dāng)用戶首次提供密碼時(通常是注冊時),由系統(tǒng)自動往這個密碼里撒一些“佐料”,然后再散列。而當(dāng)用戶登錄時,系統(tǒng)為用戶提供的代碼撒上同樣的“佐料”,然后散列,再比較散列值,已確定密碼是否正確。
這里的“佐料”被稱作“Salt值”,這個值是由系統(tǒng)隨機生成的,并且只有系統(tǒng)知道。這樣,即便兩個用戶使用了同一個密碼,由于系統(tǒng)為它們生成的salt值不同,他們的散列值也是不同的。即便黑客可以通過自己的密碼和自己生成的散列值來找具有特定密碼的用戶,但這個幾率太小了(密碼和salt值都得和黑客使用的一樣才行)。
下面詳細(xì)介紹一下加Salt散列的過程。介紹之前先強調(diào)一點,前面說過,驗證密碼時要使用和最初散列密碼時使用“相同的”佐料。所以Salt值是要存放在數(shù)據(jù)庫里的。
用戶注冊時:
1)用戶提供密碼(以及其他用戶信息);
2)系統(tǒng)為用戶生成Salt值;
3)系統(tǒng)將Salt值和用戶密碼連接到一起;
4)對連接后的值進(jìn)行散列,得到Hash值;
5)將Hash值和Salt值分別放到數(shù)據(jù)庫中。
登錄時:
1)用戶提供用戶名和密碼;
2)系統(tǒng)通過用戶名找到與之對應(yīng)的Hash值和Salt值;
3)系統(tǒng)將Salt值和用戶提供的密碼連接到一起;
4)對連接后的值進(jìn)行散列,得到Hash'(注意有個“撇”);
5)比較Hash和Hash'是否相等,相等則表示密碼正確,否則表示密碼錯誤。
3 ASP.NET 2.0 Membership中的相關(guān)代碼
(省略關(guān)于Membership的介紹若干字)
本文Anders Liu僅研究了SqlMembershipProvider,該類位于System.Web.dll,System.Web.Security命名空間中。
首先,要使用Membership,必須先用aspnet_regsql.exe命令來配置數(shù)據(jù)庫,該工具會向現(xiàn)有數(shù)據(jù)庫中添加一系列表和存儲過程等,配置好的數(shù)據(jù)庫中有一個表aspnet_Membership,就是用于存放用戶帳戶信息的。其中我們所關(guān)注的列有三個——Password、PasswordFormat和PasswordSalt。
Password存放的是密碼的散列值,PasswordFormat存放用于散列密碼所使用的算法,PasswordSalt就是系統(tǒng)生成的Salt值了。
網(wǎng)站安全了,程序自然也就復(fù)雜了...
discuz的加密方式:md5(md5($password).$salt),$salt是一個6位隨機數(shù)。
注冊的時候,把用戶的密碼用md5(md5($password).$salt)加密,$salt是一個6位隨機數(shù)字,下面是我的一個獲取6位隨機數(shù)的一個方法:
function randstr($len=6) {
$chars='abcdefghijklmnopqrstuvwxyz0123456789';
// characters to build the password from
mt_srand((double)microtime()*1000000*getmypid());
// seed the random number generater (must be done)
$password='';
while(strlen($password)<$len)
$password.=substr($chars,(mt_rand()%strlen($chars)),1);
return $password;
}
$salt=randstr();把randstr()賦值給$salt,然后用md5(md5(會員提交的密碼).$salt)加密就可以了,但是千萬不要忘了把$salt入庫哦(uc_members表)。
登陸的時候根據(jù)用戶名把$salt取出來,用md5(md5(會員提交的密碼).$salt)匹配密碼,如果一樣就登陸成功了