Memory-hard function 是刻意讓每次計算都佔用大量記憶體的函式,用途是壓制攻擊者的平行度。防守方與攻擊者跑的是同一個計算,差別在硬體——攻擊者可以用繪圖處理器或訂製晶片同時算幾萬份,而那個優勢的來源是單次計算需要的資源少、複製一份便宜。記憶體改變的正是這個比例:每個平行實例都要獨佔一塊記憶體,於是平行度被晶片上的記憶體總量封頂,而記憶體在晶片面積上的成本遠高於計算單元。它與 salt 解的是不同的問題——salt 讓相同的密碼產生不同的值,這一類函式讓每一次猜測都貴。

概念位置

它是密碼雜湊三種收費位置裡的一種。時間(迭代次數)是最直觀的一項,PBKDF2 只有這一項——把迭代數乘以十,防守方與攻擊者的成本同時乘以十,比例不變,這是它抗硬體能力最弱的結構原因。記憶體改變比例,Argon2 的 m 與 scrypt 的 N 買的都是這一項。記憶體的存取形態是第三項:讀取位置由資料本身決定時攻擊者無法預先排程搬運,代價是存取形態會洩漏資訊給觀察得到快取行為的旁通道攻擊者,而 Argon2 分成三個變體正是在這條軸上取值。完整的選型判讀走 7.30 使用者密碼儲存。把金鑰放到資料庫之外是另一條獨立的軸,見 pepper

bcrypt 在這個框架裡有明確的位置:它有記憶體項但小且不可調。約 4 KB 這個量級至今仍超過繪圖處理器每個核心可用的快取,這是它抗那一類硬體明顯優於 PBKDF2 的原因;而參數不可調意味著硬體變大之後這個優勢不會跟著長。

可觀察訊號與例子

選它要付的營運代價是記憶體變成容量約束。每次登入常駐的記憶體乘上尖峰併發數就是要準備的量,而這一項在只算 CPU 的容量規劃裡看不到——機器會在尖峰時因記憶體不足而倒,而不是因為算不完。

另一個容易漏的是平行度參數。它被編進雜湊字串、驗證時必須用同一個值,所以它不是事後可以調的效能旋鈕;而主流函式庫的預設值多半不是 1,照預設跑的話每次雜湊佔用的核心數要跟著放大。

設計責任

判別一個沒見過的構造適不適合用來存密碼,用同一組問題:它對什麼收費、那一項調不調得動、調高之後攻擊者的平行度會不會跟著降。三個問題都有答案的才進入比較;直接使用一般用途的雜湊在第一個問題上就出局,因為它的設計目標正好相反。

合規環境要注意這個性質與核准清單無關。經過驗證的密碼型金鑰衍生函式目前只有 PBKDF2 一種,而它不是記憶體硬化的——受那一類約束時,抗硬體能力要靠迭代次數推到延遲預算的上限來補,補得有限但那是那一格能做的全部。