9. 密碼是如何存儲的?
9-1 認識雜湊函數
雜湊函數是一種能將數據變成摘要(digest)的算法,執行 irb
,然後輸入以下代碼實驗看看:
require 'digest'
Digest::SHA1.hexdigest '12345678'
得到 "7c222fb2927d828af22f592134e8932480637c0d"
雜湊函數有一些特性:
- 相同的數據,每次都會得到一樣的摘要
- 是單向的,無法逆推:只知道摘要的話,沒有辦法能夠透過計算知道本來的數據長怎樣。例如給你
7c222fb2927d828af22f592134e8932480637c0d
,沒有算法可以逆推回來。除非有一個對照的字典。
9-2 雜湊函數的用途
雜湊函數非常有用,可以拿來快速比較兩個文檔是否相同,而不需要實際比較文檔內容,例如:
- Git 每次的 commit,都會有一個摘要。不同的摘要就代表 commit 內容不同。Git 用這個摘要值當作每次 commit 的唯一識別 ID。
- 網路傳檔的時候,透過比較這個摘要,就可以知道下載了完整正確的檔案。
- 在 Rails 中,Asset pipeline 會將 CSS 和 JavaScript 壓縮,檔名就是透過雜湊函數產生的。這是因為瀏覽器會快取靜態檔案,如果 CSS/Javascript 內容有修改的話,用戶瀏覽器可能不知道有新版而使用到舊的 CSS/JS 檔案。但是因為檔名用了雜湊函數的關系,內容一改檔名就會變得不一樣,那麽瀏覽器就會下載新的檔案了。
- 存儲用戶密碼。大家已經會用 Devise 在 Rails 中實做 User Model,在 users table 中實際的欄位是
encrypted_password
用戶註冊時輸入的密碼,在實際存儲進資料庫時,會先經過雜湊函數,變成摘要值。資料庫裡面沒有存用戶的明碼,而是存密碼摘要後的值。
而下次用戶要登入的時候,將用戶輸入的密碼摘要一次,與資料庫中存的密碼摘要進行比對,就可以知道密碼對不對了。
這樣的好處是什麽呢?
- 資料庫不會存用戶的明碼,所以即使是資料庫管理員,也不會知道用戶真正的密碼是什麽。知道
encrypted_password
並沒有什麽用,因為我們無法逆推。也無法用這個encrypted_password
做登入。 - 萬一資料庫整個外洩了,駭客也無法知道用戶的密碼
不過,目前是市面上仍有很多網站是直接存儲用戶明碼,這會造成用戶隱私很大的危害。因為管理員或駭客(如果資料庫外洩)可以直接看到你密碼,然後很多人在不同網站中,會沿用一樣的密碼。
要怎麽判斷一個網站有沒有存明碼呢?只要試試看忘記密碼程序即可,如果網站直接將你的密碼寄給你,那就代表他的 資料庫存明碼。如果網站要求你重新設定密碼(就像 Devise 一樣),就表示這網站有安全意識。