Go 部落格

Go 密碼學安全審計

Roland Shoemaker 和 Filippo Valsorda
2025 年 5 月 19 日

Go 的標準庫中包含一套完整的密碼學軟體包,可幫助開發人員構建安全的應用程式。Google 最近委託獨立的安保公司 Trail of Bits 對核心軟體包集進行審計,這些軟體包集也作為 新的原生 FIPS 140-3 模組 的一部分進行了驗證。審計發現了一個低嚴重性問題,出現在傳統且不受支援的 Go+BoringCrypto 整合 中,以及一些資訊性發現。審計報告全文可在此處找到:此處

審計範圍包括我們實現的金鑰交換(ECDH 和後量子 ML-KEM)、數字簽名(ECDSA、RSA 和 Ed25519)、加密(AES-GCM、AES-CBC 和 AES-CTR)、雜湊(SHA-1、SHA-2 和 SHA-3)、金鑰派生(HKDF 和 PBKDF2)和認證(HMAC),以及加密隨機數生成器。低級別的超大整數和橢圓曲線實現,以及其精密的彙編核心,都包含在內。TLS 和 X.509 等更高級別的協議不在此次審計範圍之內。三名 Trail of Bits 工程師參與了為期一個月的審計。

我們為 Go 密碼學軟體包的安全記錄以及此次審計結果感到自豪,這只是我們確保軟體包正確性的眾多方式之一。首先,我們遵循 密碼學原則,積極限制其複雜性,例如優先考慮安全性而非效能。此外,我們採用多種不同技術 對其進行全面測試。我們甚至對內部軟體包也力求利用安全的 API,當然,我們還可以依靠 Go 語言特性來避免記憶體管理問題。最後,我們注重可讀性,以使維護更容易,程式碼審查和審計更有效。

一個低嚴重性發現

唯一可能被利用的問題 TOB-GOCL-3 具有“低嚴重性”,這意味著它影響較小且難以觸發。此問題已在 Go 1.24 中修復。

至關重要的是,TOB-GOCL-3(下文將進一步討論)涉及 舊版 Go+BoringCrypto GOEXPERIMENT 中的記憶體管理,該實驗預設未啟用,且不支援在 Google 之外使用。

五個資訊性發現

其餘發現均為“資訊性”,這意味著它們不構成即時風險,但與安全最佳實踐相關。我們已在當前的 Go 1.25 開發樹中解決了這些問題。

發現 TOB-GOCL-1、TOB-GOCL-2 和 TOB-GOCL-6 涉及各種加密操作中可能的時序側通道。在這三個發現中,只有 TOB-GOCL-2 影響了由於操作秘密值而預期為恆定時間的操作,但它僅影響 Power ISA 目標 (GOARCH ppc64 和 ppc64le)。TOB-GOCL-4 強調了內部 API 中的誤用風險,如果將其重新用於當前用例之外的用途。TOB-GOCL-5 指出了一個實際上無法達到的限制的缺失檢查。

時序側通道

發現 TOB-GOCL-1、TOB-GOCL-2 和 TOB-GOCL-6 涉及輕微的時序側通道。TOB-GOCL-1 和 TOB-GOCL-6 與我們不用於敏感值但將來可能用於此類值的函式有關,而 TOB-GOCL-2 與 Power ISA 上 P-256 ECDSA 的彙編實現有關。

crypto/ecdh,crypto/ecdsa:位元組到欄位元素的轉換不是恆定時間 (TOB-GOCL-1)

NIST 橢圓曲線的內部實現提供了一種在內部和外部表示之間轉換欄位元素的方法,該方法以可變時間操作。

該方法的所有使用都對不被視為秘密的公共輸入(公共 ECDH 值和 ECDSA 公鑰)進行操作,因此我們認為這不是一個安全問題。儘管如此,我們還是決定 將該方法設為恆定時間,以防止將來意外地將此方法與秘密值一起使用,並且我們不必考慮它是否是一個問題。

crypto/ecdsa:P-256 條件取反在 Power ISA 彙編中不是恆定時間 (TOB-GOCL-2, CVE-2025-22866)

除了 一流 Go 平臺 之外,Go 還支援許多其他平臺,包括一些不常見的架構。在審查我們各種底層密碼原語的彙編實現時,Trail of Bits 團隊發現了一個影響 ppc64 和 ppc64le 架構上 ECDSA 實現的問題。

由於在 P-256 點條件取反的實現中使用了條件分支指令,該函式以可變時間而非預期的恆定時間操作。此問題的修復相對簡單,用我們已經在其他地方使用的模式替換了條件分支指令,以恆定時間有條件地選擇正確的結果。我們將此問題指定為 CVE-2025-22866。

為了優先處理覆蓋大多數使用者的程式碼,並且由於針對特定 ISA 需要專業知識,我們通常依靠社群貢獻來維護非一流平臺的彙編。我們感謝 IBM 的合作伙伴為我們的修復提供審查幫助。

crypto/ed25519:Scalar.SetCanonicalBytes 不是恆定時間 (TOB-GOCL-6)

內部 edwards25519 包提供了一種在標量的內部和外部表示之間轉換的方法,該方法以可變時間操作。

