获取 SHA1 的不同方法会给出不同的结果

获取 SHA1 的不同方法会给出不同的结果

我正在学习 SHA1(特别是 Git),我想通过使用不同的方法计算字符串的 SHA1 来检查我的理解 - 我期望相同的 SHA1 哈希值,但相反,我从四种方法中的三种得到了不同的结果:

>git hash-object --stdin <<< "Apple Pie"
23991897e13e47ed0adb91a0082c31c82fe0cbe5

>sha1sum <<< "blob 9\0Apple Pie"
332cd56150dc8b954c0b859bd4aa6092beafa00f  -

>printf 'blob 9\0Apple Pie' > foo.txt
>sha1sum foo.txt
9eed377bbdeb4aa5d14f8df9cd50fed042f41023  foo.txt

>openssl sha1 foo.txt
SHA1(foo.txt)= 9eed377bbdeb4aa5d14f8df9cd50fed042f41023

接受的答案这个堆栈溢出问题表示git hash-object对前缀为“blob [文件大小]/0”的指定内容运行 SHA1 哈希。因此,我明确地将该文本添加到我使用非 git 方法测试的字符串的前缀。

为什么会有这些不同的结果?我认为 SHA1 是给定字符串的特定且唯一的哈希值,并且 SHA1 没有不同的“类型” - 这不是真的吗?

答案1

差异并非来自 SHA1,而是来自输入。 Here-string 语法附加一个换行符,正如我们可以看到的od

$ od -c <<< foo
0000000   f   o   o  \n

所以在你的git命令中输入的是十个字符Apple Pie\n

此外,您在此处字符串中使用的双引号不支持反斜杠转义,例如\nor \nnn,因此<<< "blob 9\0Apple Pie"给出一个包含文字反斜杠和零的字符串。

printf然而它确实解释\0为 NUL 字节,并且它不添加尾随换行符,因此添加换行符并固定长度后,我们应该得到预期的输出:

$ printf 'blob 10\0Apple Pie\n' | sha1sum
23991897e13e47ed0adb91a0082c31c82fe0cbe5  -

我们可以尝试使用引号对此处字符串执行相同的操作,$''该引号确实支持\0表示 NUL 字节,但这可能不适用于所有 shell,因为 NUL 字节结束字符串。例如 Bash 无法处理它,zsh可以:

$ zsh -c "sha1sum <<< $'blob 10\0Apple Pie'"
23991897e13e47ed0adb91a0082c31c82fe0cbe5  -

相关内容