SHA-256 的 Length extension attack

Hacker News 上看到「Breaking SHA256: length extension attacks in practice (kerkour.com)」,在講不當使用 SHA-256 會導致 Length extension attack 類的安全漏洞,主要是因為 MD5SHA-1 以及 SHA-2 類的 hash function 最後生出 hash 值時會暴露出 hash function 的內部狀態而導致的問題。

這邊講的不當使用是指你沒有使用標準的 MAC,而是自己用字串組合實作造成的問題,通常是 S = H(secret || message) 這樣的形式,這邊的 || 是指字串相接。

拿 MD5 為例子,在維基百科上面可以看到 MD5 演算法對應的 pseudo code,最後輸出的部分可以看到是把 a0a1a2a3 這四個 32-bit variable 接起來,也就是把內部的狀態丟出來了:

// Process the message in successive 512-bit chunks:
for each 512-bit chunk of padded message do
    // ...

    // Add this chunk's hash to result so far:
    a0 := a0 + A
    b0 := b0 + B
    c0 := c0 + C
    d0 := d0 + D
end for

var char digest[16] := a0 append b0 append c0 append d0 // (Output is in little-endian)

於是你在可以反推 padding 的結構之後 (會需要知道 secret 的長度),就可以往後接東西繼續算下去,這就是被稱作 length extension attack。

本來只有 S = H(secret || message),你在不知道 secret 的情況下就可以疊字串到後面而且算出對應的 hash 值,變成 S' = H(secret || message || evildata)

維基百科給的例子也示範了怎麼「用」,這是原始的資料以及 server 端簽出來的 hash 值:

Original Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo
Original Signature: 6d5f807e23db210bc254a28be2d6759a0f5f5d99

於是我們想要蓋 waffle 參數,就變成:

Desired New Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo&waffle=liege

攻擊者則可以不斷的嘗試,去猜測 padding 的結構,把計算出來對應的 hash 值丟到 server 看反應,直到看到 200 OK 的回應:

New Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x28&waffle=liege
New Signature: 0e41270260895979317fff3898ab85668953aaa2

如同前面提到的,這是 hash function 在最後把內部狀態直接暴露出來造成的問題,在 MD5、SHA-1、SHA-2 (SHA-256、SHA-384、SHA-512) 都有類似的問題,而比較新的 hash function 在設計時就已經有考慮到了,不會出現這個問題,像是 SHA-3

另外一方面,不要自己發明演算法,使用標準的 MAC 演算法通常是比較好的選擇。這邊用的比較廣泛的應該就是 HMAC,超過 25 年了。

結論是 SHA-256 還是堪用,儘量拿現成的演算法套,不要自己搞。

Git 在 SHA-256 支援上遇到的問題

在 Hacker News 首頁上的「Whatever happened to SHA-256 support in Git?」這篇,大概半年前,今年六月的文章,在講 GitSHA-256 支援上遇到的問題。

最大的問題還是沒有 transition plan:

Bjarmason pointed out that there is still no interoperability between SHA-1 and SHA-256 repositories, and that none of the Git hosting providers appear to be supporting SHA-256.

這點導致了目前場上看的到的服務與 open source 軟體都沒有支援的計畫,這點算是一個超級失敗的 transition plan。

另外乾脆請 OpenAIChatGPT 幫忙寫:

Git是一種源代碼管理系統,它使用散列函數將每個對象(例如文件的每個版本)和每個提交都轉換為一個數值,用於存儲該對象。散列函數的安全性是整個倉庫完整性的重要組成部分。如果攻擊者可以用具有相同散列值的另一個提交替換提交,他們可能會在不冒檢測風險的情況下將惡意代碼植入倉庫中。這種前景令任何依賴 Git 倉庫中代碼安全性的人感到擔心,也就是所有人。

Git 項目早已選擇 SHA-256 作為 SHA-1 的替代品。Git 最初是使用 SHA-1 寫成的,但是這些代碼已被重構,並且可以處理多種散列類型,其中 SHA-256 是第二種支持的類型。現在可以使用 SHA-256 創建 Git 倉庫(只需使用 --object-format=sha256 標誌),大多數本地操作都會正常工作。Git 中支持替代散列算法的基礎是2020年發布的2.29版本的一部分,並且似乎很穩定。

