編按:本文綜合整理自 GitButler Blog、Hacker News 討論串,並加入 Siami 編輯部觀點與分析。
故事從哪裡開始?
這個議題我觀察了好幾年,一直沒寫下來,主要是因為有更聰明的人正在專注處理這件事,我並不喜歡當個後座駕駛。不過,我覺得 Git 3.0 即將到來的釋出,將會浪費大家大量時間與精力,卻只換來微乎其微的效益,而且幾乎沒有人意識到接下來會發生什麼事。
所以泡杯茶,讓我來講一個關於 Git 3.0 即將到來的某個破壞性變更,如何變成一場昂貴的全球級災難、卻幾乎沒有實際價值。
SHA-1 在 Git 的角色
我盡量講簡短,因為很多人對這部分的基本概念應該都不陌生。
Git 是一種「內容可定址資料庫」(content addressable database)。這代表如果你想在其中儲存與傳遞資料,Git 會計算內容的雜湊值,並把這個值當作 key/value 資料庫裡的 key(value 則是內容本身)。同樣的內容,在全球任何地方都會得到同一個雜湊值。
這個設計很棒,因為它代表同樣的檔案內容永遠不會被儲存兩次。還有一個很酷的特性:每個 commit 都會編碼前一顆 commit 的雜湊值,這代表這個完整性會「傳遞下去」——你要改任何一個東西的雜湊值,就必須連帶改掉所有後續東西的雜湊值。這讓它具備「密碼學完整性」(critical integrity),意思是雜湊最新的 commit,本質上也等於雜湊了它前面可能數百萬個檔案內容、tree 物件與 commit。
在 Git 中,這個雜湊函式一直都是 SHA-1。這是 Linus 在 2005 年 Git 誕生時所選定的,這 20 年來表現得相當不錯——它的計算速度很快,而且在實務上兩個不同的檔案幾乎不可能意外雜湊到同一個值。
事實上,就我所知,在整個 Git 歷史上每一個被建立的檔案、tree 物件與 commit,從來沒有發生過一次碰撞事件——這可是幾十億個物件的規模。
從數學上來看,對於 SHA-1 的 160 位元輸出,生日攻擊下界代表你需要大約 1.4 個 septillion(一千四百萬兆兆,1,400,000,000,000,000,000,000,000)個隨機檔案,集中在同一個專案裡,才有可能讓雜湊值意外碰撞。
SHA-1 真的「壞了」嗎?
不過這裡有個問題:在數學上,SHA-1 現在被認為是半「壞掉」的,因為已經有發表過的碰撞攻擊(2017 年的 SHAttered、2020 年的 SHA-1 is a Shambles)——雖然在實務上沒有人展示出能真正利用的方式,但理論上已經成為可能。
因此,在一群非常聰明的人做了大量工作之後,即將到來的 Git 3.0 釋出,預計要把預設雜湊演算法從半「壞掉」的 SHA-1 換成更強的 SHA-256。
但首先,先暫停一下。在深入討論之前,「壞掉」到底是什麼意思?
這一點很重要,因為它可能跟一般人所想的「壞掉」不一樣。從密碼學雜湊的角度來看,這種意義下的「壞掉」基本上代表「找出碰撞並不是不可能」。
換句話說,如果你投入足夠的金錢與 GPU,還是有可能針對某些內容形狀,人為製造出兩個不同內容卻雜湊到相同值的東西。
這代表理論上存在這樣的攻擊路徑:有人可以用惡意版本替換掉某一筆檔案內容,而因為雜湊值一模一樣,Git 無法分辨出差異。
那些論文顯示,SHA-1 有一個特性,理論上能被現代 GPU 農場以數萬美元的成本利用來製造有意的碰撞,而 SHA-256 沒有這個特性(如果你真的非常想深究,可以 google「linear message schedule sha-1 vs sha-256」)。
聽起來很可怕對吧?是不是要為孩子們想想!?
碰撞攻擊的真相
其實沒那麼嚴重。
但先花一分鐘退一步,談談這些碰撞。
當你在考慮針對雜湊函式的攻擊時,主要有兩種問題(先讓我大幅簡化)。一種是「碰撞攻擊」,另一種是「第二原像攻擊」。
「碰撞攻擊」是指你知道自己將會是攻擊者,但先假裝是好人直到取得信任。你人為製造兩個雜湊值相同的檔案——一個良性、一個惡意。你先用良性的那個,等取得信任後再換成惡意的,因為雜湊值相同,你確定 Git 分不出來。你甚至可以對含有良性檔案的物件建立已簽署的 tag 或 commit,讓它看起來像是惡意檔案被簽署過。
「第二原像攻擊」是指你看到一個想要替換的檔案,然後製造出第二個會做壞事的檔案,而且剛好雜湊值也跟原檔一樣,讓人在不知情的狀況下拉下來。重點是,這不代表原始檔案的作者也必須是攻擊者。
為什麼 SHA-1 在實務上其實夠安全?
在我開始抱怨之前,我想強調最重要的一點:雖然第二原像攻擊聽起來更令人擔憂,但幾乎沒有任何廣泛使用的雜湊函式真的會被這種攻擊影響。
Git 即使改用 MD5(被認為是非常「壞掉」的雜湊函式),在實務上也幾乎對第二原像攻擊免疫。再強調一次,MD5 被視為完全「壞掉」的雜湊函式,而 SHA-1 並不是——它強得多。
我說的「實務上免疫」是什麼意思?如果地球上大約 30 億個 GPU 全部神奇地變成 RTX 5090,而且每一個都 100% 全力只跑 MD5,要暴力破解出特定原像的期望時間仍然大約是 160 億年(中位數約 110 億年),差不多是宇宙的年齡。
數字計算:3.4 × 10³⁸ 檢查次數 ÷ (3 × 10⁹ 顆 GPU × 2.2 × 10¹¹ hashes/sec) ≈ 5.2 × 10¹⁷ 秒 ≈ 160 億年
連上 Google 2024 年公佈的結果都只有後面超過 16 billion years(足以),這還是拿 RTX 5090 全速運算的數字。
為什麼這件事重要
這篇文章出自 GitHub 共同創辦人 Scott Chacon(現在是 GitButler CEO)之手,他對 Git 的內部運作理解比大多數人都深。他的核心論點很明確:Git 3.0 把預設雜湊從 SHA-1 換成 SHA-256,會為了根本不會發生的威脅,付出巨大的全球相容性代價。
幾個關鍵事實值得注意:
- 碰撞攻擊 ≠ 第二原像攻擊:密碼學界對「壞掉」的定義,跟一般工程師腦中的「壞掉」完全不同。SHA-1 即使在數學上被證明可碰撞,在實務上要製造針對性惡意檔案的成本仍然高達數萬到數十萬美元,而且只能針對特定內容形狀。
- SHA-1 在 Git 20 年歷史中從未真的發生過碰撞:這是一個橫跨幾十億個 commit 的事實樣本。現實世界的 Git 工作流根本沒碰過這個問題。
- 破壞的後向相容性是巨大的:任何在內部把 SHA-1 當作 commit identifier 的服務(CI 系統、套件管理器、Git hosting 平台、簽章工具鏈)都會被迫進入雙重解析模式,這對小團隊與開源維護者是不必要的維運負擔。
數據解讀與質疑
Scott Chacon 在文章中給出的暴力破解數字其實非常關鍵:
- 3.4 × 10³⁸ 次檢查 ÷ 30 億顆 RTX 5090 × 2.2 × 10¹¹ hashes/sec ≈ 5.2 × 10¹⁷ 秒 ≈ 160 億年
- 這個數字針對的是 MD5(比 SHA-1 弱得多),而且假設全人類的 GPU 算力都拿來攻擊一個雜湊值
- 即使假設可行,第二原像攻擊的成本在現實中也遠超任何攻擊者能承受的範圍
換言之,把 Git 3.0 換成 SHA-256 的「安全收益」,在可預見的未來都是零;相對的,全球 Git 生態要付出的相容性成本,卻是實實在在的巨大。這正是 Scott 認為這是「costly mistake」的核心論據。
值得質疑的是,雖然 SHA-1 在 Git 的內部使用場景(內容定址)實務上幾乎不可能被攻破,但在外部場景(例如 Git commit hash 被當作套件版本號、CI 快取 key、第三方服務的 identifier)時,這些下游消費者被迫升級的成本,遠比 Git 內部核心演算法升級的效益要來得實質。
社群對於這個議題的態度分歧明顯。技術核心派認為 Git 應該走在前面,預先因應未來的密碼學威脅;而實務派則認為,只要 SHA-1 在 Git 的真實使用場景中沒出過事,就不應該為了理論風險而強迫整個生態轉換。Hacker News 上 264 則討論中,後者的聲音明顯佔上風。
📌 Siami 觀點:GitButler CEO Scott Chacon 公開質疑自家(Git 社群)將推出的破壞性變更,是非常勇敢的舉動。這正是開源精神的核心——即使是社群核心人物,也能對技術路線提出公開質疑,而不必擔心政治風險。建議開發者關注 Git 3.0 釋出時程,預先評估自家基礎設施的相容性影響。
網友熱門留言 (3)