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

發布日期:2017-06-12首頁 > 安全資(zī)訊


66372-20170608152133622-227970294.png


    如何給服務器端做最基本的密碼安全。做 app 做網站,難免要和服務器、後台、數據打交道,那麽作爲一(yī)名後台開(kāi)發,當涉及到注冊登錄,你最應當想到的應該是用戶的安全,尤其是密碼安全。

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

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

    通信安全

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

    信息摘要 MD5 SHA1

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

    固定鹽

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

    用戶是不可信的

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

    真正的密碼加鹽

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

    那麽選擇了加密算法,該加密什麽内容呢?加密的是 用戶的密碼 a 以及我(wǒ)們在服務器端實時生(shēng)成的随機鹽 b,即 a+b

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

    可是,這樣是安全了,那麽上文說的,下(xià)次用戶登錄,我(wǒ)又(yòu)該如何才能判斷用戶輸入的密碼正确呢?畢竟創建的時候是随機的,總不能每次都找回密碼吧!

    所以,這個鹽你不能扔,得同樣存在數據庫裏,當用戶輸入密碼,你就要把密碼和鹽合并,然後計算哈希,把得到的結果和數據庫中(zhōng)的密碼對比,如果一(yī)緻,那就說明密碼是正确的啦!同時,如果黑客拿到了你的數據庫,他們依舊(jiù)無法得到用戶真正的密碼,得到的是一(yī)堆完全不重複的密碼哈希以及完全随機的鹽。

    過短的鹽和不加沒啥區别

    你的随機字符串太短,那基本上和沒有是一(yī)樣的,使用長一(yī)點的随機鹽才更有意義,另外(wài),不要使用你代碼基本框架裏提供的 普通 僞随機數生(shēng)成器,那些随機數不是爲密碼安全準備的,應該使用專門的随機生(shēng)成,比如 Python 中(zhōng)的 os . urandom ( n ) 具體(tǐ)的使用方法:

    from os import urandom

    from base64 import b64encode

    salt = b64encode(urandom(64)).decode('utf8')

    擴展性

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

    總結

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