【问题标题】:Ruby-BCrypt: Specify saltRuby-BCrypt:指定盐
【发布时间】:2019-05-16 16:19:54
【问题描述】:

是否可以指定使用 ruby​​-bcrypt 加密字符串时使用哪种盐?

我知道它不是很安全,但我只将它用于安全性不高的数据: 我有一个平台,当用户删除他的帐户时,我仍然想知道该用户之前是否使用此电子邮件注册过(由于注册时免费积分)。

所以我想我会用 Bcrypt 加密电子邮件(在删除之前),然后当用户想用这个电子邮件地址再次注册时,我可以在之后查询这个哈希是否存在?

但现在我意识到 bcrypt 总是会产生新的盐......我可以以某种方式指定盐吗?

谢谢,

免责声明/注意:

一般来说,您永远不应该直接指定盐 - 它不安全!!!

【问题讨论】:

  • 您不能将唯一的盐值与密码哈希一起存储在某个地方吗? (如果你只有一个字段可以使用,你可以在散列的电子邮件地址和 salt 之间粘贴一个已知的分隔符)
  • 等等,我是个白痴。 Bcrypt 已经处理了 hash + salt 的存储。

标签: ruby-on-rails ruby bcrypt bcrypt-ruby


【解决方案1】:

是的,你可以:

BCrypt::Engine.hash_secret( 'foo@example.com', "$2a$10$ThisIsTheSalt22CharsX." )

前 7 个字符在技术上不是盐,它们标识 bcrypt 算法,并将迭代次数设置为 2**10 == 1024。不过,为简单起见,Ruby 的 bcrypt 模块将第一个字符视为盐的一部分,所以你也需要。您可能应该使用

BCrypt::Engine.generate_salt

创建你的共享盐,因为这并不依赖于你想出一些“随机”的东西。

为了稍微提高安全性,您可以将盐与可搜索的哈希分开,并将其视为应用中的任何其他秘密数据。例如,将其设置为一个配置项,并且只存储 bcrypt 的哈希部分以供搜索(第一部分对您来说是多余的数据,并且会降低搜索的性能,尽管这种影响可能很小):

email = 'foo@example.com'
full_hash = BCrypt::Engine.hash_secret( email, settings.email_search_salt )
searchable_hash = full_hash[29,31]
# Either store or search . . .

【讨论】:

  • 您的回答是对的,但我会接受 struthersneil 的回答,因为他先发帖...不过谢谢!我会赞成你的回答。
【解决方案2】:

可以使用BCrypt::Password.create,将电子邮件传递给它,生成这些哈希值以及唯一的盐。

2.0.0-p195 :003 > hashed_email = BCrypt::Password.create 'joe@test.com'
 => "$2a$10$vX2tl3omW9h4k66XC7/BwOFH0n7EqtH4PJATPa7YVSeJh7TEpt/bK" 
2.0.0-p195 :004 > hashed_email = BCrypt::Password.create 'joe@test.com'
 => "$2a$10$RdQIHtz.L5To1F1XRK//..h6nHYdQ3uJ2PTgB58e3xufoqgZGqbO6" 
2.0.0-p195 :005 > hashed_email = BCrypt::Password.create 'joe@test.com'
 => "$2a$10$bTFVXO/d0/sf6SxzCcRMU.zBPcR5yjI6ID6O9J2eXKbqim/jPM3PC" 
2.0.0-p195 :006 > hashed_email = BCrypt::Password.create 'joe@test.com'
 => "$2a$10$gbXU4UEiHTC0HCnD672Dm.TeBhZeCa6sBiX8Pk50KSXcprDJnEYA." 

现在您不必担心使用固定盐,因为 BCrypt 已经为您存储了哈希值。

但我猜你已经确定这意味着稍后会有与比较相关的处理成本,因为你不能只做一个'SELECT user WHERE email_hash = hash '...

如果你绝对想使用固定盐,你可以。

salt = BCrypt::Engine.generate_salt
hash = BCrypt::Engine.hash_secret 'hello', salt

(只需将该盐字符串存储在某个地方,以后可以使用它。)

【讨论】:

  • OP 需要一个固定的盐,以便对电子邮件进行数据库搜索,而无需存储电子邮件明文。我对列入黑名单的信用卡号码和 AFAIK 做了类似的工作,保持结果可搜索的唯一解决方案是使用固定盐。
  • 这是我在第二段之后的描述。
  • 或者换一种说法:“这确实意味着稍后会有与比较相关的处理成本”,假设该站点足够受欢迎以至于有一千封电子邮件要检查,那么您是讨论 分钟 的 CPU 时间,以便系统确定之前是否已经看到过注册。在每次注册时。
  • 我正在弄清楚 OP 的推理过程......然后在那里提供答案。也许“我愿意”这个词太具有暗示性了。好的。重新措辞。
  • 您不应该直接将hash 存储到数据库中,因为这将在数据库中包含盐(这里实际上是胡椒),如果目的是电子邮件假名,则它毫无价值。相反,请按照 Neil 的回答中的建议去除盐。
【解决方案3】:

这是一个非常古老的线程,但仍然......这里是使用固定盐 bcrypt 的其他选项:

如果安全不是问题(仅仅是混淆):使用 md5

Digest::MD5.hexdigest 'some value'

优点:计算成本低(生成速度更快)

缺点:计算成本低(黑客攻击速度更快)

如果存在安全问题,您可以使用共享密钥(无哈希)对其进行加密。见https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL.html#module-OpenSSL-label-Encryption

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 2014-01-31
    • 2015-04-24
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    相关资源
    最近更新 更多