<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/faq.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'faq.passwords.php',
    1 => 'パスワードのハッシュ',
    2 => '安全に、かつセキュアにパスワードをハッシュする',
  ),
  'up' => 
  array (
    0 => 'faq.php',
    1 => 'FAQ',
  ),
  'prev' => 
  array (
    0 => 'faq.using.php',
    1 => 'PHP の使いかた',
  ),
  'next' => 
  array (
    0 => 'faq.html.php',
    1 => 'PHP と HTML',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'faq/passwords.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="faq.passwords" class="chapter">
  <h1 class="title">安全に、かつセキュアにパスワードをハッシュする</h1>

  
  
  <p class="simpara">
   この節では、なぜハッシュ関数を使ってパスワードを守るのかについての理由と、
   ハッシュ処理を効率的に行う方法について説明します。
  </p>
  
  <div class="qandaset"><ol class="qandaset_questions"><li><a href="#faq.passwords.hashing">
     
      なぜ、アプリケーションのユーザーが登録したパスワードをハッシュしなければならないのですか?
     
    </a></li><li><a href="#faq.passwords.fasthash">
     
      よく使われるハッシュ関数である md5 や
      sha1 は、なぜパスワードのハッシュに適していないのですか?
     
    </a></li><li><a href="#faq.passwords.bestpractice">
     
      よく使われるハッシュ関数では不適切だというのなら、
      パスワードをどうやってハッシュすればいいのですか?
     
    </a></li><li><a href="#faq.passwords.salt">
     
      ソルトとは?
     
    </a></li><li><a href="#faq.password.storing-salts">
     
      ソルトはどのように保存すればいいのですか？
     
    </a></li></ol></div>
   <dl class="qandaentry" id="faq.passwords.hashing">
    <dt><strong>
     <p class="simpara">
      なぜ、アプリケーションのユーザーが登録したパスワードをハッシュしなければならないのですか?
     </p>
    </strong></dt>
    <dd class="answer">
     <p class="simpara">
      パスワードのハッシュは、最も基本的なセキュリティ要件のひとつです。
      ユーザーからパスワードを受け取るアプリケーションやサービスを設計するときには必ず考慮しなければなりません。
      ハッシュしなければ、パスワードを格納したデータストアが攻撃を受けたときにパスワードを盗まれてしまいます。
      それは即時にアプリケーションやサービスが乗っ取られることにつながるし、
      もしそのユーザーが他のサービスでも同じアカウント・同じパスワードを使っていればさらに被害が大きくなります。
     </p>
     <p class="simpara">
      ユーザーのパスワードにハッシュアルゴリズムを適用してからデータベースに格納しておくと、
      攻撃者が元のパスワードを知ることが難しくなります。
      とはいえ、パスワードのハッシュ結果との比較は可能です。
     </p>
     <p class="simpara">
      しかし、ここで注意すべき点は、パスワードのハッシュ処理はあくまでもデータストアへの不正アクセスからの保護にすぎず、
      アプリケーションやサービス自体に不正なコードを注入される攻撃からは守れないということです。
     </p>
    </dd>
   </dl>
   <dl class="qandaentry" id="faq.passwords.fasthash">
    <dt><strong>
     <p class="simpara">
      よく使われるハッシュ関数である <span class="function"><a href="function.md5.php" class="function">md5()</a></span> や
      <span class="function"><a href="function.sha1.php" class="function">sha1()</a></span> は、なぜパスワードのハッシュに適していないのですか?
     </p>
    </strong></dt>
    <dd class="answer">
     <p class="simpara">
      MD5 や SHA1 そして SHA256 といったハッシュアルゴリズムは、
      高速かつ効率的なハッシュ処理のために設計されたものです。
      最近のテクノロジーやハードウェア性能をもってすれば、
      これらのアルゴリズムの出力を<q class="quote">ブルートフォース</q> で(力ずくで)調べて元の入力を得るのはたやすいことです。
     </p>
     <p class="simpara">
      最近のコンピュータではハッシュアルゴリズムを高速に<q class="quote">逆算</q> できるので、
      セキュリティ技術者の多くはこれらの関数をパスワードのハッシュに使わないよう強く推奨しています。
     </p>
    </dd>
   </dl>
   <dl class="qandaentry" id="faq.passwords.bestpractice">
    <dt><strong>
     <p class="simpara">
      よく使われるハッシュ関数では不適切だというのなら、
      パスワードをどうやってハッシュすればいいのですか?
     </p>
    </strong></dt>
    <dd class="answer">
     <p class="simpara">
      パスワードをハッシュするときに検討すべき重要な二点は、
      その計算量とソルトです。
      ハッシュアルゴリズムの計算コストが増えれば増えるほど、
      ブルートフォースによる出力の解析に時間を要するようになります。
     </p>
     <p class="simpara">
      PHP には
      <a href="book.password.php" class="link">ネイティブのパスワードハッシュ API</a>
      が用意されており、これを使えば <a href="function.password-hash.php" class="link">ハッシュの計算</a>
      や <a href="function.password-verify.php" class="link">パスワードの検証</a>
      を安全に行えます。
     </p>
     <p class="simpara">
      パスワードをハッシュするときのおすすめのアルゴリズムは Blowfish です。
      パスワードハッシュ API でも、このアルゴリズムをデフォルトで使っています。
      というのも、このアルゴリズムは MD5 や SHA1 と比較して計算コストが高いにもかかわらず、スケーラブルだからです。
     </p>
     <p class="simpara">
      <span class="function"><a href="function.crypt.php" class="function">crypt()</a></span> 関数もパスワードのハッシュに使えますが、
      他のシステムとの相互運用性を保つために使うのがおすすめです。
      可能な限り
      <a href="book.password.php" class="link">ネイティブのパスワードハッシュ API</a>
      を使うようにしましょう。
     </p>
    </dd>
   </dl>
   <dl class="qandaentry" id="faq.passwords.salt">
    <dt><strong>
     <p class="simpara">
      ソルトとは?
     </p>
    </strong></dt>
    <dd class="answer">
     <p class="simpara">
      暗号理論におけるソルトとは、ハッシュ処理の際に追加するデータのことです。
      事前に計算済みのハッシュとその元入力の対応表 (レインボーテーブル)
      で出力を解析される可能性を減らすために利用します。
     </p>
     <p class="simpara">
      端的に言うと、ソルトとはちょっとした追加データです。
      これをつけるだけで、ハッシュをクラックするのが劇的に難しくなります。
      事前に計算済みのハッシュとその元入力を大量にまとめた表が、オンラインで多数公開されています。
      ソルトを使えば、そのハッシュ値がこれらの表に含まれている可能性を大きく減らすことができます。
     </p>
     <p class="simpara">
      <span class="function"><a href="function.password-hash.php" class="function">password_hash()</a></span> は、ソルトを指定しなかった場合にはランダムなソルトを作ります。
      一般に、これがいちばんお手軽で安全なアプローチでしょう。
     </p>
    </dd>
   </dl>
   <dl class="qandaentry" id="faq.password.storing-salts">
    <dt><strong>
     <p class="simpara">
      ソルトはどのように保存すればいいのですか？
     </p>
    </strong></dt>
    <dd class="answer">
     <p class="simpara">
      <span class="function"><a href="function.password-hash.php" class="function">password_hash()</a></span> や
      <span class="function"><a href="function.crypt.php" class="function">crypt()</a></span> を使った場合、戻り値であるパスワードハッシュの中にソルトが含まれています。
      このソルトは、そのままの形式でデータベースに格納する必要があります。
      というのも、利用したハッシュ関数の情報がそこに含まれており、それを直接
      <span class="function"><a href="function.password-verify.php" class="function">password_verify()</a></span> や <span class="function"><a href="function.crypt.php" class="function">crypt()</a></span>
      に渡せばパスワードの検証ができるからです。
     </p>
     <div class="warning"><strong class="warning">警告</strong>
      <p class="simpara">
       タイミング攻撃を避けるために、保存されたハッシュ結果を比較したり
       再ハッシュを行う代わりに
       常に <span class="function"><a href="function.password-verify.php" class="function">password_verify()</a></span> を使うべきです。
      </p>
     </div>
     <p class="simpara">
      <span class="function"><a href="function.crypt.php" class="function">crypt()</a></span> や <span class="function"><a href="function.password-hash.php" class="function">password_hash()</a></span>
      の戻り値の書式を次の図に示します。
      このように、使ったアルゴリズムや検証時に必要なソフトに関する情報もすべて含まれています。
     </p>
     <p class="para">
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/2a34c7f2e658f6ae74f3869f2aa5886f-crypt-text-rendered.svg" alt="
        password_hash や crypt が戻す値。
        使ったアルゴリズム、そのアルゴリズムのオプション、使ったソルト、そしてハッシュしたパスワードが続く。
       " width="690" height="192" />
       </div>
      </div>
     </p>
    </dd>
   </dl>
  
  
 </div>
<?php manual_footer($setup); ?>