为什么每次“openssl passwd”的输出都不一样?

Sto*_*row 4 linux openssl

openssl passwd 命令计算在运行时键入的密码的哈希值或列表中每个密码的哈希值。密码列表取自选项 -in 文件的命名文件、选项 -stdin 的标准输入以及其他情况下的命令行。可以使用 UNIX 标准算法 crypt 和基于 MD5 的 BSD 密码算法 1 及其 Apache 变体 apr1。

我理解术语“散列”的意思是“将输入转换为难以/不可能导出原始输入的输出”。更具体地说,散列后的输入:输出关系是N:M,其中M<=N(即可能发生散列冲突)。

为什么“ openssl passwd”的输出在相同的输入下连续运行?

> openssl passwd
Password:
Verifying - Password:
ZTGgaZkFnC6Pg
> openssl passwd
Password:
Verifying - Password:
wCfi4i2Bnj3FU
> openssl passwd -1 "a"
$1$OKgLCmVl$d02jECa4DXn/oXX0R.MoQ/
> openssl passwd -1 "a"
$1$JhSBpnWc$oiu2qHyr5p.ir0NrseQes1
Run Code Online (Sandbox Code Playgroud)

我一定不明白这个函数的目的,因为它看起来像在同一个输入上运行相同的哈希算法会产生多个唯一的输出。我想我对这种看似 N:M 的输入:输出关系感到困惑,其中 M>N。

tel*_*coM 10

> openssl passwd -1 "a"
$1$OKgLCmVl$d02jECa4DXn/oXX0R.MoQ/
Run Code Online (Sandbox Code Playgroud)

这是扩展的 Unix 风格crypt(3)密码哈希语法,特别是它的 MD5 版本。

第一个$1$标识哈希类型,下一部分OKgLCmVl是用于加密密码的盐,然后在分隔$符之后到行尾是实际的密码哈希。

因此,如果您从第一个加密中取出 salt 部分并将其与后续加密一起使用,您应该始终得到相同的结果:

> openssl passwd -1 -salt "OKgLCmVl" "a"
$1$OKgLCmVl$d02jECa4DXn/oXX0R.MoQ/
> openssl passwd -1 -salt "OKgLCmVl" "a"
$1$OKgLCmVl$d02jECa4DXn/oXX0R.MoQ/
Run Code Online (Sandbox Code Playgroud)

当您更改密码时,您应该始终切换到新的盐。这可以防止任何人事后发现新密码是否与旧密码相同。(如果你想防止旧密码的重复使用,你当然可以将新密码候选哈希两次:一次使用旧盐,然后,如果结果与旧密码不同,因此可以接受,再次使用新密码盐。)

如果不openssl passwd带任何选项使用,您将获得原始的crypt(3)-compatible 散列,如 dave_thompson_085 所述。有了它,盐是散列的两个第一个字母:

> openssl passwd "a"
imM.Fa8z1RS.k
> openssl passwd -salt "im" "a"
imM.Fa8z1RS.k
Run Code Online (Sandbox Code Playgroud)

您不应在任何新实现中使用这种旧的哈希样式,因为它将有效密码长度限制为 8 个字符,并且盐量太少,无法充分抵御现代方法。

(我曾经计算过为每个经典crypt(3)散列存储一整套彩虹表所需的数据量。我不记得确切的结果,但假设我的计算是正确的,它的顺序是“适度堆叠多-TB 磁盘”。在我看来,这将其置于“有组织的犯罪分子可以做到”的范围内。)


dav*_*085 5

与普通散列不同,密码散列应该使用“盐”并且应该很慢(通常通过迭代)以防止获得散列的攻击者轻松恢复密码。请参阅security.SX 上的规范以及与之相关的许多内容。

最初的20世纪70年代的crypt(3) ,现在叫DEScrypt为了清楚起见,(轻轻)盐渍

salt是从 [a-zA-Z0-9./] 集合中选择的两个字符的字符串。该字符串用于以 4096 种不同方式之一扰乱算法。

稍新的 MD5crypt 方案经过加盐和迭代,但不符合现代标准。https://en.wikipedia.org/wiki/Crypt_%28C%29中详细介绍了这两种方案以及在 Unix 上取代它们的一些更好的方案。