Git
獲取 SHA1 的不同方法給出不同的結果
我正在學習 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
。此外,您在此處字元串中使用的雙引號不支持反斜杠轉義,例如
\n
or\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 -