如何給服務器端做最基本的密碼安全

做 app 做網站,難免要和服務器、後台、數據打交道,那麼作為一名後台開發,當涉及到註冊登錄,你最應當想到的應該是用戶的安全,尤其是密碼安全。

現在安全界幾乎天天都有某網站、某公司被脫褲,也就是整站的數據庫被偷走被下載。那麼你的用戶數據全部落入了歹徒手中,應該怎麼防範即使如此,歹徒也不能拿到用戶的真實密碼呢?

這裡我們定義,“不能拿到”指的是在“有生之年”他得不到,理論上如果有足夠的時間(比如10000000年)那麼任何的密碼總能解密的,那麼如果一個加密方案在當今現有算力的前提下幾百年不能被算出來,那我們就認為這個加密是安全的;“真實密碼”這裡我們指的不是用戶輸入了的那個密碼,而是能夠用來登錄我們網站的那個字符串(你要是真的明文保存了用戶的密碼……那就真的是明文的了)。

通信安全

這一點是最大的前提,否則任何人都能獲取用戶和服務器之間的通信,那你安全就很難做了,最基本的要用個 HTTPS,如果追求高質量,那麼可以自己簽發一個證書。

信息摘要 MD5 SHA1

這應該是大家最熟悉的哈希算法,它們被廣泛用於數據庫密碼安全領域——當然,還有黑客的密碼破解字典、彩虹表等等。一旦你的數據庫洩露,如果你直接把用戶的密碼進行了一個 MD5 或者 SHA1,那幾乎等同於明文。

固定鹽

密碼哈希前加鹽是業界安全通用做法,給用戶做信息摘要之前,先加入特定的內容,然後合在一起做哈希,這樣就得到了一個不同的哈希字符串,看起來似乎很美妙,但注意,你的鹽是固定的(不然用戶下次登錄怎麼對比?),那麼黑客拿到你的數據庫(甚至逆向等得到了你的鹽),你的加密依舊一定程度上等同與明文——因為黑客很容易就能根據你的鹽製作生成一份全新的字典。

用戶是不可信的

無論是開發網站,還是開發移動應用,請在心裡時刻謹記這一標題——用戶是不可信的。我們不能雙手合十或者放到膝蓋上來祈禱用戶都是道德高尚的聖人,所以你單純在客戶端做加密,是萬萬不足以保護用戶的安全的。另外,就算你保護的很好,那麼中間人攻擊呢?所以,我們一定要保證,所有的必要加密操作,都要在服務端實現,客戶端可以進行簡單的加密以避免用戶的明文密碼在傳輸過程中被竊取,但這個簡單的加密絕對不能直接存入數據庫。

真正的密碼加鹽

那麼到底怎麼做才能達到必要的,或者說業界規範的安全呢?首先是合適的摘要算法,MD5或者SHA1已經過時了,使用更安全的 SHA256 進行加密。

那麼選擇了加密算法,該加密什麼內容呢?加密的是 用戶的密碼 a 以及我們在服務器端實時生成的隨機鹽 b,即A + B

這樣的好處是什麼呢?用戶a 和 用戶b 同時使用了弱密碼 123 作為他們的密碼,那麼如果你直接進行哈希,得到的字符串毫無疑問是相同的,那麼黑客至少可以直接判斷這兩個用戶使用了相同的密碼。如果你加了隨機生成的字符串,那麼這兩個用戶即使使用了相同的密碼,也會在數據庫存入完全不同的字符串,這樣就保證了當黑客竊取了你的數據庫,他完全無法判斷哪些人的密碼一致從而進行針對性的弱口令破解。

可是,這樣是安全了,那麼上文說的,下次用戶登錄,我又該如何才能判斷用戶輸入的密碼正確呢?畢竟創建的時候是隨機的,總不能每次都找回密碼吧!

所以,這個鹽你不能扔,得同樣存在數據庫裡,當用戶輸入密碼,你就要把密碼和鹽合併,然後計算哈希,把得到的結果和數據庫中的密碼對比,如果一致,那就說明密碼是正確的啦!同時,如果黑客拿到了你的數據庫,他們依舊無法得到用戶真正的密碼,得到的是一堆完全不重複的密碼哈希以及完全隨機的鹽。

過短的鹽和不加沒啥區別

你的隨機字符串太短,那基本上和沒有是一樣的,使用長一點的隨機鹽才更有意義,另外,不要使用你代碼基本框架裡提供的普通偽隨機數生成器,那些隨機數不是為密碼安全準備的,應該使用專門的隨機生成,比如 Python 中的 .urandom的(ñ) 具體的使用方法:

擴展性

別以為這就收工了,你的加密方式最好也順便存入數據庫與用戶對應,這樣方便你日後如果做了加密方式升級(SHA256 也總有過期的一天),那麼你依舊可以新舊同時進行兼容,不至於強制所有用戶立即修改密碼。

總結

總之,通過真正的密碼加鹽哈希,你得到了業界標準的安全要求,當然,這個哈希算法也決定了你根本上的安全程度。這只是作為一個服務器安全的最基本的一環,比如你所有提交的數據應該經過簽名,用戶登錄應該得到一個 token 每次用 token 進行驗證而不是本地保存用戶的賬號密碼……

想要更進一步了解密碼加鹽,移步:正確使用密碼加鹽散列[譯]

本文由 落格博客 原創撰寫:落格博客 » 如何給服務器端做最基本的密碼安全

轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2759.html

關於作者

R0uter

如非聲明,本人所著文章均為原創手打,轉載請註明本頁面鏈接和我的名字。

發表評論

您的電子郵件地址不會被公開. 必填字段標 *