使用 Ruby 验证 Python 生成的 SHA256 字符串

Verifying Python generated SHA256 strings using Ruby

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

使用 Python Passlib 库以 SHA256 格式保存的示例密码: $rounds=110000QB3mR7z8SVQwVDtjT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6 这是 password

我发现的 gem 是:

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

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

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

根据@Niel Slater 的评论,我使用 UnixCrypt 的 build 重新哈希 "password",它仍然与 Python 哈希字符串不同。

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

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

您的问题是出于某种原因您认为 $rounds=110000QB3mR7z8SVQwVDtjT2mdn9XHRD.O8gsCJXoUTDWJSLrY09uD8KZp78ou6password 的散列。不是。

在Python中:

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

在Ruby中:

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

还有:

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

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