如何安全儲存口令?了解下Hash加鹽的原理

2021-09-19 19:52:36 字數 4229 閱讀 4073

最近要開發乙個專案,其中涉及到了使用者口令儲存(大家習慣稱之為密碼),毫不誇張的說,如果方案設計的不合格,未來再想補救就會困難重重。

首先,口令加密是非常系統化的乙個工程,涉及到多方面,比如**安全性,系統安全性,資料儲存安全性,任何乙個方面出現漏洞,可能就會導致口令的洩漏。嚴格的說,誰也不能保證自己系統的使用者口令不被外洩,我們要做的就是盡可能的減少這種風險。

其次我寫的文章主要描述口令儲存方案的設計,至於 web 程式安全,伺服器安全等方面不會涉及,比如手機簡訊驗證、圖形驗證碼、前台登入限制這些策略對保護口令安全也非常重要,但不是描述的重點。

什麼是口令呢?就是使用者自行設定的一段字串,使用者要對自己的口令安全性負責,要認識到口令的重要性,因為一旦口令因為各種原因洩漏,那麼攻擊者就能以使用者的身份進行任何操作。

從這個角度來看,使用者應該盡量設定強口令(比如多種字元的組合、定期修改);系統也有義務強制要求使用者使用強口令。

從破解的角度看,不管系統採用什麼加密演算法,強口令也更有安全性,破解的難度也會加大,從歷史上出現的口令洩漏事件來看,很多是因為使用者的口令太弱了。

從系統設計的角度看,口令儲存到磁碟(比如 mysql)的時候,不能是明文的,道理很簡單,如果 mysql 出現安全漏洞,比如被攻擊者拖庫了,那麼攻擊者不費吹灰之力就能獲取使用者的明文口令。

通過密碼學演算法可以將明文口令轉換為無規則的密文,即使攻擊者知道了口令的密文,也不能破解出口令明文,這樣相當於口令沒有洩漏(當然事情沒有那麼理想,所以才需要相對完美的口令保護方案)。

那麼使用什麼密碼學演算法呢?比較流行的解決方案就是密碼學 hash 演算法(比如 sha1),很多開發者喜歡對口令進行 hash 運算,然後將運算值儲存到資料庫中。使用者登入的時候,程式用同樣的 hash 運算口令後,將運算值和資料庫中的 hash 值進行比較,如果相同,表示登入成功。

密碼學 hash 演算法有什麼特點?大家都用它保護口令呢?根本的原因在於密碼學 hash 演算法具備單向性,也就是說 hash 值不能被反解,同時不同的口令其 hash 值是不一樣的,嚴格的說密碼學 hash 演算法很難發生碰撞

為什麼我一直強調密碼學 hash演算法,普通的 hash 演算法能運算口令嗎?不能,普通的 hash 演算法主要用於資料結構中(比如 hash 表),它很容易發生 hash 碰撞,想想看,不同的口令如果 hash 值一樣,那麼我用自己的口令也許能登入別人的賬戶了。

所以說只有安全的密碼學 hash 演算法才能用於保護口令,另外也要注意的是 hash 運算口令不代表加密,因為它不是加密演算法(對稱加密演算法,非對稱加密演算法才是)。

那麼對於口令來說,應該使用 md5 還是 sha1 演算法?本質上並沒有太大的差別,雖然這二種演算法理論上已經發生了碰撞,但在實際使用過程中很難找到兩個不同值具備相同的 hash 值。尤其對 hash 進行加鹽後(後面會說),選用 md5 還是 sha1 沒有太大的差別。

如果單純用密碼學 hash 演算法運算口令,很容易被破解,接下去說說幾種攻擊方法。

(1)字典攻擊和暴力攻擊

比如攻擊者拖庫了,得到了所有的口令 hash 值,現在的目的就是找出口令明文。字典攻擊和暴力攻擊並沒有太大的區別,字典攻擊可以認為是暴力攻擊的一種,它將常用的字元(暴力攻擊是將各種可能的字元)組合起來進行 hash 運算,然後和資料庫中的 hash 值進行比較,如果相同,表示使用者的口令被成功破解。

密碼學 hash 演算法如果用於運算口令,有個最致命的弱點就是它的運算速度太快了,如果僅僅對口令進行 hash 運算,那麼很容易被破解;而且如果口令本身就是弱口令,那麼破解的速度就更快了。

不管採取何種解決方案,都有可能被暴力破解,只是時間的問題。但如果採用相對完善的 hash 解決方案(比如 hash 加鹽,後面會講),那麼被暴力破解的機率會小很多。

有些同學們會問,如果沒有被拖庫,暴力攻擊還能進行嗎?也可以,攻擊者可以組合各種字元,然後呼叫登入介面,不斷進行攻擊,如果介面返回成功,表示口令被破解了。

為了避免這樣的攻擊,可以採取驗證碼和其它策略保護登入介面,但這是另外乙個層面的問題了。

(2)查詢表

這是比字典攻擊更有效的一種方式,攻擊同種 hash 演算法非常有效率。基本的做法就是預運算字典中的口令,然後將口令和口令對應的密文儲存到乙個資料結構中(比如 hash 表或者 memcached),然後可根據口令明文和密文進行查詢,查詢速度非常快。

(3)彩虹表

彩虹表和查詢表很類似,查詢表使用的儲存較多,運算速度較快;而彩虹表儲存較小,運算較慢,相當於用空間換時間。

原理我並沒有研究,最重要的就是 r 運算(reduce function),它不是 hash 函式的反函式,它能將乙個 hash 值轉換為乙個明文(不是明文)。

