Raspberry Pi でパスワードにかかる値段
ここでは統計ページにパスワードをかけられます。そのパスワードのハッシュを計算する処理は、このサービスで唯一、遅くあるべき処理です — 盗まれたハッシュの解読を高くつかせているのが、まさにそれだからです。問題は、このハードウェアでどれくらい遅いか。
このサイトを動かしている機械で実測、PHP 8.4.21、aarch64 上:
PASSWORD_DEFAULT | 560 ms | (cost 12 になる) |
| cost 12 | 595 ms | |
| cost 11 | 277 ms | |
| cost 10 | 138 ms |
bcrypt のコスト値は指数です。一段上がるごとに作業量が倍になります。測定値はまさにその倍加を示していて、ほかに何も邪魔していないという良い印です。
なぜここでは既定値が誤った選択なのか
PHP は bcrypt の既定コストを 10 から 12 に上げました。データセンターのサーバーなら妥当な引き上げです — 数十ミリ秒のこと。小さな ARM ボードでは、それは半秒を超える純粋な計算時間であり、しかもその機械は同時に他の全員のカウンター画像を描いています。
ログイン一回に半秒はそれ自体で悪い。招待状としてはもっと悪い。ログインの入り口は誰でも呼べますし、一回の呼び出しがサイト全体を賄う一つの CPU の 560 ms を食います。これでパスワード照合は、ここにある中でいちばん安上がりな過負荷の手段になります。
そこでコストは既定値に任せず 10 に固定してあります。これは PHP が今選ぶものより意図的に弱く、埋めずにはっきり言うべきことです。コスト 10 のハッシュは、コスト 12 のものより四分の一の費用で解けます。それを買い戻しているのは、このパスワードが実際に守っているものです — 訪問数のページが見えるかどうかであって、アカウントでも、お金でも、身元でもありません。その奥に乗っ取れるものは何もないのです。
見落としやすいところ
PASSWORD_DEFAULT は設計上、動く値です。何年も前に書かれ、それを使っているコードは、PHP を上げるたびに黙って遅くなります — 同じソース、同じ入力で、実行時間は何倍にも。それが想定された振る舞いで、ほとんどのソフトウェアにとっては正しい。
誤りになるのは機械が吸収できないときだけで、吸収できないときに何も警告してくれません。更新は通り、テストも通り、ページも動く。ただ半秒余計にかかるだけで、その数字は測りに行かないかぎり誰も見ません。