質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • PHP

    24054questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ハッシュ化したパスワードが一致しない

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 4,911

aaaaaaaa

score 469

下記のソースにて前頁から送られてきたパスワードとDBに存在する既にハッシュ化されたパスワードを照合しています。 

しかし、前頁から、ハッシュ化されたパスワードに対応する値を下記のソースに送信しているのにも関わらず照合が一致せず次の処理に進まないのです。 もちろんですが、DBに存在するパスワードをハッシュ化しなければ、前頁で記述したパスワードは一致します。なぜハッシュ化した途端上手くいかなくなるのでしょうか。

<?php
try {
 require_once '../lib/dbaccess.php';
 require_once '../common/common.php';

 $post = sanitize($_POST);
 $member_email = $post['email'];
 $member_pass = $post['pass'];

 $dbh = dbaccess();
 $sql = 'SELECT code,password,name,email FROM dat_member WHERE email=?';
 $stmt = $dbh->prepare($sql);
 $data[] = $member_email;
 $stmt->execute($data);

 $rec = $stmt->fetch(PDO::FETCH_ASSOC);
 $db_pass = $rec['password'];
 if(!password_verify($member_pass, $db_pass)) {
 echo <<<EOL
 <p>パスワードが間違っています。</p>
 <a href="./member_login.html">戻る</a>
 EOL;
 } else {
 session_start();
 $_SESSION['member_login'] = 1;
 $_SESSION['member_code'] = $rec['code'];
 $_SESSION['member_name'] = $rec['name'];
 header('Location: ./shop_list.php');
 }
 $dbh = null;

 $rec = $stmt->fetch(PDO::FETCH_ASSOC);
 } catch(Exception $e) {
 echo <<<EOL
ただいま障害により大変ご迷惑をおかけしております。
EOL;
 exit();
 }
 ?>

@common.php

<?php
 function sanitize($before) {
 foreach($before as $key => $value) {
 $after[$key] = htmlspecialchars($value);
 }
 return $after;
 };

@前頁

<!DOCTYPE html>
 <html lang="ja">
 <head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=divise-width, initial-scale=1, user-scalable=1">
 </head>
 <body>
 <h1>会員ログイン</h1>
 <form method="post" action="./member_login_check.php">
 <label><p>登録メールアドレス</p><input type="text" name="email"></label>
 <label><p>パスワード</p><input type="password" name="pass"></label>
 <input type="submit" value="送信">
 </form>
 </body>
 </html>

@パスワードをハッシュ化しDBに保存するときのソース

