在某些情況下,花椒會有所幫助。
作為一個典型示例,假設您正在構建Web應用程序。 Web應用程序代碼(在某些Web應用程序框架中運行,ASP.NET MVC,Python上的金字塔無關緊要)和用於存儲的SQL數據庫。 Web應用程序和SQL DB 運行在不同的物理服務器上。
最常見的數據庫攻擊是成功的SQL注入攻擊。這種攻擊不一定能訪問您的Web應用程序代碼,因為Web應用程序在其他服務器&用戶ID上運行。
您需要安全地將密碼存儲在數據庫中 ,並提出以下形式的內容:
$ hashed_password = hash($ salt。$ password)
其中 $ salt
與 $ hashed_password
表示形式以及為每個新密碼或更改的密碼隨機選擇的 一起存儲在數據庫中。每個密碼哈希方案最重要的方面最重要的方面是 hash
是一種 slow 加密安全哈希函數,請參見 https://security.stackexchange .com / a / 31846/10727了解更多背景知識。
然後問題是,假設為常量添加一個恆定值幾乎是零的努力。應用程序代碼,並且該應用程序代碼通常不會被破壞進行SQL注入攻擊,那麼下面的內容是否比上面的要好?
$ hashed_password = hash($ pepper。 $鹽。 $ password)
,其中 $ salt
以明文形式存儲在數據庫中,而 $ pepper
是以明文形式存儲在數據庫中的常量。應用程序代碼(如果代碼在多個服務器上使用或源是公共的,則為配置)。
添加此 $ pepper
很容易-您只是在代碼中創建一個常量,輸入一個較大的加密安全隨機值(例如,來自/ dev / urandom hex或base64編碼的32byte)並在密碼哈希函數中使用該常量。如果您已有用戶,則需要一種遷移策略,例如,在下次登錄時重新哈希密碼,並在哈希旁邊存儲密碼哈希策略的版本號。
答案:
使用 $ pepper
確實增加了密碼散列的強度,如果數據庫的損害並不意味著的應用程序。在不了解Pepper的情況下,密碼仍然完全安全。由於密碼特定的鹽,您甚至無法找出數據庫中的兩個密碼是否相同。
原因是 hash($ pepper。$ salt。$ password)
使用 $ pepper
作為鍵並輸入 $ salt。$ password
作為輸入有效地構建偽隨機函數(對於理智的 hash
候選對象,例如帶有SHA *,bcrypt或scrypt的PBKDF2)。偽隨機函數的兩個保證是,您不能從秘密密鑰下的輸出推論輸入,也不能在不知道密鑰的情況下從輸入推論輸出。這聽起來很像哈希函數的單向屬性,但是不同之處在於,使用像密碼這樣的低熵值,您可以有效地枚舉所有可能的值,並在公共哈希函數下計算圖像,從而找到其值圖像與原圖像匹配。使用偽隨機函數,沒有鍵就無法做到這一點(即沒有胡椒),因為沒有鍵就無法計算單個值的圖像。
如果可以長時間訪問數據庫,並且仍然可以從外部正常使用該應用程序,則 $ salt
在此設置中的重要作用將發揮作用。如果沒有 $ salt
,則可以將您控制的帳戶的密碼設置為已知值 $ passwordKnown
,然後將哈希值與未知密碼的密碼進行比較 $ passwordSecret
。作為 hash($ pepper。$ passwordKnown)== hash($ pepper。$ passwordSecret)
的情況,當且僅當 $ passwordKnown == $ passwordSecret
時,您才可以將未知密碼與任何選擇的值(出於技術上的考慮,我假設哈希函數具有抗碰撞性)。但是如果加上鹽,則當且僅當 $ salt1時,您會得到 hash($ pepper。$ salt1。$ passwordKnown)== hash($ pepper。$ salt2。$ passwordSecret)
。 $ passwordKnown == $ salt2。分別為 $ passwordKnown
和 $ passwordSecret code分別隨機選擇了$ passwordSecret
和 $ salt1
和 $ salt2
。 >鹽將永遠不會相同(假設隨機數足夠大,例如256位),因此您將無法再將密碼進行相互比較。