老調重彈——你存儲的密碼做Hash了嗎?

看了標題,你馬上會明白我這篇文章要講什麼——密碼的Hash化,雖然這並不是什麼新技術,也不是高端技術,但它確實很有意義。當然如果僅僅因爲它有意義還不足以讓我寫這篇文章。有些人會覺得不就是密碼Hash嘛,沒有什麼必要,還會影響網站的處理速度,如果你是這些人中的一員,請聽我說兩個真實的故事。

故事1
某***通過一些技術手段進入了一個剛剛起步的網站(至於用什麼方法大家就不要多問了,再說與這篇文章關係不大),這個網站的安全問題很嚴重,嚴重到可以拿到所有用戶的用戶名、郵箱、網站密碼。大家知道,很多人不喜歡記太多密碼,他們在任何網站使用的永遠是同一個密碼。好了,問題出來了!這裏面有大量的gmail、msn賬戶,也就是說知道郵箱,知道密碼,我們不但能進入這個人的電子郵箱,還能進入googletalk或msn這樣的及時聊天系統,從而獲得更多的私人信息和關係網信息,甚至能冒用這個人的身份進行詐騙,還好這個***並沒有惡意,並沒有採取進一步的行動,否則後果不堪設想。

這個故事告訴我們在不同的網站、郵箱要使用不同的密碼,當然要選擇自己好記些的,但千萬不要爲了圖方便而都用一樣的密碼,這是很危險的!特別是涉及金融、銀行方面的網站更要使用高強度密碼(有數字、大小寫字母、下劃線等組成),這樣可以防止一些人用字典進行密碼破解。從另一個角度看,這個故事還告訴我們,作爲網站的開發者你必須時刻記住一點,在任何時候都不應該把機密數據用明文保存或傳遞,數據從進入系統那一刻開始網站就有義務保證數據的安全性,所以必須作相應的安全處理。對於密碼,我們應該對密碼做Hash,大家應該知道一個字符串無論何時做Hash,出來的結果是一樣的,雖然從理論上講會出現不同的字符串產生相同的Hash序列的情況,但是這種概率很低,基本上是中彩票的概率,這也是爲什麼要用Hash逆推出原文來幾乎是不可能的,我們可以認爲這種方法是安全的。

故事2
早上我在公交車上聽到幾句電話對話
甲:你密碼忘記了?
....
甲:這個沒關係,我幫你去問問IT部,他們知道密碼是多少?
....

可能乍一看,這段對話很正常,沒有什麼特別的,但是我們可以分析一下其中的含義。密碼忘了我們第一個想到的是什麼——要回密碼,但這能夠實現嗎?對於一個公司內部而言,這種密碼獲取還相對簡單,畢竟大家可以方便地證明自己的身份,所以從業務上來講似乎拿回密碼一點問題都沒有,但實際上,技術上不允許我們這麼做。我們剛纔說到過Hash是不可逆的,如果一個網管告訴你他可以幫你拿回原來的密碼,這說明什麼?說明密碼很有可能是用明文存儲的,這在很多情況下是很危險的,管理員可以利用自己的職權,獲得一些人的密碼,然後進入那些人的私人郵箱(非公司郵箱)盜取信息。即使有些密碼是加密存儲的,如果它是可逆的那也是不安全的,只要有加密後的字符串,且知道加密算法和密鑰,也能輕易獲得原密碼,這同樣是很危險的,當然相對而言這種方法要難許多、不是每個人都能做到的,但在第一個故事中我們看到如果某個***進入了這樣的系統,仍然有辦法獲得原密碼,畢竟***的技術水準要高出許多。從這一點我們應該意識到加密的密文必須不可逆,否則會帶來進一步的信息泄漏。

好了,通過上面兩個故事,我想大家應該對密碼Hash的必要性比較認同了,希望以後在寫code或者做架構設計的時候一定要把這個它考慮進去。從技術角度講,我們只能爲用戶重置密碼,但不能告訴用戶原密碼是什麼,這一點live.com就做得很好,如果哪個網站可以拿回原密碼,說明他不夠安全,建議馬上改密碼!用一個和你的郵箱不一樣的密碼,特別是註冊這個網站時使用的那個郵箱。

下面我順便講講.NET下如何實現密碼Hash化。有人說,Hash可以用System.Security.Cryptography命名空間下面的加密類來實現,對,說得沒錯,我們的確可以這麼做,但這似乎還是有些麻煩~~(我比較懶,呵呵)其實呢,.NET提供了一個專門用於做Password Hashing的方法,這在.NET 1.1中就有了,定義如下:

public static string HashPasswordForStoringInConfigFile ( 
   
string password, 
   
string passwordFormat
)


第一個參數password就是密碼,而第二個參數則是要使用的Hash算法,這個值只能是FormsAuthPasswordFormat枚舉的成員(位於System.Web.Configuration下),不過不清楚爲什麼不直接傳枚舉類型。FormsAuthPasswordFormat有三個枚舉成員,它們是Clear、MD5、SHA1,其中的Clear就是不加密,直接用明文的意思。

具體的例子MSDN上有,我就不抄了,大家可以參考:http://msdn2.microsoft.com/en-us/library/system.web.security.formsauthentication.hashpasswordforstoringinconfigfile.aspx

加了一個基於Salt的密碼Hash實現,代碼如下:
    public class PasswordHelper 
   

       
public static string CreateSalt(int size) 
       

           
//Generate a cryptographic random number. 
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
           
byte[] buff = new byte[size]; 
            rng.GetBytes(buff); 
 
           
// Return a Base64 string representation of the random number. 
            return Convert.ToBase64String(buff); 
        }
 
 
       
public static string CreatePasswordHash(string pwd, string salt) 
       

           
string saltAndPwd = String.Concat(pwd, salt); 
           
string hashedPwd = 
             FormsAuthentication.HashPasswordForStoringInConfigFile( 
             saltAndPwd,
"sha1"); 
 
           
return hashedPwd; 
        }
 
 
       
public static bool PasswordMatch(string current,string salt,string savedPasswordHash) 
       

           
string currentPasswordHash=CreatePasswordHash(current, salt); 
           
return (currentPasswordHash == savedPasswordHash); 
        }
 
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章