在使用 SHA-256 和 SHA-512的 Unix crypt 中,作者 Ulrich Drepper 介绍了SALT 字符串如下(由我强调):
对于基于 SHA 的方法,SALT 字符串可以是最多使用 16 个字符的简单字符串。
将此字符串称为简单字符串的理由是什么?这是什么意思?后果是什么?例如,我对提供 16 个 NUL 字节字符串的边缘情况特别感兴趣。
在使用 SHA-256 和 SHA-512的 Unix crypt 中,作者 Ulrich Drepper 介绍了SALT 字符串如下(由我强调):
对于基于 SHA 的方法,SALT 字符串可以是最多使用 16 个字符的简单字符串。
将此字符串称为简单字符串的理由是什么?这是什么意思?后果是什么?例如,我对提供 16 个 NUL 字节字符串的边缘情况特别感兴趣。
该文本的意思是“简单”,与旧的基于 DES 的旧传统 DEScrypt()
中使用的相反,其中 salt 是 12 位值,表示为受限集中的两个字符。Ulrich Drepper 想说他的创作不那么挑剔,可以将最多 16 个字节的任何序列作为盐。
尽管散列函数本身可以处理任何字节(包括零,这对于散列函数而言并不特殊),但您链接到的文本中显示的 C 代码使用基于字符串的 API:
char *
sha256_crypt (const char *key, const char *salt)
即盐将在第一个零值字节之前停止,或在第 16 个字节之后停止,以先到者为准。此外,salt 的值将是生成的输出字符串的一部分,因此 salt 最好包含可打印的 ASCII 字符并且不包括'$'
符号,因为这是在该字符串中用作分隔符的内容。
为该函数生成“正确的盐字符串”的一种简单方法是生成恰好 12 个随机字节的序列(取自良好的 PRNG,即/dev/urandom
),并使用Base64对它们进行编码。这将产生 16 个随机字符,在一个包含字母(大写和小写)、数字'+'
和'/'
-- 的字母表中,仅此而已,特别是没有'$'
和没有麻烦的控制字符。盐仍然有 96 位熵,使得盐重用相当不可能(所以一切都会好起来的)。
在这种情况下,一个简单的字符串是 C 中的任何字符数组,例如:char[]
. 该代码正在执行 strlen() ,因此它以空值终止。盐应该是加密随机数。