SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

Linux 下載檔案 checksum 驗證教學

使用 sha256sum 計算檔案雜湊,對照 SHA256SUMS 檢查下載內容,再修改 1 個位元組,觀察檢查失敗與 checksum 能證明的範圍。

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 12, 2026.

在 2 分鐘內使用 checksum 驗證下載內容

若要使用 checksum 驗證下載內容,請先對收到的檔案計算雜湊,再讓工具將該雜湊與發布者列出的值進行比對。sha256sum 可完成這兩個步驟:單獨執行時會輸出摘要,搭配 -c 時則會讀取摘要清單,並回報哪些檔案相符。本指南會在自行建立的檔案上執行完整流程,接著故意修改該檔案,讓你實際觀察驗證失敗,而不是只閱讀相關說明。

請全程記住一句話。Checksum 只能告訴你目前持有的位元組,是否就是產生該摘要的位元組;它無法告訴你這些位元組是由誰產生的。第二個問題需要簽章,以及你信任的金鑰。本指南最後會明確說明兩者的界線。

建立練習用檔案

請在暫存目錄中操作,避免這裡的任何內容影響系統其他部分。以下每個命令都來自 GNU coreutils。這是所有 Ubuntu 或 Debian 伺服器都具備的基本命令集,因此不需要安裝任何套件。

mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txt

您會看到一行輸出:64 個十六進位字元、兩個空格,接著是檔案名稱。這 64 個字元就是檔案的摘要值。再次執行相同命令時,輸出內容會完全一致,因為雜湊運算具有確定性:相同輸入永遠產生相同輸出。修改檔案中的一個字元後再次執行,摘要值不會只略微變化,而是會看起來完全不同,因為輸入的一個位元翻轉時,輸出約有一半的位元也會翻轉。這項特性讓 64 個字元的字串可以作為 4 GB 映像檔的可用代表值。

儲存 SHA256SUMS 檔案,然後進行檢查

只顯示在畫面上的摘要,隔天就沒有用處。請將摘要寫入檔案,並使用 sha256sum 本身寫入的格式,讓工具之後能讀回檔案。

sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMS

sha256sum -c 會逐行讀取清單,計算該行所指定檔案的雜湊值,並比對兩個摘要。檔案全部正常時,每個檔案會輸出一行:

payload.txt: OK

也要檢查結束狀態,因為指令碼會讀取該狀態,而不會讀取文字輸出。正常執行後,echo $? 會輸出 0。SHA256SUMS 這個名稱是慣例,不是硬性規定;但各發行版與大多數版本發布頁面都會使用這個名稱。因此也請採用它,讓下一位使用者不必開啟檔案,就知道檔案的內容。

翻轉 1 個位元組並觀察檢查失敗

現在刻意破壞檔案。此操作會寫入單一位元組至偏移量 5,其他內容保持不變,因此檔案的長度與名稱都會保留。

printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMS

conv=notrunc 是關鍵旗標。若省略此旗標,dd 會在停止寫入的位置截斷檔案,屆時測試的是更明顯的損壞類型。此時檢查會輸出:

payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

echo $? 會輸出 1。FAILED 表示檔案已讀取,但其摘要與清單中的摘要不一致。還原原始位元組,並確認檢查結果恢復為 OK:

printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMS

這就是完整的操作習慣。檔案中的任何位置只要有 1 個位元組不同,就會產生 FAILED。連線中斷導致下載不完整、鏡像站提供前一天的建置版本、代理伺服器在傳輸過程中改寫檔案,或磁碟回傳錯誤區塊,最後都會顯示在同一行。

清單列出你未下載的檔案

實際的發行版 SHA256SUMS 檔案會列出專案發布的每個映像檔,而你只下載了其中一個。請在此重現這種情況。

printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.all
payload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

FAILED open or read 與 FAILED 是不同的失敗狀況,混淆兩者只會浪費時間。FAILED 表示檔案內容的位元組不正確。FAILED open or read 表示 sha256sum 根本找不到該檔案,因此沒有進行比對。在實際下載中,常見原因是目前工作目錄不正確,因為清單中的檔名是相對於執行命令時所在目錄的路徑。切換到存放該檔案的目錄後,再次執行命令。若只要檢查目前實際擁有的檔案,請指定該檔案:

sha256sum --ignore-missing -c SHA256SUMS.all

命令會輸出 payload.txt: OK,並以 0 結束。如果清單中的檔名一個都不存在,--ignore-missing 不會在零個檔案的情況下靜默成功。它會回報 no file was verified,並以非零狀態結束。這正是所需的行為,因為檢查了零個檔案卻顯示通過,才是最容易被忽略的失敗。

不直接目視閱讀已發布的摘要

