パスワードをソルトつきハッシュ化してDBに保存するのがベストプラクティス…とは限らないという話

フレームワークの責務とセキュリティ - MugeSoの日記についての感想文です。

世の中にはたくさんの通信プロトコルが存在し、中には、特定の条件でパスワードを含む文字列をハッシュ化した値を検証しなければならないものも含まれています。

例えば、HTTP Digest認証の場合は、MD5("realm:user:password")を保存しておく必要がありますし、APOPの場合は生のパスワードを、CRAM-MD5の場合はMD5("password")を保存しておく必要があったはず。

で、こういった様々なプロトコルに対応可能な認証データベースを準備しようとすると、パスワードを復号可能な方式で保存しておく必要があります*1

ただ、パスワードを復号可能な方式で保存するとか、開発者あるいは管理者としてやりたくないというのはもちろんそうなので。で、長期的には世の中どこへ向かってるかというと:

  • 選択肢a) 三者間認証を使う(OAuthとかそういうやつ)
  • 選択肢b) 経路をTLS(SSL)暗号化し、パスワードは平文のまま認証サブシステムまで到達する。認証サブシステムは独自の最適と考える方式でパスワードを保存する*2

って感じなのかなと思います。

こういう経緯があるので、パスワードを、独自のやり方でハッシュ化するのを強制する、というのをフレームワークレベルでやるのは良くないよ*3というのが僕の考えです(注: MugeSoさんは、そのような強制をすべきと主張しているのではないとのこと*4)。

PS. もちろん、アプリケーション要件的に、生パスワードがアプリケーションまでわたってくるという前提をおけるのであれば、ソルトつきハッシュ化を「アプリケーションデベロッパー」が選択すべきだと思いますし、それを推奨するようなフレームワークであれば良いのかなと思います。

PS2. ソルトつきハッシュ以外の方法でパスワードを保存するなんて怖い、っていう人は「Kazuho's Weblog: パスワードが漏洩しないウェブアプリの作り方 〜 ソルトつきハッシュで満足する前に考えるべきこと」をあわせてお読みください

*1:今後対応する必要がありうる全ての方式のプロトコルに対応した形で、あらかじめ(一方向)暗号化したパスワードデータベースを用意しない限りにおいて、です。また、共通鍵暗号化を用いて保存する場合でも、ECBモードではなくCBCモードを使うべきでしょう。参照: Adobeサイトから漏えいした暗号化パスワードはなぜ解読されたか | 徳丸浩の日記

*2:パスワードが常に平文のまま認証サブシステムにまで到達する世の中になれば、ソルト付きハッシュで保存できるようになる

*3:それは結局、上で述べた「特定の条件でパスワードを含む文字列をハッシュ化した値を検証しなければならない」というアンチパターンに陥る話なので

*4:参照: mugeso on Twitter: "@kazuho 反応ありがとうございます。 件のエントリではBasic認証の実装をFWに取り込む場合の話ですので、他の認証方法に関して制限を設けるということではありません。"