【问题标题】:Verifying Python generated SHA256 strings using Ruby使用 Ruby 验证 Python 生成的 SHA256 字符串
【发布时间】:2015-09-17 08:18:32
【问题描述】:

我正在将 Python 项目转换为 Rails,它们都使用相同的数据库,并且我正在尝试使用 Ruby 来验证使用名为 passlib.hash.sha256_crypt 的 Python 库保存的密码。我想使用 Ruby 来验证用户输入的密码与使用任何 Ruby 库保存的密码相比是否是有效密码,但找不到任何合适的 gem。

使用 Python Passlib 库以 SHA256 保存的示例密码: $5$rounds=110000$4QB3mR7z8SVQwVDt$1jT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6 这是password

我发现的宝石是:

  1. Ruby Digest library : 没有以$5$..... 的格式生成
  2. Unix Crypt : 生成相关格式的摘要,但无法验证结果
  3. Gibberish : 只推进AES模式解密,不生成$5$.....格式

Unix Crypt 是最相关的解决方案,但生成的字符串“密码”摘要与 Python 生成的摘要不同。我试图从保存的摘要中删除rounds 并验证它,但它失败了,我认为这是因为他们使用不同的rounds 来生成摘要。

[7] pry(main)> UnixCrypt::SHA256.build("password")
=> "$5$qbpSpYyYoTCr0q4G$/jyjVRgg3Y4vQj39f9OWwUQhKOh70bTB50jH7WfsZl2"
[10] pry(main)> UnixCrypt.valid?("password", "$5$rounds=110000$4QB3mR7z8SVQwVDt$1jT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6")
=> false
[11] pry(main)> UnixCrypt.valid?("password", "$5$4QB3mR7z8SVQwVDt$1jT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6")
=> false

根据@Niel Slater 的评论,我使用了UnixCrypt 的build 重新散列“密码”,它仍然不同于Python 散列字符串。

[81] pry(main)> UnixCrypt::SHA256.build("password", "4QB3mR7z8SVQwVDt", 110000)
=> "$5$rounds=110000$4QB3mR7z8SVQwVDt$hF/KhMEITeydgv58fXf2brManFYwhhy.dMqGnrkrLb1"

有什么解决方法,或者有没有更简单的方法来验证 Ruby 中的用户密码?我对加密不熟悉,也欢迎任何关于轮次和摘要的详细解释。

【问题讨论】:

  • 字符串是不同的,因为它们包含一个随机的 salt(Python 版本中的第 3 个和第 4 个 $ 之间的值),所以你永远不会看到相同的哈希.您可以通过在 Python 中重新散列“密码”来确认这一点,并注意到它每次都不同。验证失败更多的是一个问题,这意味着 python 和 Ruby 版本之间的格式和/或算法存在一些其他差异。

标签: python ruby-on-rails ruby sha256


【解决方案1】:

您的问题是您认为$5$rounds=110000$4QB3mR7z8SVQwVDt$1jT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6password 的哈希值,出于某种原因。不是。

在 Python 中:

hash = sha256_crypt.encrypt("password", rounds=110000, salt='4QB3mR7z8SVQwVDt')
# '$5$rounds=110000$4QB3mR7z8SVQwVDt$hF/KhMEITeydgv58fXf2brManFYwhhy.dMqGnrkrLb1'

在 Ruby 中:

UnixCrypt::SHA256.build("password",'4QB3mR7z8SVQwVDt', 110000 )
# "$5$rounds=110000$4QB3mR7z8SVQwVDt$hF/KhMEITeydgv58fXf2brManFYwhhy.dMqGnrkrLb1"

还有:

UnixCrypt.valid?("password", 
   "$5$rounds=110000$4QB3mR7z8SVQwVDt$hF/KhMEITeydgv58fXf2brManFYwhhy.dMqGnrkrLb1")
# => true

因此,Ruby gem unix-crypt 是解决您的问题的最简单选择,因为它与 Python 库 passlib 匹配最简单(无需弄清楚细节,只需在整个过程中使用相同的参数和字符串值) .

【讨论】:

  • 这是我的错误,最终原文根本不是“密码”。感谢您的提示! UnixCrypt 是宝石,但 README 文档不够详细,所以在我在 rdoc 中找到它之前,我不知道 roundsalt 选项是否可用。
  • 这是那些简单的错误之一,一旦成为测试的假设,可能会让您费尽心思并浪费时间。我删除了有关可能存在的错误的 cmets,看起来 Ruby 和 Python 在算法的细节上非常一致。
猜你喜欢
  • 2020-05-04
  • 2017-06-22
  • 1970-01-01
  • 2016-02-19
  • 2015-07-13
  • 2010-09-07
  • 1970-01-01
  • 2014-07-16
  • 1970-01-01
相关资源
最近更新 更多