问题描述
我正在Mac上进行开发并部署到Linux。我是在现有PHP应用程序的顶部编写Rails API,因此无法更改密码或密码,但需要进行身份验证才能工作。我需要能够针对现有密码进行身份验证,然后最终更改密码以仍然能够被原始PHP应用读取。我可以访问确切的crypt函数。我需要使用Ruby的解决方案(可以使用gem)。
$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。
UPDATE 3 / ANSWER :这里的问题是盐应该被截断超过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