PHP:crypt()函数。请问其加密后的密值有可能等于盐值么?

发布于 2022-09-04 21:10:24 字数 258 浏览 19 评论 0

最近看到一个web应用中,别人关于用户验证这一块,用到了PHP:crypt(string str, string [salt]) 这个函数。具体的代码如下:

if ($auth != crypt(md5($cdata), $auth))
{
   exit(); //exit,验证失败;
}
//验证成功,运行之后代码;

我想请问一下,这个函数中的加密后的密值怎么会等于盐值的,要怎样这个验证条件才能成立啊???根本想不通啊,求教!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最丧也最甜 2022-09-11 21:10:25

先说结论,可以的。

Yii中的发现

今天在研究Yii2.0框架关于密码登陆的问题,同样发现这个问题。经过亲身实践,发现原理。

举个简单例子:

<?php
$password = '1234567';
$hash = '$2y$13$4Y5KRDHPFYF.rYumLe6rx.4IcM6PIB6KQWQHpWwVnN5PMnJnd/4ia';
$test = crypt($password,$hash);
echo $test==$hash; //判断密码crypt后是否和盐值一样
?>

>>> 1  //输出

原因

原因在于这个hash不是一个标准的hash。

标准的Blowfish Hash应该是以$2a$$2x$或者$2y$开头,然后是用于cost参数的两位数字,紧接着一个$字符,最后是22位./0-9A-Za-z范围里的字符.

所以这个hash应该是到了$2y$13$4Y5KRDHPFYF.rYumLe6rx.就结束了,那么后面的4IcM6PIB6KQWQHpWwVnN5PMnJnd/4ia好像就被crypt忽略了。

而实际上,后面的4IcM6PIB6KQWQHpWwVnN5PMnJnd/4ia就是加密后的密值一部分。

所以通过这个原理,数据库里直接把这个特异hash保存后,直接比对是否和crypt后的密值相同,同则通过登录,不同则拒绝。

執念 2022-09-11 21:10:25

一系列测试:

crypt("abc", "12") == "12BWKETBcM70Q";
crypt("abc", "123") == "12BWKETBcM70Q";
crypt("abc", "1234") == "12BWKETBcM70Q";
crypt("abc", "12BWKETBcM70Q") == "12BWKETBcM70Q";

其实你也能看出来了,默认CRYPT_STD_DES算法下,盐值只有前两位有效,而且盐值会保存在结果的前两位。

文档也说了:

基于标准 DES 算法的 crypt() 在输出内容的开始位置返回两个字符的盐值。

CRYPT_STD_DES - 基于标准 DES 算法的散列使用 "./0-9A-Za-z" 字符中的两个字符作为盐值

其他算法产生的hash也有类似的机制,在结果起始部分保存盐值,计算hash时只取符合格式的部分作为盐值,这些在官方文档都有描述。

私货:
bcryptjs 同一个字符串 每次生成的 hash 值都不一样

撩动你心 2022-09-11 21:10:25

这代码写的有问题吧。这咋可能相等啊,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文