Pepper
Pepper 是密碼雜湊過程裡額外混入的一把金鑰,而它不存在資料庫裡。它與 salt 的分工是兩件不同的事:salt 每筆紀錄一個、與雜湊存在一起、用來讓相同的密碼產生不同的值;pepper 全系統共用、存在資料庫之外、用來讓外洩的資料本身不足以開始猜。兩者並用,而少了 pepper 不影響 salt 的作用。
概念位置
它的保護是條件性的,範圍要先講清楚:只在資料庫與金鑰分開淪陷時成立。資料隱碼攻擊取走整張表、備份檔案外流、唯讀副本被存取,這幾種是它擋得住的形態;整台伺服器被拿下或應用程式的執行權限被取得時,金鑰跟著走,這一層歸零。要不要加,看的是威脅模型裡前一類路徑的權重,判讀走 7.30 使用者密碼儲存。它與 memory-hard function 是兩條獨立的軸:後者讓猜測變貴,這一層讓猜測開始不了。
它與 work factor 解的是不同的問題。Work factor 讓每一次猜測變貴,攻擊者仍然猜得動;pepper 讓攻擊者連猜都開始不了,前提是他沒有拿到那把金鑰。前者的強度隨硬體變快而下降,後者不會——但後者的成立條件比較窄。
可觀察訊號與例子
金鑰的住址決定實際強度,差別在於攻擊者取得執行權限之後還剩下什麼。放在應用程式的設定檔或環境變數時,執行環境一旦被取得金鑰立刻可讀。放進外部金鑰管理服務時金鑰不落在應用程式的磁碟上,但應用程式有權呼叫,取得執行權限的攻擊者一樣拿得到——差別在他必須留在線上一次次呼叫,而那些呼叫留下紀錄、也可以被限速。放進硬體安全模組時金鑰不離開模組,性質同前一項而金鑰本身不可導出。後兩者換到的是偵測與限速的機會,見 key management。
輪替成本由那一層是不是可逆的決定,而不是由它混在雜湊前面還是後面決定。不可逆的接法(與密碼一起做訊息驗證再餵給金鑰衍生函式、或對衍生結果再做一次訊息驗證)都要等使用者登入才換得掉;可逆的接法(用金鑰把衍生結果加密起來存)可以用舊金鑰解、新金鑰包,全庫離線完成。把位置當成判準會對最常見的那一種做法得出相反的答案。
設計責任
導入前要定案的是金鑰的保管與備援,因為遺失 pepper 的後果是全部密碼都無法驗證,唯一的出口是全體使用者重設。這個後果的量級高於密碼儲存的其他任何一項決定,所以備份、存取權限與復原演練要在上線前確認,而不是等第一次輪替時才處理。
紀錄旁要存一個金鑰版本識別,否則輪替期間新舊並存就沒有依據判斷該用哪一把驗證。
選可逆的接法時要接受它帶進加密自己的失效形態:用確定性的加密或重複使用同一個初始向量時,「兩個帳號的密碼相同」會變得看得出來,而那正是 salt 要消除的性質。