Go 部落格
FIPS 140-3 Go 加密模組
FIPS 140 是密碼學實現的標準,儘管它不一定能提高安全性,但在某些日益採用 Go 的受監管環境中,FIPS 140 合規性是強制要求。到目前為止,FIPS 140 合規性一直是 Go 使用者面臨的一個重大摩擦點,需要使用不受支援的解決方案,這些解決方案存在安全性、開發者體驗、功能性、釋出速度和合規性問題。
Go 正在透過內置於標準庫和 go
命令中的原生 FIPS 140 支援來滿足這一日益增長的需求,使 Go 成為遵守 FIPS 140 最簡單、最安全的方式。經驗證的 FIPS 140-3 Go 加密模組現在構成了 Go 內建加密庫的基礎,從去年 2 月釋出的 Go 1.24 中包含的 Go 加密模組 v1.0.0 開始。
v1.0.0 模組已獲得 密碼演算法驗證程式 (CAVP) 證書 A6650,並已提交給密碼模組驗證程式 (CMVP),並於 5 月進入 正在處理的模組列表 (Modules In Process List)。MIP 列表中的模組正在等待 NIST 審查,並且已經可以在某些受監管環境中部署。
Geomys 與 Go 安全團隊合作領導了實現工作,並正在為 Go 社群的利益尋求廣泛適用的 FIPS 140-3 驗證。Google 和其他行業利益相關者與 Geomys 簽訂了合同關係,以在證書中包含特定的操作環境。
有關模組的更多詳細資訊可在文件中找到。
一些 Go 使用者目前依賴 Go+BoringCrypto GOEXPERIMENT 或其分支之一作為其 FIPS 140 合規策略的一部分。與 FIPS 140-3 Go 加密模組不同,Go+BoringCrypto 從未得到官方支援,並且存在嚴重的開發者體驗問題,因為它完全是為 Google 的內部需求而生產的。一旦 Google 遷移到原生模組,它將在未來的版本中刪除。
原生開發者體驗
該模組完全透明地整合到 Go 應用程式中。事實上,每個使用 Go 1.24 構建的 Go 程式都已將其用於所有 FIPS 140-3 批准的演算法!該模組只是標準庫 crypto/internal/fips140/...
包的另一個名稱,這些包提供了 crypto/ecdsa
和 crypto/rand
等包所公開操作的實現。
這些包不涉及 cgo,這意味著它們像任何其他 Go 程式一樣進行交叉編譯,它們不產生 FFI 效能開銷,並且它們不像 Go+BoringCrypto 及其分支那樣遭受 記憶體管理安全問題。
啟動 Go 二進位制檔案時,可以使用 fips140=on
GODEBUG 選項將模組置於 FIPS 140-3 模式,該選項可以設定為環境變數或透過 go.mod
檔案設定。如果啟用了 FIPS 140-3 模式,模組將使用 NIST DRBG 進行隨機性生成,crypto/tls
將自動僅協商 FIPS 140-3 批准的 TLS 版本和演算法,並且它將在初始化和金鑰生成期間執行強制性自檢。就是這樣;沒有其他行為差異。
還有一個實驗性的更嚴格模式,fips140=only
,它會導致所有未經批准的演算法返回錯誤或觸發 panic。我們理解這對於大多數部署來說可能過於不靈活,並且正在尋求反饋,以瞭解策略執行框架可能是什麼樣子。
最後,應用程式可以使用 GOFIPS140
環境變數來針對較舊的、經過驗證的 crypto/internal/fips140/...
包版本進行構建。GOFIPS140
的工作方式類似於 GOOS
和 GOARCH
,如果設定為 GOFIPS140=v1.0.0
,程式將針對這些包提交給 CMVP 進行驗證時的 v1.0.0 快照進行構建。此快照隨 Go 標準庫的其餘部分一起提供,作為 lib/fips140/v1.0.0.zip
。
使用 GOFIPS140
時,fips140
GODEBUG 預設為 on
,因此綜上所述,所有針對 FIPS 140-3 模組構建並在 FIPS 140-3 模式下執行所需的一切就是 GOFIPS140=v1.0.0 go build
。就是這樣。
如果工具鏈是使用設定了 GOFIPS140
構建的,則它生成的所有構建都將預設為該值。
用於構建二進位制檔案的 GOFIPS140
版本可以使用 go version -m
進行驗證。
Go 的未來版本將繼續與 Go 加密模組的 v1.0.0 一起釋出和工作,直到下一個版本由 Geomys 完全認證,但在針對舊模組構建時,某些新的加密功能可能不可用。從 Go 1.24.3 開始,您可以使用 GOFIPS140=inprocess
動態選擇 Geomys 驗證已達到“正在處理”階段的最新模組。Geomys 計劃每年至少驗證一次新的模組版本,以避免 FIPS 140 構建落後太多,並且每當模組中的漏洞無法在呼叫標準庫程式碼中得到緩解時,也會進行驗證。
不妥協的安全性
我們開發模組的首要任務是匹配或超越現有 Go 標準庫密碼包的安全性。這可能令人驚訝,但有時實現和證明符合 FIPS 140 安全要求最簡單的方法並不是超越它們。我們拒絕接受這一點。
例如,crypto/ecdsa
始終生成對沖簽名。對沖簽名透過結合私鑰、訊息和隨機位元組生成 nonce。與確定性 ECDSA 一樣,它們可以防止隨機數生成器故障,否則會導致私鑰洩露 (!)。與確定性 ECDSA 不同,它們還能夠抵抗 API 問題和故障攻擊,並且不會洩露訊息等價性。FIPS 186-5 引入了對 RFC 6979 確定性 ECDSA 的支援,但不支援對沖 ECDSA。
我們沒有在 FIPS 140-3 模式下(或者更糟糕的是,在不同模式下)降級到常規隨機或確定性 ECDSA 簽名,而是切換了對沖演算法,並連線了半打文件中的點,以證明新演算法是 DRBG 和傳統 ECDSA 的合規組合。在此過程中,我們還添加了確定性簽名的可選支援。
另一個例子是隨機數生成。FIPS 140-3 對加密隨機數的生成方式有嚴格規定,這實質上強制使用使用者空間 CSPRNG。相反,我們認為核心最適合生成安全的隨機位元組,因為它最適合從系統中收集熵,並檢測程序甚至虛擬機器何時被克隆(這可能導致假定的隨機位元組被重複使用)。因此,crypto/rand 將每個讀取操作路由到核心。
為了解決這個問題,在 FIPS 140-3 模式下,我們維護一個基於 AES-256-CTR 的合規使用者空間 NIST DRBG,然後在每個讀取操作中注入從核心獲取的 128 位資料。為了 FIPS 140-3 的目的,這種額外的熵被認為是“未計入”的附加資料,但實際上,它使其與直接從核心讀取一樣強大——即使速度較慢。
最後,Go 加密模組 v1.0.0 的所有內容都在 Trail of Bits 最近的安全審計範圍內,並且未受唯一非資訊性發現的影響。
結合 Go 編譯器和執行時提供的記憶體安全保證,我們相信這實現了我們的目標,即讓 Go 成為 FIPS 140 合規性最簡單、最安全的解決方案之一。
廣泛的平臺支援
FIPS 140-3 模組只有在經過測試或“供應商確認”的操作環境中執行才符合要求,這實際上是作業系統和硬體平臺的組合。為了儘可能多地啟用 Go 用例,Geomys 驗證在業內最全面的操作環境集合之一上進行了測試。
Geomys 的實驗室在 x86-64(AMD 和 Intel)、ARMv8/9(Ampere Altra、Apple M、AWS Graviton 和 Qualcomm Snapdragon)、ARMv7、MIPS、z/ Architecture 和 POWER 的混合平臺上測試了各種 Linux 版本(Podman 上的 Alpine Linux、Amazon Linux、Google Prodimage、Oracle Linux、Red Hat Enterprise Linux 和 SUSE Linux Enterprise Server)、macOS、Windows 和 FreeBSD,總共有 23 個測試環境。
其中一些由利益相關者付費,另一些由 Geomys 為 Go 社群的利益提供資金。
此外,Geomys 驗證列出了廣泛的通用平臺作為供應商確認的操作環境
- x86-64 和 ARMv7/8/9 上的 Linux 3.10+,
- Apple M 處理器上的 macOS 11–15,
- x86-64 上的 FreeBSD 12–14,
- x86-64 上的 Windows 10 和 Windows Server 2016–2022,以及
- x86-64 和 ARMv8/9 上的 Windows 11 和 Windows Server 2025。
全面的演算法覆蓋
這可能令人驚訝,但即使在受支援的操作環境上使用由 FIPS 140-3 模組實現的 FIPS 140-3 批准的演算法,也不一定足以符合要求;該演算法必須在驗證過程中經過專門測試。因此,為了儘可能輕鬆地在 Go 中構建符合 FIPS 140 的應用程式,標準庫中所有 FIPS 140-3 批准的演算法都由 Go 加密模組實現,並作為驗證的一部分進行了測試,從數字簽名到 TLS 金鑰排程。
Go 1.24 中引入的後量子 ML-KEM 金鑰交換(FIPS 203)也經過驗證,這意味著 crypto/tls
可以透過 X25519MLKEM768 建立符合 FIPS 140-3 的後量子安全連線。
在某些情況下,我們在多個不同的 NIST 命名下驗證了相同的演算法,以便它們可以完全合規地用於不同的目的。例如,HKDF 在四個名稱下進行了測試和驗證:SP 800-108 Feedback KDF、SP 800-56C two-step KDF、Implementation Guidance D.P OneStepNoCounter KDF 和 SP 800-133 Section 6.3 KDF。
最後,我們驗證了一些內部演算法,例如 CMAC Counter KDF,以便能夠公開未來的功能,例如 XAES-256-GCM。
總的來說,原生 FIPS 140-3 模組提供了比 Go+BoringCrypto 更好的合規性配置檔案,同時為 FIPS 140-3 受限應用程式提供了更多演算法。
我們期待新的原生 Go 加密模組能夠讓 Go 開發者更容易、更安全地執行符合 FIPS 140 的工作負載。
下一篇文章:Go 1.25 釋出
上一篇文章:泛型介面
部落格索引