linux - 登录时如何比较MD5哈希?
问题描述
CentOS (v6.3 ie) 等 Linux 发行版使用特定的引导管理器,例如“GRUB”,其中包含一个 .conf 文件,您可以在其中编辑用户信息,例如密码等。
密码必须使用 MD5 加密(即:Password --md5 kw485/fgf$&e),这有点令人困惑。
假设 MD5 是一种单向加密方法,并且加密相同的字符串总是会给出一个新生成的字符串。
系统如何比较这两个密码,因为它们永远不会匹配?
这是一个例子:
grub> md5crypt
md5crypt
Password: hello
hello
Encrypted: $1$95Uz30$X/u7PX4F5GtEOsMguDDq10
grub> md5crypt
md5crypt
Password: hello
hello
Encrypted: $1$H8Uz30$LwAkSMZBYC07zJbx3lIVa1
如您所见,我们插入了相同的字符串并得到了两个不同的结果,假设这就是登录场景应该发生的方式,例如:
$ login user
password : hello
- hello 将被转换为
$1$H8Uz30$LwAkSMZBYC07zJbx3lIVa1
grub.conf 中$1$95Uz30$X/u7PX4F5GtEOsMguDDq10
的哈希密码,这是一次失败的登录尝试。
解决方案
哈希
正如您所说,用户在设置密码时输入的密码存储为哈希值。一个好的散列函数是:
- 无法恢复
- 抗碰撞(很难找到两个输入,导致相同的输出)
- 但如果给定相同的输入,则总是产生相同的输出。
假设您的操作系统使用 md5 并以您的密码示例hello为例。hello 的 md5 哈希是
echo -n hello | md5sum
5d41402abc4b2a76b9719d911017c592
所以操作系统会存储5d41402abc4b2a76b9719d911017c592
如果用户再次登录,操作系统将询问他的密码,并且他的输入再次使用相同的函数进行哈希处理,在我们的示例中为 md5。如果输入的密码正确,则哈希匹配。因此,操作系统知道输入了正确的密码,而实际上并不知道密码。
但这5d414...
不是 GRUB 向您显示的字符串,因为实际上它有点复杂。
盐
假设攻击者已经获得了您密码的哈希值。为了防止攻击者获取您的真实密码,操作系统通常会在计算哈希值之前为您的密码添加一个随机值。这个值称为salt,它与用户密码的哈希一起以未加密的形式存储。Salting 可以防止预计算攻击,攻击者会预计算常用密码列表,存储哈希值,然后简单地将窃取的哈希值与该列表进行比较。但是加盐并不能阻止攻击者通过尝试将可能的密码列表与盐值一起作为散列函数的输入并将结果与被盗散列进行比较,从而暴力破解您的密码。
因此,在您的示例中,您第一次输入hello GRUB 时,将盐添加95Uz30
到您的密码中
openssl passwd -1 -salt 95Uz30 hello
$1$95Uz30$X/u7PX4F5GtEOsMguDDq10
结果字符串正是 GRUB 向您展示的,但它不仅仅是哈希值,它是
$x$salt$hash
在哪里
- x 是使用的散列函数,1: md5,更完整的列表参见示例所有 Linux 发行版都使用相同的加密散列函数吗?
- salt 是使用的盐值,这里:
95Uz30
- 哈希是生成的哈希值
这种格式并非特定于 GRUB,密码/etc/passwd
或/etc/shadow
(请参阅影子密码)以相同的方式存储。
推荐阅读
- javascript - 如何枚举私有 JavaScript 类字段
- javascript - 将标题转换为图像
- javascript - 带有 Google Recaptcha v3 的 Django 联系表
- javascript - How can i select multiple values in react js?
- ios - 如何避免firestore中的dup文件?
- python - 提高 Tesseract 精度
- mysql - 在 SQL 中可以进行这种连接吗?
- android - 反应原生地图:onPress 标记事件是延迟
- javascript - WebAssembly 中 call_indirect 的错误结果
- javascript - NetSuite:TypeError record.createCurrentLineItemSubrecord 不是函数?