根据包含APR1-MD5密码散列的文件检查键入的密码


Checking typed password against file containing APR1-MD5 hashes of passwords

我在一个网站上工作,该网站试图在登录时从Apache身份验证切换到PHP身份验证。密码当前存储在一个文件中,并以Apache自己的md5格式(例如$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1)进行加密。

密码未存储在数据库中。

现在,我正在编写一个PHP登录脚本。我的问题是,如何检查键入的密码是否与文件中的加密密码相同?我已经找到了基于纯文本密码生成APR1-MD5的代码,但这不是我所需要的,因为它生成的代码与文件中的代码不同。

长话短说,有没有一种方法可以同样地检查键入的密码是否确实是保存在文件中的密码?

我知道Apache有用于生成这些代码的开源代码,但代码是用C编写的,我对此一无所知。

肯定有一种方法可以在不更改每个用户密码的情况下从Apache身份验证迁移到PHP?

据我所知,密码来自您的登录功能。你必须对照APR1-md5散列来检查这个密码。如果你的登录页面不包含任何用户名,这将很难搜索。但如果你有相应密码的用户名,它可以实现:

假设登录函数发送两个参数:$username和$password。将APRI-md5密码文件称为"password.txt"。我将解释的方法只有在password.txt文件中有用户名并且登录脚本中的用户名与password.txt中的用户名相同时才有效。

$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1密码散列有三个部分:

apr1=格式标识符[静态,每个密码行相同]

z6hoasr5=salt文本[每个密码不同]

0Kk7p/8Hfhy9nBxu/hFUj1=实际md5哈希字符串

即使输入文本相同,也不能通过此方法生成相同的密码,除非使用相同的salt文本。所以,要生成相同的散列字符串并与输入进行比较,您必须知道给定用户的salt文本是什么。

例如,当您从登录脚本中获得$username和$password时,您应该在password.txt文件中找到username。然后,您应该从password.txt中提取salt文本部分(在您的示例中,"z6hoar5")。然后使用这个salt文本和$password[来自登录],您应该生成APR1-md5哈希。(您可以修改http://www.php.net/manual/en/function.crypt.php#73619以便将$salt作为输入参数。因此,您可以发送salt和文本并获得密码散列)。如果密码正确,则使用password.txt中的salt文本新建的哈希字符串将与password.txt相同。然后可以进行字符串比较,检查密码是否有效。

我自己也遇到过这个问题,我认为我应该发布一个好的解决方案。我从人们之前的工作开始,并将其打磨成经过测试和打包的解决方案。

composer.json:

"require": {
  "whitehat101/apr1-md5": "~1.0"
}

用途:

// Check plaintext password against an APR1-MD5 hash
APR1_MD5::check('plaintext', '$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1'); // bool
// Hash a password with a known salt
echo APR1_MD5::hash('PASSWORD', 'z6hoasr5');
// Hash a password with a secure random salt
echo APR1_MD5::hash('PASSWORD');

由于害怕对.htpasswd文件进行I/O操作,我认为这个库几乎涵盖了人们想要使用Apache的APR1-MD5哈希进行的所有操作。