algorithm - 将旧密码迁移到 CakePHP 3

标签 algorithm hash passwords salt cakephp-3.0

我正在阅读 Cake 3 网站上的 Auth 文档here ,我仍然对如何将我的用户的密码迁移到我的新应用程序有点困惑。

它说要包含 FallbackPasswordHasher 类,但如果是这种情况,我应该将旧密码的盐放在哪里(因为新站点的情况不同)?除此之外,一切似乎都是不言自明的。

我有几个不同但相关的网站,我将它们整合到一个网站中,这些网站将在多个企业中提供相同的服务,因此我需要从使用不同盐的各种网站导入用户的密码。

最佳答案

这取决于使用的旧哈希机制

根据所使用的机制和算法,您可能不需要旧的 salt,因为它已经附加到散列,例如,使用 Blowfish 密码散列器散列的密码就是这种情况,或者通常使用 crypt() 散列的密码,它们可以由 Default 密码哈希器验证。

因此,如果您的所有密码都是这种情况,那么您根本不需要使用 Fallback 密码哈希器,而可以仅使用 Default 密码哈希器,并在必要时重新哈希密码 as shown in the docs

不加盐的哈希

对于使用不将盐附加到散列的机制进行散列的密码,例如 md5()sha1()mhash() 等,您可能需要一个自定义的旧密码散列器,其中包含已用于旧密码的盐。

在大多数情况下,WeakPassword hasher 应该完成这项工作,它使用旧的 Cake 2 机制和 salt 配置,即全局 Security.salt 选项和 hashType hasher 选项。

Cookbook > Authentication > Changing Hashing Algorithms

如果弱散列器对您不起作用,因为例如您在旧应用程序中使用了自定义散列器,那么您将需要一个自定义旧散列器。旧密码散列器 can be found in the docs 的示例,加入盐应该像示例一样简单

namespace App\Auth;

use Cake\Auth\AbstractPasswordHasher;

class LegacyPasswordHasher extends AbstractPasswordHasher {

    public function hash($password) {
        throw new \LogicException('You really should not use me!');
    }

    public function check($password, $hashedPassword) {
        // compare using the legacy salt
        return sha1($password . 'legacy-salt-here') === $hashedPassword;
    }

}

请注意,在使用 Fallback 散列器的情况下,传统散列器不需要实现 hash() 来实际散列某些东西,因为您不应该将它用于新的散列。

每个应用程序不同的盐和/或算法

拥有来自不同来源的密码,其中使用了单独的盐,可能会使事情变得更加复杂。

有多种方法可以解决这个问题,最明显的方法(因为这就是 Fallback 哈希器的工作方式)是为每个应用程序创建一个单独的自定义遗留哈希器,不同的哈希器将使用适当的盐,也许还有特定应用程序的算法。

然后您需要做的就是依靠 Fallback 哈希器迭代所有旧哈希器,直到其中一个成功验证密码。

'passwordHasher' => [
    'className' => 'Fallback',
    'hashers' => ['Default', 'LegacyApp1', 'LegacyApp2', 'LegacyApp3', /* ... */]
]

就这样?

基本上,是的,这里唯一的问题可能是冲突,即 App X 的哈希器将成功验证密码,该密码通常会被哈希器评估为 false App Y 的密码来自何处。

如果这是一种可能出于任何原因的情况(即使对于非常弱的 MD5,通常也不太可能发生),您必须寻求更严格的解决方案。

可能有 10^Cake 方法来解决这样的问题,所以由于冲突应该是不太可能的,我会坚持我认为最基本的方法,那就是在合并密码之前修改密码,以便它们有一个标识符添加了标识旧应用程序的功能,然后旧密码哈希器可以使用它来选择适当的盐和算法。

一个例子

例如,如果 App 1 的旧密码是
de1566cc82d9fda1ac39a28a45afe3671d9ef880

app1 前面加上一个唯一的分隔符,这个分隔符不能出现在任何旧的和新的密码哈希中)使密码列包含类似的内容
app1:::de1566cc82d9fda1ac39a28a45afe3671d9ef880

并在您的旧密码哈希器中检查它是否执行类似的操作

public function check($password, $hashedPassword) {
    if(strpos($hashedPassword, ':::') === false) {
        // this is not the password you are looking for
        return false;
    }
    // separate the identifier from the password
    list($app, $hashedPassword) = explode(':::', $hashedPassword, 2);

    // create comparision hash using app specific legacy algorithms and salts
    switch($app) {
        case 'app1':
            $compare = sha1($password . '375828236784563245364');
            break;

        case 'app2':
            $compare = md5('legacy-salt-for-app-2' . $password);
            break;,

        // etc

        default:
            return false;
    }

    return $compare === $hashedPassword;
}

正如最初提到的,有很多方法可以解决这个问题,显示的方法只是其中之一,但是这应该会提示您完成此类任务通常需要什么。

ps,请注意这里所有的示例代码都是未经测试的!

关于algorithm - 将旧密码迁移到 CakePHP 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27336798/

相关文章:

algorithm - 如何定义哪些对角线属于凹多边形

python - 有没有办法在 python 中使用 opencv 获得更清晰和连续的边缘?

java - 忘记密码请求 (Java)

c++ - 基于 C++ 中的另一个变量类型派生变量类型

hash - 更快地找到正确的 block 顺序以获得已知的 SHA1 哈希?

MySQL 5.6.26 (Windows 8.1 x64) : Trouble with setting a password for the root MySQL user

linux - 托管 Subversion (svn) 存储库的密码过期如何工作?

arrays - 在矩阵中找到连接单元格的最有效方法

algorithm - swift中的优先级队列

postgresql - 如何使用字符串作为 PostgreSQL 咨询锁的键?