Git

獲取 SHA1 的不同方法給出不同的結果

  • May 15, 2017

我正在學習 SHA1(特別是 wrt 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

這個 Stack Overflow 問題的公認答案是在指定內容上git hash-object執行 SHA1 雜湊,前綴為“blob

$$ file size $$/0"。因此,我將該文本顯式添加到我使用非 git 方法測試的字元串的前綴。 為什麼所有這些不同的結果?我認為 SHA1 是給定字元串的特定且唯一的雜湊,並且 SHA1 沒有不同的“類型”——這不是真的嗎?

差異不是來自 SHA1,而是來自輸入。這裡的字元串語法附加了一個換行符,我們可以看到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  -

我們可以嘗試使用$''支持表示 NUL 字節的引號對 here-string 執行相同的\0操作,但這可能不適用於所有 shell,因為 NUL 字節結束了字元串。例如 Bash 無法處理它,zsh可以:

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

引用自:https://unix.stackexchange.com/questions/365041