構建彩虹表的過程:對乙個口令組合進行不斷的 hash 運算、r 運算,持續 k 次後得到一條鏈,然後將鏈條的頭部和尾部儲存起來(中間的不要)。

那麼如何破解呢?同學們還是直接看 wiki 或找一些專門的文章,在此文中,只要記住,彩虹表能夠破解口令明文,而且很有效。

那麼如何防止彩虹表和查詢表攻擊呢?最好的方法就是 hash 加鹽(hash+salt)。或者這麼說,如果將來你要設計口令儲存方案,hash 加鹽雖然不是最好的方法,但如果實施得當,也是比較安全的。

簡單 hash 就是對口令進行單純 hash 運算,hash 加鹽是在口令後面加一段隨機值(salt),然後再進行 hash 運算。

不管是彩虹表還是查詢表,如果兩個使用者的口令相同,他們的密文也必定相同,攻擊就相對容易,構建的口令組合相對減少,乙個使用者的口令密文被破解後,那麼具有相同口令密文的使用者其口令也被破解了。

而加鹽就是保證同樣的口令其密文值不一樣,這樣攻擊者構建的彩虹表和查詢表的將非常巨大,破解的速度和成功率將極低,換句話說,優秀的口令儲存方案就在於即使被拖庫了,攻擊者也沒有啥辦法。

現在重點就是 salt 值如何設定了,salt 一定要不可**,且高度隨機,如果可**的話,攻擊者就能猜測出 salt,這樣即使 hash 加鹽了,本質上和純 hash 加密沒有區別。

那麼如何生成 salt 呢?請使用密碼學中的偽隨機函式(csprng),比如 php 語言中可以使用 openssl_random_pseudo_bytes() 函式,千萬不要使用非安全的 rand() 函式。安全的偽隨機函式的關鍵在於種子(seed),此處就不多描述了,記住一點,獲取 salt 需用標準的密碼學演算法,不要想當然自行設計。

salt 值獲取還有幾個誤區,比如使用和使用者有關的屬性(比如 email,手機號)充當使用者的 salt,這樣很容易被猜測。

也要避免使用全域性 salt,如果將全域性 salt 值硬編碼,那麼一旦**洩漏或伺服器被攻擊,攻擊者在構建字典的時候,在各種字元組合後面加上 slat,然後再 hash,想想看,是不是很容易攻擊?

全域性 salt 另外乙個弱點在於,攻擊者很容易找出規律,因為相同口令其密文值也是相同的。

salt 值也不能太短,理論上 salt 長度應該和 hash 值長度一致。

乙個設計良好的 salt,攻擊基本很難成功,想象下,乙個口令再加上 salt,攻擊者要構建多少個 hash 演算法的輸入值?而且有了 salt,即使使用者的口令相對弱一點,也能有效保障使用者的安全性。

hash 加鹽的根本目標是:即使被拖庫了,攻擊者也很難破解出密文。雖然它不是標準的口令安全儲存解決方案,但從結果上來看,也是非常不錯的一種設計。

最後非常非常重要的一點就是,salt 不能和口令密文儲存在一起,不然就和沒有 salt 一樣,因為攻擊者拖庫後,構建字典非常簡單,因為它能夠直接看到 salt,所以一定要分開儲存(比如在不同的機器上),這樣即使口令密文表被拖庫了,而 salt 表沒有被拖庫,也是相對安全的。

salt 看上去雖然是毫無規則的,但本質上是明文的,所以如果想進一步安全,可以可以引入乙個 pepper(乙個公共金鑰),那麼如何加密保護 salt 或密文口令呢?有兩種辦法。

(1)在計算密文口令的時候,採用 hmac 方法(內部還是乙個 hash 演算法):

口令密文=hash(口令+salt+pepper)
(2)或者對密文口令進行加密(對稱加密演算法或非對稱加密演算法)

口令密文=rsa(hash(口令+salt),pepper)
不管採用那種方案,pepper 的安全性非常重要,因為這個 pepper 一旦洩露,對於保護口令沒有太大的作用。

但不管怎麼說,使用 pepper 還是很有積極意義的,畢竟增加了一層保護。

解決方案永遠沒有絕對安全的,只有相對的,至於 pepper 採用那種處理方法,後一篇博文我會描述。

如何安全儲存口令?了解下Hash加鹽的原理

最近要開發乙個專案,其中涉及到了使用者口令儲存 大家習慣稱之為密碼 毫不誇張的說,如果方案設計的不合格,未來再想補救就會困難重重。首先,口令加密是非常系統化的乙個工程,涉及到多方面,比如 安全性,系統安全性,資料儲存安全性,任何乙個方面出現漏洞,可能就會導致口令的洩漏。嚴格的說,誰也不能保證自己系統...

如何安全地儲存密碼?

用 bcrypt 用bcrypt 用bcrypt 用bcrypt 用bcrypt 用bcrypt 用bcrypt 用bcrypt 用bcrypt 重要的話就是要多多地重複幾次 這些都是通用的hash函式,設計的初衷是為了盡可能快的計算大量資料的摘要。這意味著它們在保證資料完整性方面非常優秀但是對於儲...

企業如何實現資料安全儲存

企業如何實現資料安全儲存 資源來自問道網www.askform.cn askform問道網採用阿里雲提供基礎服務,因此充分利用阿里雲提供的服務來制定策略,從而達到資料安全,可靠,穩定。1.資料可靠性 資料可靠性是第一位,askform問道網的首要職責是保證使用者所有資料不丟失,達到銀行級別的可靠性。...