根据crypt() 文档,盐需要是字母表“./0-9A-Za-z”中的 22 个基数为 64 位的数字。
这是他们给出的代码示例:
crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$');
第一个令人困惑的部分是 salt 有 25 个字符,而不是 22 个。
问题 #1:这是否意味着盐应该超过22 个字符?
然后我自己测试了这个功能并注意到了一些东西。如果我使用 20 个字符的盐,我会得到这个
// using 20 char salt: 00000000001111111111
crypt('rasmuslerdorf', '$2a$07$00000000001111111111$');
// $2a$07$00000000001111111111$.6Th1f3O1SYpWaEUfdz7ieidkQOkGKh2
因此,当我使用 20 个字符的盐时,整个盐都在输出中。这很方便,因为那时我不必将盐存放在单独的地方。(我想使用随机盐)。我将能够从生成的哈希中读取盐。
但是,如果我按照文档所述使用 22 个字符的盐,或者使用更长的盐,盐会在最后被切断。
// using 22 char salt: 0000000000111111111122
crypt('rasmuslerdorf', '$2a$07$0000000000111111111122$');
// $2a$07$000000000011111111112uRTfyYkWmPPMWDRM/cUAlulrBkhVGlui
// 22nd character of the salt is gone
// using 25 char salt: 0000000000111111111122222
crypt('rasmuslerdorf', '$2a$07$0000000000111111111122222$');
// $2a$07$000000000011111111112uRTfyYkWmPPMWDRM/cUAlulrBkhVGlui
// Same hash was generated as before, 21 chars of the salt are in the hash
问题 #2:那么,盐的正确长度到底是多少?20?22? 更长?
问题 #3:另外,在检查密码时从哈希中读取盐值是否是个好主意?而不是将盐存储在一个单独的字段中并从那里读取它。(这似乎是多余的,因为盐似乎包含在哈希中)。