phpでパスワードをハッシュ化して安全にDBに格納したいと考えいてるのですが、ベストな方法が見つかりません。


phpのマニュアルの下記URLのアドバイスを見ると、crypt関数でBlowfishアルゴリズムでハッシュを作るのがベストな選択肢のようなのですが、
http://www.php.net/manual/ja/faq.passwords.php#faq.passwords.fasthash
それをどうやって実装していいのかがわからずに困っています。
マニュアルのcryptページのサンプルには
crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$')
このように例が記載されているのですが、saltは任意の文字列だと思われるのですが07?にあたる部分の「コストパラメーター」?を得る方法が分からずに困っております。

ちなみにPEARのCrypt_Blowfishというものを見つけたのですが、ググるとこれはどうも可逆暗号のようでパスワード文字列のように復号できると安全度が下がるようなものには使うべきではないのかと考えておりますが、あっておりますでしょうか。

質問を重ねて申し訳ありませんが、詳しい方にアドバイスをお願いできればと思います。
よろしくお願いいたします。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/07/24 09:50:57
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:TransFreeBSD No.1

回答回数668ベストアンサー獲得回数268

ポイント300pt

幾つでもいいといえばいいのでは?
マニュアルをそのまま解釈すれば、04なら16回、08なら256回、31なら……21億回くらいハッシュ化を繰り返す、ということだと思います。
なので、数字を大きくすればするほど計算時間がかかってしまいます。
そしてそれが狙いです。なので、大きくできるなら大きくしておいた方が良いと思います。
多分(暗号理論は難解で以外な所に落とし穴あったりするので一応)

万が一、暗号化したファイルが流出した場合、ブルートフォースアタックで復号されてしまう危険性がありますが、ハッシュ化に時間がかかればかかるほど、探し当てる時間を長くできます。
例えば07の時、3日で探し当てるマシンがあったとします。すると08なら6日、10なら1ヶ月近く、14なら1年以上、20なら67年と、実質復号不能に持っていけます(ただし、将来的に計算アルゴリズムの改良による高速化とかハードの高速化を考慮しなければ)。
ただ、辞書攻撃などで陥落しない、本当に総当たりのブルートフォースアタックの場合という大前提がありますが。

http://net.tutsplus.com/tutorials/php/understanding-hash-functions-and-keeping-passwords-safe/
これの7番かな?


可逆暗号の場合、暗号化キーをどう扱うかという問題が発生します。
暗号化したデータと一緒に保存しては意味がありませんが、プログラムからはアクセス可能でなければなりません。
また、一旦復号出来た時は全てのパスワードが復号できる事になります。
ただ、例えばワンタイムパスワードを使用しようと思うと、一方向ハッシュは使えないのです。
なのでサーバに保存されたデータの流出を心配するか、ユーザの入力後の盗聴を心配するか、と言う話になると思います。

ただし、フィッシングとかソーシャルハック的攻撃に乗らないという前提での話になりますが。

他1件のコメントを見る
id:tdoi

適切なオフィシャルな説明は見つけてないですが、以下が参考になるかと。
http://stackoverflow.com/questions/2225720/why-does-crypt-blowfish-generate-the-same-hash-with-two-different-salts
saltとして扱われるのは、「usesomesillystringforsalt$」であり、26文字です。
挙動を見る限り、22文字以上については打ち切られるようですね。

2012/07/20 11:05:01
id:n_maco2

ご回答ありがとうございます。
私のほうでも文字数を増やして増加分がどうなるかのテストをしてみたりしてみたのですが、おっしゃるとおり文字数が大きいと無視されるようですね。大体疑問点が解消できました、ご協力いただきありがとうございます。

それにしてもオフィシャルの情報が不足?しているものを、パスワードという重要な機構に使うのは若干の不安を感じるのですが・・勉強不足と考えてこのままやるしかないですかねぇ・・テスト等慎重に進めてみたいと思います。

ありがとうございました

2012/07/20 13:43:12
  • id:tdoi
    マニュアルからの引用ですが、
    >>>
    CRYPT_BLOWFISH - Blowfish ハッシュ。salt の形式は、 "$2a$"、2 桁のコストパラメータ、"$"、そして文字 "./0-9A-Za-z" からなる 22 桁となります。 この範囲外の文字を salt に使うと、crypt() は長さゼロの文字列を返します。 2 桁のコストパラメータは反復回数の 2 を底とする対数で、 これは Blowfish ベースのハッシュアルゴリズムで使います。 この値は 04 から 31 までの範囲でなければならず、 それ以外の値の場合は crypt() は失敗します。
    <<<
    なので、04から31までであればよいと思いますが。
    具体的にはどのあたりが疑問なのでしょうか?
  • id:n_maco2
    コメントありがとうございます。
    「2 桁のコストパラメータは反復回数の 2 を底とする対数」というのがまったく理解できなかったのです・・04〜31の間ならいくつでもいいという意味なのでしょうか?
  • id:Windymelt
    そもそもblowfishはハッシュを生成するものではありません。
    ハッシュ化してDBに格納するだけならば、SHA-512を数回繰り返して格納すればいいだけなのでは?

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません