password_hash関数

実は、md5関数とそれを使ったパスワードのソルト(salt)付与は、古い方法とみなされています。 これらを学んだのは、今後の内容を理解してもらうためと、他人のプロジェクトでこの方法に出会う可能性があるからです。

より洗練された方法でソルト付きパスワードを得る方法があります。そのために使われるのが password_hash関数です。最初のパラメータとして文字列を受け取り、二番目のパラメータとして暗号化アルゴリズムを指定し(後述)、その文字列のソルト付きハッシュを返します。

次のコードを何度か実行してみてください:

html<?php
  echo password_hash('12345', PASSWORD_DEFAULT);
?>

実行するたびに異なる結果が得られ、その結果の最初の部分がソルト、二番目の部分がソルト付きパスワードとなります。

password_hash関数から得られたハッシュと、何らかのパスワードがあるとします。 これがそのパスワードのハッシュかどうかを確認するには、 password_verify関数を使うべきです。 この関数は最初のパラメータとしてパスワードを、二番目のパラメータとしてハッシュを受け取り、trueまたはfalseを返します。

例を見てみましょう:

html<?php
  $password = '12345'; // パスワード
  $hash = '$2y$10$xoYFX1mFPxBSyxaRe3iIRutxkIWhxGShzEhjYUVd3qpCUKfJE1k7a'; // ハッシュ
  
  if (password_verify($password, $hash)) {
    // このパスワードからのハッシュです
  } else {
    // このパスワードからのハッシュではありません
  }
?>

これが実際に何をもたらすかというと:データベースにソルトを保存するための別のフィールドを作成したり、このソルトを生成することに悩んだりする必要がなくなります。PHPがすべてをやってくれます!

つまり、データベースのpasswordフィールドには、ソルト付きパスワードをそのソルトと共に保存することになります。 ただし、ハッシュ化されたパスワードはより長い長さになります。 そのため、データベースではパスワードフィールドのサイズを修正し、60文字に設定する必要があります。

では、登録コードを修正しましょう。 現在のコードは以下の通りです:

html<?php
  function generateSalt()
  {
    $salt = '';
    $saltLength = 8; // ソルトの長さ
    
    for($i = 0; $i < $saltLength; $i++) {
      $salt .= chr(mt_rand(33, 126)); // ASCII-tableからの文字
    }
    
    return $salt;
  }
  
  $salt = generateSalt(); //  ソルト
  $password = md5($salt . $_POST['password']); // パスワードをソルト付きハッシュに変換
?>

password_hashを使うと、次のように簡略化できます:

html<?php
  $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
?>

同様に、認証コードも修正されます:

html<?php
  $login = $_POST['login'];
  
  $query = "SELECT * FROM users WHERE login='$login'"; // ログインからユーザーを取得
  $res = mysqli_query($link, $query);
  $user = mysqli_fetch_assoc($res);
  
  if (!empty($user)) {
    $hash = $user['password']; // データベースからのソルト付きパスワード
    
    // データベースのハッシュと入力されたパスワードの一致を確認
    if (password_verify($_POST['password'], $hash)) {
      // すべてOK、認証...
    } else {
      // パスワードが一致しません、メッセージを表示
    }
  } else {
    // そのログインのユーザーはいません、メッセージを表示
  }
?>
Задание 1

あなたの認証と登録を、新しく学んだ関数に変更してください。