起きたこと
- 既存のCakePHP3.5+PHP7.2のアプリケーションではハッシュ化にBCryptを使用している
$passwordHash = password_hash('test', PASSWORD_DEFAULT);
echo $passwordHash
// => "$2y$10$i3J7OqQt9h33I5bwSwAge.H6qQtO2LZASwu36AJi3oC69qdXFSx5i"
- 連携するRuby on Rails5.1+ruby2.5のアプリケーションでも同様にBCryptを採用した
password_hash = Crypt::Password.create("test")
p password_hash
# => "$2a$10$8vSfRpFpQYMXdYCDgV6i2.4yTOD.99DWqA/WYk8h5/YuOptzYJGUy"
- PHPでは検証のためsaltからハッシュを再生成できるが、Ruby側では行えなかった
# PHPで作ったやつを検証したい
password_hash = "$2y$10$i3J7OqQt9h33I5bwSwAge.H6qQtO2LZASwu36AJi3oC69qdXFSx5i"
input_password_hash = BCrypt::Engine.hash_secret("test", BCrypt::Password.new(password_hash).salt)
p password_hash == input_password_hash
# => trueになるはずがfalse
p input_password_hash
# => なぜかnil
原因
- どうにもRuby側のBCrypt実装のバージョンが古いらしい
- 先頭の
$
に囲われてる2y
と2a
が問題で、このバージョンが2y
のほうが2a
より新しいため、Ruby側ではハッシュを再生成できなかった - 参考
- 先頭の
解決方法
- バージョンを上げる、という選択肢は現状だとほぼ不可能な様子...
- とりあえずバージョンを微妙に無視すれば動くことには動きました
- 参考
password_hash = "$2y$10$i3J7OqQt9h33I5bwSwAge.H6qQtO2LZASwu36AJi3oC69qdXFSx5i"
passsword_hash = password_hash.sub(/^.../, '$2a')
p BCrypt::Password.new(passsword_hash).is_password?("test")
# => true
これで良いんだろうか...というもやもやが残る...
良い解決方法があったらコメントで教えていただけると助かります。
っていうかバージョン違うなら例外くらい投げてくれてもいいのになんでnilが返されるんですかね!?!?