<中略>
if($chumon == 'chumontouroku') {
 $sql = 'insert into dat_member (password,name,email,postal1,postal2,address,tel,danjo,born) values(?,?,?,?,?,?,?,?,?)';
 $stmt = $dbh->prepare($sql);
 $data = array();

 function password($password) {
 $options = array('cost' => 10);
 return $reg_pass = password_hash($password, PASSWORD_DEFAULT, $options);
 }

 $reg_pass = password($reg_pass);
 $data[] = $reg_pass;
 $data[] = $onamae;
 $data[] = $email;
 $data[] = $postal1;
 $data[] = $postal2;
 $data[] = $address;
 $data[] = $tel;
 if($danjo == 'dan') {
 $data[] = 1;
 } else {
 $data[] = 2;
 }
 $data[] = $birth;
 $stmt->execute($data);
 <中略>

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12153369172

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kurosawa

    2015/12/07 21:51

    動作させるPHPのバージョンはいくつでしょうか?

    キャンセル

回答 3

checkベストアンサー

+4

いろいろな原因が考えられると思いますが、DBのカラム幅はどうなっていますか?
下記リファレンスによれば、余裕を持ったカラム幅に設定しておくことが推奨されています。
  password_hash — パスワードハッシュを作る

結果をデータベースに格納するときにはカラム幅を 60 文字以上にできるようなカラムを使うことをお勧めします (255 文字くらいが適切でしょう)。 
もし、DBのカラム幅が不足していると、DBがに格納した時点で尻切れになってしまう危険があります。

一方、DBのカラム幅が広すぎると、DBからパスワードを取り出した際に、末尾に余分な空白が付加されてしまっている場合もあります。

ですので、下記の関数で具体的にどのようにパスワードの比較をしているのか分かりませんが、

password_verify($member_pass, $db_pass)

の部分の引数 $member_pass と $db_pass の中に、実際にどんな値が入っているか?(末尾の空白も含めて)を直に確認してみるのが確実だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/08 14:34

    ご回答有難うございます。
    ご指摘の通り尻切れトンボになっておりました。無事解決しました。

    キャンセル

+1

password_verify が使われていましたね。失礼しました、下記は問題ありません。。


password_hashのソルトは毎回ランダムなものが利用されます。ゆえにDBにある、事前に生成した「ハッシュ済みパスワード文字列」と、パスワード入力されて照合する際に生成されるハッシュ文字列とは、異なった内容になると思います。


あと、余談ですみませんが、初っ端でPOST変数のsanitize(htmlspecialchars)を行っている箇所は、ちょっと怪しいです。

htmlspecialcharsは、HTML出力するために利用するもので、使うところはヒアドキュメントの中や直近です。

Qiita - $_GET, $_POSTなどを受け取る際の処理

もしパスワード文字列内に & < > などがあれば、ここで加工されてしまいますので、ハッシュ関係の処理でうまく行えたとしても照合結果NGとなるでしょう。

POSTやGETされる値の安全な取得は、filter_input 関数を利用すると便利です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/08 15:40

    ご回答有難うございます。
    sanitize関連を読ませていただきました。取得した値を表示する直前に、ということですね。表示するというのは、html上にということなのでしょうか。

    キャンセル

  • 2015/12/08 16:58 編集

    >表示するというのは、html上にということなのでしょうか。
    仰る通りです。ブラウザに対して < や > などHTMLタグとして認識してほしくない場合などに、&lt; &gt; などへ置き換える(HTMLエンコードする)関数がhtmlspecialcharsです。

    たとえば「メモ帳」や「掲示板」的なアプリを作ったとして、もしHTMLエンコードをしないと

    "KYOTO<NAGOYA>SHIN-YOKOHAMA"

    とメモ入力した場合、ブラウザは<NAGOYA>の箇所をHTMLタグと認識して

    "KYOTOSHIN-YOKOHAMA"

    と表示してしまいます。表示されないどころか、意図的に

    <script>location.href='危険なサイトのURL';</script>

    と入力されたりして、セキュリティ上問題を起こしてしまいます。

    かといって、受信した文字データを最初から加工してしまうと、< や > などをそのままデータとして意味を持たせたい(使いたい)場合に困ってしまいます。ご質問のパスワード照合で、パスワード文字にアンパサンドも許容している場合、& が &amp;に変換されてしまいますので、(ハッシュ処理は省略します) m#&83R といったパスワードを指定したとき m#&amp;83R と比較をすることになってしまいます。

    ちなみに、データベースを利用する場合のSQL文に関するサニタイズも、上記のような理由から、SQL文を生成する直前に文字列データをサニタイズするか、バインド機構を利用します。

    キャンセル

0

パスワードの暗号化で、引数に PASSWORD_DEFAULT を利用しており、
さらに option に salt 指定されてたので、 bcrypt アルゴリズムを期待してるのかなぁと思いました。

$options = array('cost' => 10);
 return $reg_pass = password_hash($password, PASSWORD_DEFAULT, $options);

ただ、、 これは PHP 5.5.0 ならば、bcrypt アルゴリズムが採用されるだけであり、バージョンによってアルゴリズムが変わる(optionも変わるし、尻切れもありうる)ので、まずはバージョンを伺った次第です。

まずは解決したとのことなので、なによりです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • PHP

    24054questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。