如何将 PHP 加密实现转换为 Ruby?
How do I convert a PHP crypt implementation to Ruby?
我正在 mac 上开发并部署到 Linux。我正在现有的 PHP 应用程序之上编写 Rails API,因此我无法更改密码或密码,但我需要身份验证才能工作。我需要能够针对现有密码进行身份验证,然后最终更改密码以仍然能够被原始 PHP 应用程序读取。我可以访问确切的 crypt 函数。我需要 Ruby 中的解决方案(可以使用 gem)。
PHP中的代码(改盐保护无辜者)是这样的:
$passwordSHA = crypt($_POST['pass'],'$rounds=21000$abcdefghijklmnopqrstuv$');
我正在尝试编写一个函数来验证用户提供的密码是否与数据库中的加密密码相匹配。我尝试按照 this 的建议使用正确的盐,但它没有用(这可能与未正确包含回合有关)。
存储在数据库中的密码看起来像这样(有点,为了安全而更改)。请注意,开头始终是 $rounds=21000$zxyabcdefghijklm$
:
$rounds=21000$zxyabcdefghijklm$F/L4T80nbaaaaLMb7nPJ2OV5H/aaa.00v900000/Z5jlTLSa.XXXXXX./444444/p8b61UBz9z2Bj4qsABC4.
即使使用 OpenSSL 和 BCrypt,我也尝试了一些不同的东西,但我什至不知道如何获得以 </code>.</p> 开头的东西
<p><strong>更新</strong>:尝试第一个答案,我没有得到接近正确长度的任何东西。也许这些信息有助于弄清楚为什么这不起作用:</p>
<pre><code>2.5.3 :001 > ruby_crypt = "foo".crypt('$rounds=21000$salt$')
=> "A86JNndVTdM"
更新 2:请注意盐长度。它比 UnixCrypt 允许的最大长度 16 长。
更新 3/答案:这里的问题是 salt 应该被截断超过 16 个字符。然后另外 PHP 之后插入轮数。最终答案是:
hashed_password = UnixCrypt::SHA512.build(password, salt, 5000).gsub('', '$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('$rounds=21000$salt$')
# Because 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:
$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
RUBY:
$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
Validate:
true
true
true
我正在 mac 上开发并部署到 Linux。我正在现有的 PHP 应用程序之上编写 Rails API,因此我无法更改密码或密码,但我需要身份验证才能工作。我需要能够针对现有密码进行身份验证,然后最终更改密码以仍然能够被原始 PHP 应用程序读取。我可以访问确切的 crypt 函数。我需要 Ruby 中的解决方案(可以使用 gem)。
PHP中的代码(改盐保护无辜者)是这样的:
$passwordSHA = crypt($_POST['pass'],'$rounds=21000$abcdefghijklmnopqrstuv$');
我正在尝试编写一个函数来验证用户提供的密码是否与数据库中的加密密码相匹配。我尝试按照 this 的建议使用正确的盐,但它没有用(这可能与未正确包含回合有关)。
存储在数据库中的密码看起来像这样(有点,为了安全而更改)。请注意,开头始终是 $rounds=21000$zxyabcdefghijklm$
:
$rounds=21000$zxyabcdefghijklm$F/L4T80nbaaaaLMb7nPJ2OV5H/aaa.00v900000/Z5jlTLSa.XXXXXX./444444/p8b61UBz9z2Bj4qsABC4.
即使使用 OpenSSL 和 BCrypt,我也尝试了一些不同的东西,但我什至不知道如何获得以 </code>.</p> 开头的东西
<p><strong>更新</strong>:尝试第一个答案,我没有得到接近正确长度的任何东西。也许这些信息有助于弄清楚为什么这不起作用:</p>
<pre><code>2.5.3 :001 > ruby_crypt = "foo".crypt('$rounds=21000$salt$')
=> "A86JNndVTdM"
更新 2:请注意盐长度。它比 UnixCrypt 允许的最大长度 16 长。
更新 3/答案:这里的问题是 salt 应该被截断超过 16 个字符。然后另外 PHP 之后插入轮数。最终答案是:
hashed_password = UnixCrypt::SHA512.build(password, salt, 5000).gsub('', '$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('$rounds=21000$salt$')
# Because 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:
$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
RUBY:
$rounds=21000$salt$kvEIl.U0dy6F6y9dkTeTwUrpCOpz5eYK.jyTC2LeKo/gq9HYpDtD6.fMlHyLW.5h3fF4v.R19lX8W18KDvper1
Validate:
true
true
true