逐一目視比對 64 個十六進位字元,正是這種習慣最容易出問題的地方。人們會檢查開頭 4 個字元和結尾 4 個字元,然後就認定兩者相符;而這正是有意攻擊者預期你採用的比對方式。讓工具代為比對。將你從發布者處複製的摘要設為 EXPECTED,使用 EXPECTED= 後接貼上的值,然後建立 -c 所要求的單行內容:

printf '%s  %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256

摘要與檔案名稱之間有 2 個空格,因此格式字串也包含 2 個空格。這就是 sha256sum 寫入的格式,也是 -c 解析的格式。只包含摘要而沒有其他內容的檔案,根本不是 checksum 行,因此檢查會以 no properly formatted checksum lines found 拒絕整個檔案,而不是猜測你指的是哪個檔案。有些專案改用 BSD 標記格式發布,格式為 SHA256 (payload.txt) = 後接摘要。GNU coreutils 會以 sha256sum --tag payload.txt 寫入這種格式,並以 -c 讀回,因此儲存任一格式皆可。

檢查行為異常時,使用 cat -A SHA256SUMS 檢視清單本身。它會以 $ 標示每一行的結尾,並顯示平時看不到的字元。以 ^M$ 結尾的行,表示從 Windows 編輯器帶入了 carriage return。GNU sha256sum 會忽略該行尾字元,仍輸出 OK,因此 CRLF 清單不是造成檢查失敗的原因;不過 coreutils 以外的工具對此通常較不寬容。使用 tr -d '\r' < SHA256SUMS > SHA256SUMS.clean 將要保留的複本正規化。

Checksum 能證明什麼,又不能證明什麼?

Checksum 只能證明一件事:磁碟上的位元組,就是產生已發布摘要的那些位元組。這能完整涵蓋意外損壞的情況。若攻擊者只能替換下載鏡像上的檔案,卻無法修改發布摘要的頁面,也能偵測出這類粗心的攻擊。

Checksum 無法證明檔案的作者或來源。摘要描述的是位元組,不是人員。如果同一個頁面同時提供檔案與摘要,那麼能修改其中一項的人也能修改另一項;此時你的 OK 行只能表示鏡像與自身內容一致。因此,執行 checksum 的關鍵規則是:從不同於檔案來源的位置取得摘要。例如,映像檔來自鏡像或 torrent,但摘要取自專案自己的 TLS(transport layer security)網域。如此一來,攻擊者就必須同時控制兩個位置,而不是一個位置。Checksum 也無法說明通過驗證的位元組在執行後會做什麼。對任何代表你執行程式的內容,都應另外提出這個問題,從安裝指令碼到以代理程式權限執行的 dsh 外掛程式皆然。

演算法也很重要。截至 2026 年 8 月,SHA-256(secure hash algorithm,256 位元輸出)尚無已知碰撞,因此發布者會使用它。MD5(message digest 5)與 SHA-1 則不可靠:自 2004 年起,就能建構出具有相同 MD5 摘要的不同檔案;2020 年也發布了 chosen-prefix SHA-1 碰撞。即使是 MD5SUMS 檔案,仍可偵測下載不完整的情況,因為隨機損壞不是刻意製造的碰撞。但它無法阻止試圖欺騙你的人。如果專案同時發布兩者,請使用 SHA-256 那一行。

簽章接手驗證工作

簽章能補上摘要留下的缺口。發布者使用私鑰簽署摘要檔案,而你使用其公鑰進行驗證:gpg --verify SHA256SUMS.asc SHA256SUMS。如果驗證通過,表示這份摘要清單確實來自持有該金鑰的人。接著,sha256sum -c SHA256SUMS會將磁碟上的檔案與清單對應起來,整條信任鏈便從金鑰一路延伸到檔案內容。

弱點會轉移到金鑰本身。如果從提供檔案的同一個頁面取得金鑰,攻擊者就能同時替換兩者。GnuPG 會明確指出這一點;首次驗證時,會輸出 Good signature 以及 WARNING: This key is not certified with a trusted signature!。Good signature表示數學驗證成立,但不表示該金鑰屬於你認定的專案。請從第二個來源取得指紋,例如專案在不同網域上的文件,或已經隨附該金鑰的發行版套件,並比對完整指紋,不要只比對最後八個字元。這與SSH 私鑰同樣需要謹慎處理,原因也相同:金鑰決定信任對象,而後續所有內容都會繼承這項信任。

可重現建置將這個概念再向前推進一步。已發布的摘要仍會讓你依賴某台機器建置出的二進位檔。當專案的建置流程具備可重現性時,任何人都能從相同原始碼編譯出位元組完全相同的輸出,因此不同的建置者可以確認已發布的摘要,而不必要求你相信單一伺服器的結果。隨著越來越多程式碼透過自動化管線和機器撰寫的修補程式產生,這一點每年都更加重要。決定哪些內容可以納入建置是政策問題,而AI 輔助程式碼的開放原始碼政策也是從供應鏈的另一端處理相同問題。

套件管理器已替你完成這些工作

