Ruby
PHP
bcrypt
パスワード
ハッシュ

PHPのpassword_hashで生成したBCryptハッシュがRubyで検証できずにハマった

起きたこと

  • 既存の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

原因

解決方法

password_hash = "$2y$10$i3J7OqQt9h33I5bwSwAge.H6qQtO2LZASwu36AJi3oC69qdXFSx5i"
passsword_hash = password_hash.sub(/^.../, '$2a')
p BCrypt::Password.new(passsword_hash).is_password?("test")
# => true

これで良いんだろうか...というもやもやが残る...

良い解決方法があったらコメントで教えていただけると助かります。

っていうかバージョン違うなら例外くらい投げてくれてもいいのになんでnilが返されるんですかね!?!?