なんか最近「パスワード、いくつかの単語を組み合わせた長い文字列のほうが安全だよねぇ」的なお話が云々。
それを考えた時、今まで割と気にならなかった「警告 PASSWORD_BCRYPT をアルゴリズムに指定すると、 password が最大 72 文字までに切り詰められます。」が、途端に気になりだしてきたり。
ふと考える2つのコード、果たしてどっちがベターなのだろう?
或いは、変わらんかなぁ?
一応おいちゃんの中にはイメージがあるんだけど、ふと、問いかけてみたいように思ったので、書いてみる。
どうも、どっちも危ないっぽい。後述を参照のこと。
コード1(アウト)
$pass = パスワード; if (72 < strlen($pass)) { $pass = hash('sha512', $pass, true); } $h = password_hash($pass, PASSWORD_DEFAULT, ['cost' => 10]);
コード2(アウト)
$h = password_hash(hash('sha512', $pass, true), PASSWORD_DEFAULT, ['cost' => 10]);
costの明示指定は趣味だ気にスンナw*1
さて。コード1とコード2、どっちがどうなんだろう???
追記。
徳丸さんがfacebookで書かれていたんだけど。
「password_hash 関数はバイナリセーフでない」んだそうだ……………え?まぢで?
徳丸さんが載せていた、検証コード。
$password = "LmUb9dTqXUTTCuCxzCct3n2lIf/zS3IeZ15mtCivl0TQlD97YZtxK+u0j4AploaErAu9uYBBfqNs4R2nQITnyq+nuLZd"; $crack = "ma"; // Use sha512's raw(binary) output $h = password_hash(hash('sha512', $password, true), PASSWORD_DEFAULT); // Verify $r = password_verify(hash('sha512', $crack, true), $h); var_dump($r); // TRUEが返る
うん通った orz
コード1なら「上述は防げる」けど、「72文字を超える文字列同士で「任意箇所に\0が入ってくる」なら突破できるから、あんまりよろしくないぽげ。
さて思案。
「バイナリが駄目なら、base64にすればいいぢゃない」とか思うんだけど、sha512はbase64にしても88バイト使うから駄目なんだよねぇ。
ってなわけで、おとなしく素直に「16進数表記のsha256」が落としどころかなぁ、と。とりあえずは。
改めてコード1
$pass = パスワード; if (72 < strlen($pass)) { $pass = hash('sha256', $pass); } $h = password_hash($pass, PASSWORD_DEFAULT, ['cost' => 10]);
改めてコード2
$h = password_hash(hash('sha256', $pass), PASSWORD_DEFAULT, ['cost' => 10]);
このどっちか、になるんかなぁ今の所だと。
*1:いや実際のところ、12くらいを指定する事が多くなってきたしねぇ