昨天有說到在儲存使用者的密碼時,不管是用 AES 把他們加密起來,或是經過 SHA1 雜湊之後再進資料庫,都已經不夠安全,所以今天這邊還要提出另外一種更好的方式,讓你更妥善的把使用者的密碼保管好
就如昨天說的,單純的雜湊之所以不夠安全,是因為 CPU 計算雜湊的速度太快了,因此只要有人建表把 00000000
到 zzzzzzzz
的 SHA1 雜湊值全部都算出來,就可以發現 1785bf0ed0f6346210af2d64b310a99b4024ce44
是由 love1234
經過 SHA1 出來的結果,進而得到原本的密碼
雖然現在的 CPU 真的跑很快,但也是有他的極限的,剛剛的 love1234
之所以可以被破解其實是因為他太簡單了,只要把長度為 8 的字串雜湊值都算過一遍就好。而且小寫字母加上數字也才 36 個字元,算一算 36⁸ 大約才 2.8 兆種組合,不用花太多時間就可以建一個表出來
但如果你的密碼又臭又長又亂、包含了大小寫甚至還有一些怪怪的字元,像是 -y]@7k[BSB@3m]r$.>"R
,那以現在電腦的計算速度就還無法破解,因為長度 20 以內由數字、大小寫還有特殊字元組成的字串太多了,算到天荒地老都不見得能算出來。
但身為網站的開發者,不太可能要求所有使用者都設這種密碼,畢竟這種密碼太難記,每天光忘記密碼就飽了。所以大部分的使用者密碼還是會像 love1234
,甚至還有更簡單的 123456
或是 qwerty
這類的XD,有興趣可以看看維基百科上 最常被使用的 25 個密碼
為了解決使用者密碼太簡單的問題,於是有了所謂的加鹽,他的的基本概念就是使用隨機字串幫使用者的密碼加長**
如果今天有一個新的使用者要註冊,這時我們的後端系統就隨機生成一個長度十的字串稱作 Salt,計算 Hash 時就把使用者輸入的密碼跟 Salt 合在一起算。以下圖為例,若使用者 SmallTown 註冊時後端隨機生成的鹽是 h7.@-]%<#L
,而他輸入的密碼是 helloworld
,那就計算 SHA1("helloworld" + "h7.@-]%<#L")
得到 f80533d9f6a59796080258d2d4a2e2ec548322d4
,然後把 salt 跟 hash 結果都存起來
因為 salt 會存在資料庫裡面,所以當有天小城要登入時,就把他輸入的密碼加上資料庫內的 salt 雜湊,看會不會得到相同的雜湊值,如果相同的話代表小城輸入的密碼是對的
安全性方面,因為那一大串 f80533d...
是 helloworldh7.@-]%<#L
經過 hash 後的結果,而 helloworldh7.@-]%<#L
本身也夠長夠亂,網路上的表根本不可能包含這個字串,所以把 f80533d...
那一大串丟到網站上也破解不出來,換句話說無法得知小城的密碼是 helloworld
但如果駭客真的拿到你家資料庫,代表他同時拿到每個人的 salt 和 hash value,雖然駭客無法像先前那樣直接查網路上的表,但他還是可以用自己的電腦算雜湊值,從 aaaaaaaaaa
到 zzzzzzzzzz
把每個字串都加上 h7.@-]%<#L
再做 hash 還是可以算出小城的密碼是 helloworld
雖然真的要算的話也是可以,但因為每個人的 salt 都不同,所以要把所有使用者的密碼都算出來的話可能需要租一台超級電腦來算。如果駭客得到使用者的密碼後無法獲得相對應的利益,那其實就是白花錢而已,所以很多駭客看到資料庫內的密碼有加鹽就會放棄了
換句話說,身為網站開發者,在儲存密碼時至少要加鹽再雜湊,而且隨機產生的 salt 盡量要含有特殊字元,這樣才能保證使用者的密碼安全
今天介紹了所謂的「加鹽雜湊」,雖然說現在的網站應該都要做到這種程度才能保障使用者密碼的安全,但其實有很多網站還是停留在普通的 SHA1 雜湊,甚至少數還有直接存明碼的 ?,所以平常在註冊時個網站還是盡量用不同的密碼,才不會被這些網站拖下水
雖然加鹽雜湊對現在的 CPU 計算速度來說已經足夠安全,但以後的 CPU 只會越來越快,因此明天還要介紹一種更好的方式,讓你的網站即便有一天 CPU 比現在又快一千倍,也不會擔心使用者的密碼被反解回來~