我正在 Mac 上进行开发并部署到 Linux。我正在现有 PHP 应用程序之上编写 Rails API,因此我无法更改密码或密码,但我需要身份验证才能工作。我需要能够根据现有密码进行身份验证,然后最终更改密码,使其仍然能够被原始 PHP 应用程序读取。我可以访问确切的 crypt 函数。我需要一个 Ruby 解决方案(可以使用 gem)。
PHP 中的代码(为了保护无辜而更改了盐)是这样的:
$passwordSHA = crypt($_POST['pass'],'$6$rounds=21000$abcdefghijklmnopqrstuv$');
我正在尝试编写一个函数来验证用户提供的密码是否与数据库中的加密密码匹配。我尝试做什么 this建议使用正确的盐,但它不起作用(这可能与未正确包含回合有关)。
存储在数据库中的密码看起来像这样(为了安全起见,进行了一些更改)。请注意,开头始终是 $6$rounds=21000$zxyabcdefghijklm$
:
$6$rounds=21000$zxyabcdefghijklm$F/L4T80nbaaaaLMb7nPJ2OV5H/aaa.00v900000/Z5jlTLSa.XXXXXX./444444/p8b61UBz9z2Bj4qsABC4.
即使使用 OpenSSL 和 BCrypt,我也尝试了一些不同的方法,但我不知道如何获得以 $6
开头的东西。
更新:尝试第一个答案,我没有得到任何接近正确长度的内容。也许这些信息有助于弄清楚为什么这不起作用:
2.5.3 :001 > ruby_crypt = "foo".crypt('$6$rounds=21000$salt$')
=> "$6A86JNndVTdM"
更新 2:请注意盐长度。它比 UnixCrypt 允许的最大长度 16 长。
更新 3/答案:这里的问题是盐应该被截断超过 16 个字符。然后 PHP 会在后面插入轮数。最终答案是:
hashed_password = UnixCrypt::SHA512.build(password, salt, 5000).gsub('$6', '$6$rounds=21000')
最佳答案
使用UnixCrypt为了方便起见,这似乎有效:
require 'unix_crypt'
PHP_CMD = %q|php -r 'echo crypt("foo", "\$6\$rounds=21000\$salt\$");'|
php_crypt = `#{PHP_CMD}`
puts "PHP:"
puts php_crypt
# This code is using native crypt and is platform dependent and not portable
# ruby_crypt = 'foo'.crypt('$6$rounds=21000$salt$')
# Because $6 means SHA512, we can use UnixCrypt instead for portability (thanks @matt)
ruby_crypt = UnixCrypt::SHA512.build('foo', 'salt', 21000)
puts "\nRUBY:"
puts ruby_crypt
# If doing password validation only, it is best to use the 'valid?' method,
# as it will handle modifications in the algorithm and salt automatically.
puts "\nValidate:"
p php_crypt == ruby_crypt
p UnixCrypt.valid?('foo', php_crypt)
p UnixCrypt.valid?('foo', ruby_crypt)
输出:
PHP:
$6$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
RUBY:
$6$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
Validate:
true
true
true
关于php - 如何将 PHP crypt 实现转换为 Ruby?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63435183/