然而,自從2021年3月發布的2.31版本中出現了修復程序以來,2.29版本是最後一個在任何重大方面支持替代散列的版本。專

續寫前文,Git 專案在支持 SHA-256 之前一直使用 SHA-1 作為散列算法。然而,由於 SHA-1 的終極破解,Git 項目被迫尋找替代方案。Git 原本的代碼是深深地嵌入 SHA-1 的,但是這些代碼已經被重構,並且可以處理多種散列類型,其中 SHA-256 是第二種支持的類型。因此,現在可以使用 SHA-256 創建 Git 倉庫(只需使用 --object-format=sha256 標誌),大多數本地操作都會正常工作。

然而,目前尚不存在 SHA-1 和 SHA-256 倉庫之間的相互操作性,並且 Git 托管提供商似乎都不支持 SHA-256。這種支持(或缺乏支持)很重要,因為無法推送到 Git 熔爐的倉庫對許多人來說將是無用的。此外,使用 SHA-256 的較長散列可能會破壞 Git 項目以外開發的工具,這種風險也無法完全消除。整體而言,這是一種尚未準備好用於現實世界的功能。

雖然如此,值得注意的是,迄今為止完成大部分散列轉換工作的 brian m. carlson 對 Bjarmason 的評估持不同看法。在他看來,目前唯一“可以辯解

的”使用 SHA-1 的原因是與 Git 熔爐提供商的相互操作性。否則,他認為 SHA-1 已經過時,並且使用 SHA-256 的性能可能“大幅提升”。但是,他同意所需的相互操作性目前尚不存在,且沒有人表示它即將在短期內到來。

因此,目前看來,Git 專案在支持 SHA-256 方面的工作似乎已經停止。至於什麼原因導致了這種情況,目前還不清楚。但是,這並不意味著 Git 將永遠不會支持 SHA-256 或其他散列算法。相反,可能是因為尚未解決所有技術問題,或者可能是因為其他原因(例如技術資源有限)。無論原因是什麼,重要的是要記住,Git 項目的開發人員一直在努力使其更強大、更安全,並且將繼續努力。

Amazon S3 支援 MD5 以外的檢查演算法了

Amazon S3 宣佈支援 MD5 以外的檢查演算法了:「New – Additional Checksum Algorithms for Amazon S3」。

多支援了 SHA-1SHA-256 以及 CRC-32CRC-32C

In particular, you can specify the use of any one of four widely used checksum algorithms (SHA-1, SHA-256, CRC-32, and CRC-32C) when you upload each of your objects to S3.

雖然有拿 cryptographic hash function 來用,但其實是當作 checksum algorithm 在用,拿來檢查檔案正確性的,而不是防中間被竄改之類 (這個部份是靠 HTTPS),本來支援的 MD5 應該算是夠用,只是現在多了不少選擇。

然後全商用區都可以用了:

The four additional checksums are now available in all commercial AWS Regions and you can start using them today at no extra charge.

libtorrent 宣佈支援 BitTorrent v2

看到 libtorrent 宣佈支援 BitTorrent v2 (BEP 52) 的消息:「BitTorrent v2」。

BitTorrent v2 這個規格丟出來好久了,但一直都是 draft,而且沒什麼人想要理他,直到 Google 成功產生出 SHA-1 collision 的時候稍微有些音量跑出來,但沒想到居然有人跳下去支援了...

對使用者比較有感覺的差異是從 SHA-1 換成 SHA-2 的 SHA-256 了,這個會影響到整個 torrent file 的結構與 Magnet URI 的部份。

另外一個比較大的改變是 torrent 檔資料結構,有兩個比較大的改變。

第一個是以前用固定的 block size 切割,然後每個 block 產生出 hash,所以 torrent 檔會隨著 block size 選擇的大小 (成反比) 檔案大小 (成正比) 有關,現在會用 Merkle tree,所以只要有 root hash 就可以了。

第二個是以前是把所有檔案包在一起 hash,現在是個別檔案都有自己的 hash (改成 root hash),所以現在變成可以跨 torrent 檔共用檔案。

然後 libtorrent 的文章裡有提到向前相容的方法,不過以產品面上來說沒有什麼太大的誘因,libtorrent 雖然大,但其他幾家的支援度應該也是重點...