转换PHP';s密码\u验证到Ruby on Rails

转换PHP';s密码\u验证到Ruby on Rails,php,ruby-on-rails,ruby,Php,Ruby On Rails,Ruby,我们正在将我们的站点从一个旧的PHP框架转换为Rails,并且非常希望用户能够继续使用他们的旧密码登录。在旧站点上,我们使用密码散列和密码验证来散列和验证密码。然而,在Rails上,我似乎无法让它验证旧密码 以下是我们在PHP中的功能: 散列: 核实: password_verify($user['salt'] . $password . $user['salt'], $user['password']) 在新的Rails框架上,我们使用Desive,并构建了一个自定义迁移脚本,以移动所有内容

我们正在将我们的站点从一个旧的PHP框架转换为Rails,并且非常希望用户能够继续使用他们的旧密码登录。在旧站点上,我们使用密码散列和密码验证来散列和验证密码。然而,在Rails上,我似乎无法让它验证旧密码

以下是我们在PHP中的功能:

散列:

核实:

password_verify($user['salt'] . $password . $user['salt'], $user['password'])
在新的Rails框架上,我们使用Desive,并构建了一个自定义迁移脚本,以移动所有内容,并根据数据库中存储的密码版本识别正确的密码散列方法,这就是我在用户模型中使用的:

def valid_password?(password)
  if password_version == 'legacy'
    hash = BCrypt::Password.new(encrypted_password)
    hash_str = password_salt+password+password_salt

    return hash.is_password? hash_str
  end

  super(password)
end

如果您有任何想法,我们将不胜感激

PHP
密码\u散列的格式大致如下所示:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
默认的Ruby Bcrypt方法生成以下形式的密码:

$2a$10$GtKs1Kbsig8ULHZzO1h2TetZfhO4Fmlxphp8bVKnUlZCBYYClPohG
对于干净的解决方案,您始终可以通过
$2y
$2a
前缀来区分两者。当格式列已经烘焙到格式中时,就不需要它了

例如:

case (encrypted_password[0,3])
when '$2y'
  # Legacy PHP password
  BCrypt::Password.new(encrypted_password.sub(/\A\$2y/, '$2a')).is_password?(salt + password + salt)
when '$2a'
  # Ruby BCrypt password
  BCrypt::Password.new(encrypted_password).is_password?(password) 
else
  # Unexpected type?
end

要成功验证密码,您需要使用Ruby的方法将密码重新写入数据库,以逐渐替换所有旧的PHP格式的密码。

password\u verify并不复杂。传入新pw和原始pw哈希。将crypt方法+salt从散列中拉出,使用它们重新散列新的pw,然后比较结果散列值。@Script47是的,它应该在那里。@MarcB是的,这基本上就是我要做的。据我所知,它应该使用bcrypt,因此rails部分应该可以工作,我本以为
password\u hash
应该在不需要盐的情况下工作。添加一个只会把事情搞砸。你为什么这么做?。让它自己添加。您将获得存储在hashYep中的salt,正如我在问题中所说的,我已经知道哪些密码是哪些密码,这只是(在ruby中)用PHP哈希验证密码的问题。我想保留密码_版本,因为有一个更旧的旧密码版本正在使用,因为目前的网站没有用新的格式取代这些,它只是允许他们继续工作。我已经得到了一个很好的工作,因为它只是一个杂烩与盐我说,它应该取代他们的新版本。这里有一些测试数据可以用来说明所需的输出吗?它将取代它们,旧版本没有,所以我将使用BCrypt@jakeb我已经用一些示例代码更新了答案。您的
valid\u密码?
方法需要同时获取提供的密码和您的旧
salt
值。@jakeb以前在Python和Node.js中处理PHP密码时,我必须执行类似的操作。很高兴它成功了!
case (encrypted_password[0,3])
when '$2y'
  # Legacy PHP password
  BCrypt::Password.new(encrypted_password.sub(/\A\$2y/, '$2a')).is_password?(salt + password + salt)
when '$2a'
  # Ruby BCrypt password
  BCrypt::Password.new(encrypted_password).is_password?(password) 
else
  # Unexpected type?
end