ruby-on-rails - 为什么 BCrypt 不再接受哈希值?

标签 ruby-on-rails bcrypt-ruby mongodb-3.6 fedora-28

上周我将 Fedora 升级到全新的 28 版本,其中 mongodb 升级到 3.6。请参阅How to repair mongodb service after an upgrade to Fedora 28?我如何设法解决我的第一个问题,即 mongod 将不再启动。现在,我在使用同一数据库的 Rails 应用程序上遇到了另一个问题。

这很可能与 mongodb 升级无关,但我认为可能值得提供该上下文,并且不要因为未提供足够的上下文而错过解决方案。

因此,自从系统升级以来,此 Rails 项目上的任何登录尝试都将失败,并显示 BCrypt::Errors::InvalidHash in Devise::SessionsController#create 错误,在bcrypt (3.1.11) lib/bcrypt/password.rb:60:in处引发初始化'`。在项目的 Rails 控制台中进一步分析,似乎对此方法的任何调用都会失败:

> BCrypt::Password.create('TestPassword')
BCrypt::Errors::InvalidHash: invalid hash
from /home/psychoslave/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bcrypt-3.1.11/lib/bcrypt/password.rb:60:in `initialize'

我尝试bundle卸载/重新安装bcrypt ,甚至使用 bcrypt gem 的 github 存储库版本来代替,但它没有改变任何东西。

查看/home/psychoslave/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bcrypt-3.1.11/lib/bcrypt/password.rb:60:in初始化'`,问题似乎是哈希无效。

# Initializes a BCrypt::Password instance with the data from a stored hash.
def initialize(raw_hash)
  if valid_hash?(raw_hash)
    self.replace(raw_hash)
    @version, @cost, @salt, @checksum = split_hash(self)
  else
    raise Errors::InvalidHash.new("invalid hash")
  end
end

对应的测试如下:

  def valid_hash?(h)
    h =~ /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/
  end

哈希本身是通过 BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost)) 创建的,在我使用的平台中调用 __bc_crypt(secret.to_s, salt) ,这似乎是在调用 bcrypt-3.1.11/ext/mri/bcrypt_ext.c .

更重要的是,添加 binding.pryvalid_hash?方法,可以查看调用 BCrypt::Password.create('TestPassword') 返回的哈希值。 ,它实际上是一个相当长的字符串,其开头似乎很常见,但最终的序列很可能是错误生成的:

"$2a$10$Eb1f8DSkGh4G1u5GicyTYujBk6SwFXKYCH.nqxapmBlqJ0eFYdX32\x00\x00\x00\x00\xD1F\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00T\xBD\x02\x00\x00\x00\x00\x00\xF1V\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xE2\xB0\x02\x00\x00\x00\x
00\x00AW\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00 \x04\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xB5\xF8\x0E\x00\x00\x00\x00\x00q\xD8\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00…"

如果您可能感兴趣的话,我可以提供整个哈希的转储(大约 32Ko!)。

最佳答案

这里有一个规避解决方案,可以使bcryptrspec再次成功通过所有测试。

在等待正确的解决方案时,这确实是一个丑陋的黑客行为,但在此之前它会完成工作。只需更改 ~/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bcrypt-3.1.11/lib/bcrypt/engine.rb (适应路径,当然),第 51 行来自:

- __bc_crypt(secret.to_s, salt)
+ __bc_crypt(secret.to_s, salt).gsub(/(\n|\x00).*/, '')

也就是说,从第一个出现的“\x00”或“\n”(如果有)开始中继字符串。

贷方票据:this version of the hack was proposed通过 Andrey Sitnik ,在发现它之前,我独立地替换了我在这里提出的那个。

之后,BCrypt::Password#create 将再次起作用:

> BCrypt::Password.create('TestPassword')
=> "$2a$10$YPRnQF3ZihXHpa9kSx7Mpu.j28PlbdwaNs2umSQvAGkS.JJ.syGye"

关于ruby-on-rails - 为什么 BCrypt 不再接受哈希值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50213071/

相关文章:

ruby - 为什么 Ruby 的 bcrypt 库在散列中以明文形式包含盐?

ruby-on-rails - Rails-无法保存用户密码 bcrypt

mongodb - 如何在 MongoDB 3.6 中增加具有一秒值的日期字段?

MongoDB聚合: remove some elements from embedded array (redact?)

ruby-on-rails - 在模型文件中调用的辅助方法不起作用

ruby-on-rails - 有人请解释 rails 3 中表单的选择/选项

ruby-on-rails - 是否可以禁用 collection_select 的提示?

ruby-on-rails - 使用 Rails 将图像嵌入电子邮件的正确方法是什么?

ruby-on-rails - 实现 has_secure_password 后出现错误消息

java - 如何在 ERROR 日志级别模式下运行 mongodb 实例?