The Go Blog
Go暗号化セキュリティ監査
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の3人のエンジニアが1か月間監査に取り組みました。
Go暗号化パッケージのセキュリティ実績と、この監査の結果を誇りに思っています。これは、パッケージの正確性を保証するための多くの方法の1つにすぎません。まず、暗号化の原則に導かれ、複雑さを積極的に制限しています。たとえば、パフォーマンスよりもセキュリティを優先しています。さらに、さまざまな手法を用いて徹底的にテストしています。内部パッケージであっても安全なAPIを活用することを重視しており、Go言語の特性に頼ることでメモリ管理の問題を回避できるのは当然です。最後に、メンテナンスを容易にし、コードレビューと監査をより効果的にするために、可読性に重点を置いています。
低深刻度の発見が1件
唯一悪用される可能性のある問題であるTOB-GOCL-3は、低深刻度であり、影響が軽微でトリガーが困難であることを意味します。この問題はGo 1.24で修正されました。
重要なことに、TOB-GOCL-3(以下でさらに議論)は、デフォルトでは有効になっておらず、Google以外での使用はサポートされていないレガシーGo+BoringCrypto GOEXPERIMENTにおけるメモリ管理に関係しています。
情報提供の発見が5件
残りの発見は情報提供であり、差し迫ったリスクはないものの、セキュリティのベストプラクティスに関連していることを意味します。これらは現在のGo 1.25開発ツリーで対処されました。
TOB-GOCL-1、TOB-GOCL-2、およびTOB-GOCL-6の発見は、さまざまな暗号化操作における潜在的なタイミングサイドチャネルに関するものです。これら3つの発見のうち、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: Power ISAアセンブリにおけるP-256の条件付き否定が定数時間ではない (TOB-GOCL-2, CVE-2025-22866)
Goのファーストクラスプラットフォームに加えて、Goは、あまり一般的ではないアーキテクチャを含む、いくつかの追加プラットフォームもサポートしています。さまざまな基盤となる暗号プリミティブのアセンブリ実装のレビュー中に、Trail of Bitsチームは、ppc64およびppc64leアーキテクチャ上のECDSA実装に影響する1つの問題を発見しました。
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)
レビュー中に、Google内部でのFIPS 140-2準拠の暗号化モードを提供するcgoベースのGo+BoringCrypto統合に関して、いくつかの質問がありました。Go+BoringCryptoコードは、Goチームによって外部での使用がサポートされていませんが、GoogleのGoの内部使用には不可欠でした。
Trail of Bitsチームは、Cライブラリと対話するために必要な手動メモリ管理の結果として、1つの脆弱性と1つのセキュリティ関連ではないバグを発見しました。GoチームはGoogle以外でのこのコードの使用をサポートしていないため、この問題についてCVEまたはGo脆弱性データベースのエントリを発行しないことを選択しましたが、Go 1.24で修正しました。
この種の落とし穴は、Go+BoringCrypto統合から移行することを決定した多くの理由の1つです。通常の純粋なGo暗号化パッケージを使用するネイティブFIPS 140-3モードに取り組んでおり、複雑なcgoセマンティクスを避けて従来のGoメモリモデルを使用できるようにしています。
実装の完全性
TOB-GOCL-4およびTOB-GOCL-5の発見は、NIST SP 800-90AとRFC 8018の2つの仕様の限定的な実装に関するものです。
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には、現在CMVPテスト中の純粋なGoで書かれたFIPS 140-3モードが含まれています。これにより、すべてのGoユーザーにサポートされたFIPS 140-3準拠モードが提供され、現在サポートされていないGo+BoringCrypto統合に取って代わります。
また、最新のポスト量子暗号の実装にも取り組んでおり、Go 1.24でcrypto/mlkemパッケージにML-KEM-768およびML-KEM-1024の実装を導入し、crypto/tlsパッケージにハイブリッドX25519MLKEM768鍵交換のサポートを追加しています。
最後に、基本的なユースケース向けに高品質なアルゴリズムを選択して使用する際の障壁を減らすことを目的とした、新しいより使いやすい高レベル暗号化APIの導入を計画しています。まず、ユーザーが多数の可能なアルゴリズムの中からどれに頼るべきかを決定する必要をなくし、最先端技術の変化に合わせて新しいアルゴリズムに自動的に移行するメカニズムを備えたシンプルなパスワードハッシュAPIの提供から始める予定です。