POTI-boardのパスワードハッシュをpassword_hash()に

2018年のパスワードハッシュ - Qiita

ログイン認証と称してmd5とかsha1とか書いてあるソースはゴミなので投げ捨てましょう。
単純なMD5やSHA1ハッシュを元に戻す | Bamboo lath 日々の記録
ハッシュ値は非可逆なので元に戻す事ができない筈なのですが、「aiueo」や「12345」のような単純なパスワードはデーターベースと照合して元に戻す事ができるようです。

POTI-boardは md5() から途中の8文字を抽出してハッシュ化しているので、紹介されている逆引きサイトに8文字のハッシュ値をいれても何もでてきませんが、パスワードが同じならハッシュ値も同じである事に変わりはありません。
PHP: password_hash - Manual

password_hash − パスワードハッシュを作る
password_hash() という簡単に導入できるハッシュ化のための関数があるのに使わない手はない…ですね。

簡単なテストコード。
<?php
$h= password_hash("aiueo", PASSWORD_DEFAULT);
//パスワードは aiueo
echo $h."\n";//ハッシュ値が表示される
$v=password_verify("aiueo",$h);
//ハッシュ値とパスワードを照合
echo $v."\n";//1
var_dump($v);//true
同じパスワードなのにリロードする度にハッシュ値が入れ替わります。

しかし…。
$h= password_hash("aiueo", PASSWORD_DEFAULT);
ではcostが10になってしまいます。
<?php
/**
* このコードは、サーバーをベンチマークして、どの程度のコストに耐えられるかを判断します。
* サーバーに負荷をかけすぎない範囲で、できるだけ高めのコストを設定したいものです。
* 基準として 8 から 10 程度からはじめ、サーバーが十分に高速なら、できるだけ上げていきましょう。
* 以下のコードでは、ストレッチングの時間を 50 ミリ秒以内にすることを狙っています。
* 対話形式のログインを扱う際の許容時間としては、このあたりが妥当なところでしょう。
*/
$timeTarget = 0.05; // 50 ミリ秒

$cost = 8;
do {
$cost++;
$start = microtime(true);
password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
$end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Appropriate Cost Found: " . $cost . "\n";
?>
さくらのレンタルサーバ ライトでこのテストコードを実行してみたところ最適なcostは9でした。

一番安いライトプランではありますが有料のサーバでもcost10ではサーバに負荷がかかるという事です。
costを10から9に下げると処理時間が半分に。
8にしたらさらに半分…。costが1下がると処理時間が半分になるようです。

ログイン認証を一度だけ行ってログインしたらそのまま…という想定ならcostが10でも耐えられるのかもしれませんが何か一言書き込むだけでパスワードのハッシュ化が行われる掲示板でcost10で運用するとサーバの負荷が高くなってしまうかもしれません。
$pass = $pwd ? password_hash($pwd,PASSWORD_BCRYPT,['cost' => 5]) : "*";
costを5に引き下げました。

cost5では低すぎるのでは?と思ったりもしましたが、コメントを書き込むたびにパスワードをハッシュ化する掲示板なのでこれぐらい下げないと無料のレンタルサーバでは高負荷になる…という判断です。

それでも同じパスワードなら同じハッシュ値という従来のmd5の8文字のハッシュ値とは比べ物にならないぐらい安全性を向上できた…と思うのですが。

この変更は、lot.190823に反映されました。

POTI-board改のダウンロードはこちらから。

お絵かき掲示板はこちら。

file_exists() is_file() 速度比較

ファイルの存在確認をするときに使う関数 file_exists() 、 is_file() の速度を比較するため簡単なコードを書いてテスト。
<?php
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){//10万回繰り返す
file_exists($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){
is_file($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果

//0.37799286842346 秒 0.038822174072266 秒 さくらのレンタルサーバライト
is_file() のほうが、10倍速いという結果がでました。

テストしたコードが単純すぎてキャッシュを確認しているだけだとしても…。
速度差が10倍…なら is_file() で構わないところは is_file() を使ったほうが。

動作の違いは…。
$img='img/';
var_dump(is_file($img));//bool(false)
var_dump(file_exists($img));//bool(true)
$img='img/hoge.png';
var_dump(is_file($img));//bool(true)
var_dump(file_exists($img));//bool(true)
file_exists()は、ディレクトリしかなくても bool(true) を返します。 is_file() では bool(false) になります。

POTI-boardで使用されている file_exists() の該当箇所をしらべてみると…。
ディレクトリの確認をしているかもしれない箇所はほとんどなく逆にディレクトリしかなくても bool(true) では意図した動作にならないところに file_exists() が使用されている事がわかりました。

POTI-boardは一言書いて投稿するだけでもすべてのログを解析してHTMLファイルに書き出します。
そのためログが肥大化すると処理速度が遅くなってしまうのですが…さらに投稿するたびにすべての画像ファイルにアニメファイルがあるかどうか確認しているのでそこに重い関数を使うと…。

投稿時にアニメファイルの存在確認を行う回数が一目でわかるようにdumpしてみました。

file_exists()をis_file()に

アニメファイルの存在確認を file_exists() から is_file() に書き換えたところ8秒かかっていた投稿処理時間が1秒に短縮。

運営している絵板は設置件数が多くログ保持件数が多いのに一番安いさくらのレンタルサーバ ライトのライトプランなので、遅くても仕方がないのかな?と思っていたのですがどうにか…。

この変更は、POTI-board改 v1.52.9 lot.190812に反映されました。
(最新版は v1.53.2 lot.190831)

POTI-board改のダウンロードはこちらから。

お絵かき掲示板はこちら。