パスワード保存のベストプラクティスと bcrypt のメモ書き
考えてみるとほとんどパスワードを保存するコードを書いたことがない。現状のベストプラクティスを知らなかったのでメモ書き。
現状では bcrypt 使うのがいいみたい。b は Blowfish の b。
Modular Crypt Format というフォーマットとコンパチの出力をする。crypt (3) はもともと DES の短いフォーマットだが、弱すぎたため md5 拡張なりSHA512 拡張などが存在している。(htpasswd でも使われているので見たことある人は多いだろう)
これの Blowflish を使ったものが bcrypt で、prefix に $2$, $2a$, $2x$, $2y$ $2b$ がついている。prefix の違いはバージョンの違いであり、現在は 2b を使うのが良い。ストレッチング回数も出力に含まれるので、あるとき急にストレッチング回数を増やしても特に問題はない。
このフォーマットは出力に salt も含むので、生成された MCF はそのまま保存すれば良い。
Blowfish ってなんだ
Blowfish 自体は一方向ハッシュ化アルゴリズムではなく共通鍵暗号化アルゴリズム。処理速度が早く鍵長がある程度可変でライセンスフリーというのが特徴。
共通鍵暗号なのになんでハッシュとして使えるの?
bcrypt は "OrpheanBeholderScryDoubt" という決まった文字列を 64回 Blowfish で暗号化する。 このとき暗号に使う状態 (暗号化の鍵) を password や salt から初期化する。この初期化にも Blowfish の暗号化が使われる。
暗号化済みテキストに鍵の情報が入ることはない (もしあったとしたら暗号化アルゴリズムではない) ので一方向になる。
また "OrpheanBeholderScryDoubt" に復号化できるキーを探す (クリブ / plain text attack) も Blowfish では難しいため、実質的にブルートフォースアタックしかできない。
備考: salt を別途保存する必要がないのは bcrypt に限らない
そもそも Modular Crypt Format のものは des crypt ですら salt も出力に含んでいる。ググると「bcrypt なら salt は別に保存する必要がない」と書いてる人がいたりする。間違いではないが正しくはない。
Modular Crypt Format のいくつかのパターンを引用する
des_crypt : {salt}{checksum}
md5_crypt : $1${salt}${checksum}
bcrypt : $2a${rounds}${salt}{checksum}
sha256_crypt : $5$rounds={rounds}${salt}${checksum} ( https://passlib.readthedocs.io/en/stable/modular_crypt_format.html から一部をコピペ)
備考: パスワード保存は必要か?
そもそも現代ではプラットフォーマーでなければパスワードを保存しなければならないケースがかなり少ない。OAuth などで外部サービスに認証を委託したほうがはるかに楽だからだ。パスワードを保存するということはそれ自体が難しいうえに、パスワードリセットや2段階認証なども含めてトータルで抜け道がないか考える必要がある。
ref.
関連エントリー
- Ubuntu LTS 16 → 18 → 20 一応バックアップ sudo parted -l Model: Virtio Block Device (virtblk) Disk /dev...
- Mac でウェブカメラの定期撮影を Swift で書く macOS 用にウェブカメラからjpgを取得するコマンドラインツールにimagesnapというのがある。単発で使うには問題ないんだけど、イン...
- WSL2 で USB (usbipd-win) https://github.com/dorssel/usbipd-win WSL2 内ではホストの USB デバイスを使うことができないと...
- Sierra にしたらリモートの日本語が化けるようになった 以下のような環境で日本語が化けるようになった。 macOS Sierra リモートで screen を使っている ssh host -t s...
- Raspberry Pi 2 B+ と 3.2inch LCD もともと初代 Raspberry Pi 用に買ったものだけれど、初代 Raspberry Pi をいよいよ捨てたので、ついでにいろいろ調べな...