在 Debian 和 Ubuntu 上,apt 每次安裝套件時都會自動執行這條驗證鏈。套件索引會記錄每個 .deb 檔案的 SHA-256 摘要。Release 檔案會記錄這些索引檔的摘要,而 InRelease 會攜帶涵蓋 Release 的簽章,並使用 /usr/share/keyrings 和 /etc/apt/trusted.gpg.d 中的金鑰進行驗證。驗證鏈中斷時,apt 會明確指出原因:第三方套件庫缺少金鑰時顯示 The following signatures couldn't be verified because the public key is not available: NO_PUBKEY;抓取的索引與已簽署的 Release 不一致時顯示 Hash Sum mismatch。後者通常表示快取代理伺服器提供了過期檔案,或你在鏡像站同步期間取得了檔案。

當專案首頁要求你將 curl 的指令碼直接管線傳給 shell 時,應以這套標準進行比較。這樣不會驗證內容,你也不會看到指令碼內容。伺服器還可能對指令碼回傳一種內容,對瀏覽器回傳另一種內容,而你事後沒有副本可供檢查。使用 curl -fsSL <url> -o install.sh 將檔案下載到本機,計算其雜湊,使用 less 讀取內容,最後才執行。這個習慣大約只需 20 秒;在伺服器上安裝任何其他軟體前,也應在全新的 VPS 啟用後前 10 分鐘內開始這麼做。

保留手動安裝項目的摘要清單

apt 安裝的套件會被追蹤。您手動複製到 /usr/local/bin 的二進位檔不會被追蹤,系統也不會監控它。摘要清單可讓您隨時檢查這些檔案:

printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256

所有檔案都相符時,--quiet 不會輸出任何內容。若有檔案不相符,則只會輸出檢查失敗的行。因此,沒有輸出表示檢查通過,而 echo $? 會以 0 確認結果。這種形式適合放入排程工作。--status 更進一步,完全不輸出內容,只留下結束狀態。使用 sha256sum /usr/local/bin/* > ~/local-bin.sha256 將相同模式套用至實際檔案,即可建立基準。路徑會依您輸入的形式原樣儲存在清單中,因此使用絕對路徑可讓您從任何目錄執行檢查。

請明確了解這份基準的用途。它可以偵測檔案是否變更,但無法偵測已取得 root 權限的攻擊者,因為該攻擊者同樣能輕易改寫 inventory.sha256 與二進位檔。若希望這份清單具有實際意義,請將它保存在該機器之外。這也是更廣泛問題的一部分:您實際上信任 VPS 的程度,以及其他人是否能存取其底層磁碟。

FAQ

相符的 checksum 是否表示下載內容安全?

不是。這表示你取得的位元組,與拿來比對的 digest 相符。如果攻擊者控制發布 digest 的頁面,對方可以發布自己檔案的 digest,而你的檢查結果會顯示 OK。相符只能證明內容一致。要證明安全,必須使用從其他來源取得的 key 驗證 signature,之後 digest 才能繼承這份信任。

為什麼 sha256sum -c 會顯示 FAILED open or read?

因為它根本沒有讀取檔案。就在它上方的另一行會顯示 No such file or directory,其中包含它尋找的檔名。SHA256SUMS 檔案中的檔名,是相對於執行命令所在目錄的路徑。因此,請切換到存放下載檔案的目錄後重新執行。如果清單中也列出你未下載的檔案,請加入 --ignore-missing。沒有 open or read 的單純 FAILED 則表示情況相反:檔案已讀取,但其 digest 不相符。

MD5 是否足以驗證下載內容?

若要檢查意外損毀,可以。傳輸內容遭截斷或磁碟區塊損壞,不會意外產生相符的 MD5 digest。但若要防範攻擊者,則不夠。自 2004 年起,就能建構出具有相同 MD5 digest 的不同檔案;2020 年則出現了 chosen-prefix collision,使 SHA-1 失效。專案同時發布 SHA-256 與 MD5 時,請使用 SHA-256;如果專案只提供 MD5,應將其視為舊式發行流程的跡象。

sha256sum -c 與 gpg --verify 有何差異?

sha256sum -c 可證明檔案與某個 digest 相符。gpg --verify 可證明 digest 檔案由特定 private key 的持有者簽署。兩者回答的是不同問題,因此專案同時提供兩者時,請一併執行。signature 使 digest 清單具備可信度,而 digest 清單再使下載的檔案具備可信度。

如何將單一檔案與網頁上列出的 digest 比對?

不要用肉眼比對字元。將 digest 與檔名存成同一行,中間以兩個空格分隔,然後對該檔案執行 sha256sum -c,並查看它輸出的 OK 或 FAILED。使用 printf '%s %s\n' 建立該行,可避免格式錯誤,否則 sha256sum 會以 no properly formatted checksum lines found 拒絕該檔案。

#checksums#sha256sum#integrity#supply-chain#security