此方法僅用於 ed25519.Verify 的簽名輸入,這些輸入不被視為秘密,因此我們認為這不是一個安全問題。儘管如此,與 TOB-GOCL-1 發現類似,我們還是決定 將該方法設為恆定時間,以防止將來意外地將此方法與秘密值一起使用,並且因為我們知道人們會在標準庫之外分叉此程式碼,並可能將其與秘密值一起使用。

Cgo 記憶體管理

發現 TOB-GOCL-3 涉及 Go+BoringCrypto 整合中的記憶體管理問題。

crypto/ecdh:自定義終結器可能會在使用該記憶體的 C 函式呼叫開始時釋放記憶體 (TOB-GOCL-3)

在審查期間,關於我們基於 cgo 的 Go+BoringCrypto 整合有許多問題,該整合提供了 FIPS 140-2 相容的加密模式,供 Google 內部使用。Go 團隊不支援在 Google 之外使用 Go+BoringCrypto 程式碼,但它對 Google 內部使用 Go 至關重要。

Trail of Bits 團隊發現了一個漏洞和一個 非安全相關錯誤,兩者都是與 C 庫互動所需的手動記憶體管理的結果。由於 Go 團隊不支援在 Google 之外使用此程式碼,因此我們選擇不為此問題釋出 CVE 或 Go 漏洞資料庫條目,但我們已在 Go 1.24 中修復了它

這種陷阱是我們決定放棄 Go+BoringCrypto 整合的眾多原因之一。我們一直在開發 原生 FIPS 140-3 模式,該模式使用常規的純 Go 密碼學軟體包,使我們能夠避免複雜的 cgo 語義,轉而採用傳統的 Go 記憶體模型。

實現完整性

發現 TOB-GOCL-4 和 TOB-GOCL-5 涉及兩個規範的有限實現,NIST SP 800-90ARFC 8018

crypto/internal/fips140/drbg:CTR_DRBG API 存在多種誤用風險 (TOB-GOCL-4)

作為我們正在引入的 原生 FIPS 140-3 模式 的一部分,我們需要 NIST CTR_DRBG(基於 AES-CTR 的確定性隨機位元生成器)的實現來提供合規的隨機性。

由於我們只需要 NIST SP 800-90A Rev. 1 CTR_DRBG 功能的一小部分,因此我們沒有實現完整規範,特別是省略了派生函式和個性化字串。這些功能對於在通用上下文中安全使用 DRBG 至關重要。

由於我們的實現嚴格限定於我們所需的特定用例,並且由於該實現未公開匯出,因此我們認為這是可以接受的,並且值得降低實現的複雜性。我們不期望此實現將來會在內部用於其他目的,並且已在 文件中添加了警告,詳細說明了這些限制。

crypto/pbkdf2:PBKDF2 不強制執行輸出長度限制 (TOB-GOCL-5)

在 Go 1.24 中,我們開始了將軟體包從 golang.org/x/crypto 移入標準庫的過程,結束了一個令人困惑的模式,即第一方、高質量、穩定的 Go 密碼學軟體包無故保留在標準庫之外。

作為此過程的一部分,我們將 golang.org/x/crypto/pbkdf2 軟體包移入標準庫,作為 crypto/pbkdf2。在審查此軟體包時,Trail of Bits 團隊注意到我們沒有強制執行 RFC 8018 中定義的派生金鑰大小限制。

限制為 (2^32 - 1) * <雜湊長度>,超出此限制金鑰將迴圈。使用 SHA-256 時,超出限制將需要超過 137GB 的金鑰。我們不期望有人曾使用 PBKDF2 生成如此大的金鑰,特別是由於 PBKDF2 在每個塊上執行迭代,但為了正確性,我們 現在強制執行標準定義的限制

下一步是什麼

此次審計的結果驗證了 Go 團隊在開發高質量、易於使用的密碼學庫方面所做的努力,並應為依賴它們構建安全軟體的使用者提供信心。

然而,我們並沒有止步不前:Go 貢獻者仍在繼續開發和改進我們為使用者提供的密碼學庫。

Go 1.24 現在包含用純 Go 編寫的 FIPS 140-3 模式,目前正在進行 CMVP 測試。這將為 Go 的所有使用者提供受支援的 FIPS 140-3 相容模式,取代目前不受支援的 Go+BoringCrypto 整合。

我們還在努力實現現代後量子密碼學,在 Go 1.24 中在 crypto/mlkem 軟體包 中引入 ML-KEM-768 和 ML-KEM-1024 實現,並向 crypto/tls 軟體包新增對混合 X25519MLKEM768 金鑰交換的支援。

最後,我們計劃引入新的更易於使用的高階密碼學 API,旨在降低選擇和使用高質量演算法進行基本用例的門檻。我們計劃從提供一個簡單的密碼雜湊 API 開始,該 API 消除了使用者決定應該依賴哪種眾多可能演算法的需要,並提供了自動遷移到最新演算法的機制,以適應技術發展。

下一篇文章:[ 關於 | 無 ] 錯誤處理的語法支援
上一篇文章:使用 testing.B.Loop 實現更可預測的基準測試
部落格索引