crypto/tls: Profiles
要約
概要
crypto/tls にプロファイル(Profile)を導入する提案です。プロファイルとは、名前の付いたセキュリティ設定の一式で、Go チームが管理します。現在の tls.Config では利用者が多数の設定項目を個別に決める必要がありますが、この提案では「Modern」や「FIPS 140」などの方針を1つ選ぶだけで、TLS のバージョン、暗号スイート、鍵交換方式などをまとめて決められるようにします。
ステータス変更
(新規) → active
2026年10月14日の Proposal Review Meeting で active 列に追加され、毎週のレビュー対象になりました。この会議の議事録(aclements による)では、次の2点が主な論点として挙がっています。
- プロファイルの変化と固定:
ProfileModernのようなプロファイルは、ベストプラクティスの変化に合わせて Go のリリースごとに中身が更新される前提です。ただし、過去の内容に固定する手段も必要とされました。手段の候補は GODEBUG か、年号付きの定数(ProfileModern2026など)で、採用するのはどちらか一方だけとされています。 - 既存の設定項目との関係: プロファイルを設定したうえで他の Config 項目も設定するとエラーにする案が出ています。一方で、
ProfileDefaultをゼロ値にした場合にこの規則とどう両立させるかは、まだ決まっていません。
技術的背景
現状の問題点
tls.Config には設定項目が多く、使う側がそれぞれを判断し、保守し続ける負担があります。これまでも #45430(暗号スイートの順序指定を廃止)や #69393(CurvePreferences の順序を自動で決める)のように、項目ごとに整理されてきました。しかし、N 個の項目をそれぞれ決めなければならない構造自体は変わっていません。
特に問題なのは、リストを指定する項目です。たとえば CurvePreferences を明示的に設定すると、そのリストに固定されます。結果として、将来 Go が標準で有効にする PQ(耐量子計算機暗号)の鍵交換を、意図せず使わないことになります。また、古い挙動に戻すための GODEBUG(tlsrsakex=1、tls3des=1、tlssha1=1、tls10server=1 など)も増え続けています。
提案された解決策
当初の案は次のとおりです。
type Config struct {
Profile Profile
// ... 既存フィールド ...
}
type Profile string // 当初は int。値の足し引きなど算術を防ぐため string に変更
const (
ProfileDefault // ゼロ値。安全な既定値で、リリースごとに更新される
ProfileCompatibility // 古い方式も許可する互換性重視のプロファイル
ProfileModern // より厳しい。将来の Default の先取り
ProfileFIPS140 // GODEBUG=fips140=on と同じ内容
)
当初の考え方は「プロファイル(許可するパラメータの最大集合)と、Config の各項目で指定した値の共通部分を使う」というものでした。議論を経て、FiloSottile が示した次の3案のうち、案 C が有力になっています。
- 案 A: プロファイルと各項目の値の共通部分を使う。
- 案 B: ゼロ値以外のプロファイルを選んだ場合、各項目の値は無視する。
- 案 C: ゼロ値(None)の場合は現在の挙動のまま。それ以外のプロファイルを選んだうえで
MinVersion、MaxVersion、CipherSuites、CurvePreferences、Renegotiationを設定するとエラーにする。
プロファイルの内容をどう更新していくかについては、go.mod の Go バージョンと GODEBUG の仕組みを使う案が FiloSottile から出ています。具体的にはtls=go1.Nのような GODEBUG を1つ用意する案です。古い値のサポートは、GODEBUG 削除ポリシー(#76163)に沿って2年後に打ち切る想定です。
これによって何ができるようになるか
- より新しい設定を簡単に選べる:
ProfileModernを指定するだけで、TLS 1.3 以上に限定するなどの厳しい構成を選べます。その後も Go のリリースに合わせて構成が更新されます。 - 規格への準拠: FIPS 140 や CNSA 2.0(米国の暗号規格)などに合わせた設定を、プロファイル1つで表せます。ただし、FIPS 140 プロファイルを選んでも FIPS 140 準拠そのものにはならない点は、ドキュメントで注意喚起する方針です。
- 耐量子暗号への移行: 量子計算機で破られる可能性のあるアルゴリズムを、Go 側の判断ですばやく無効にできます。
- GODEBUG の増加を防ぐ: 既定値を変えるたびに個別の GODEBUG を追加する必要がなくなり、1つの
tlsGODEBUG にまとまります。
コード例
// Before: 項目を個別に指定するので、将来の改善(PQ 鍵交換など)から取り残される
cfg := &tls.Config{
MinVersion: tls.VersionTLS13,
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
}
// After(案 C を想定した例): 方針だけを選び、具体的な中身は crypto/tls に任せる
cfg := &tls.Config{
Profile: tls.ProfileModern,
}
// プロファイルと項目を同時に設定するとエラーになる(案 C)
cfg := &tls.Config{
Profile: tls.ProfileModern,
MinVersion: tls.VersionTLS12, // エラー
}
議論のハイライト
- 型の選び方: 当初の
intには、値の大小で厳しさの順序が決まると誤解されることや、値を算術で扱われることへの懸念が出ました。struct 型にする案も出ましたが、最終的にtype Profile stringに変更されました。 - 既存項目との関係(neild、ianlancetaylor、FiloSottile): プロファイルと
CurvePreferencesなどの関係が分かりにくいという指摘が相次ぎました。最終的に、ゼロ値以外のプロファイルでは項目の設定をエラーにする案 C が支持を集めています。この案には、将来これらの項目を非推奨にする道を開けることや、後から仕様を緩めても既存の正常なプログラムを壊さないという利点があります。 - ゼロ値の扱い: 提案者の thatnealpatel は、
ProfileDefaultをゼロ値にして&tls.Config{}だけで安全にすることを望んでいました。これに対し FiloSottile は、MinVersionを設定しているすべての既存コードが動かなくなるので受け入れられないと反論しました。その結果、ゼロ値は現在の挙動を保つ None とし、独立したProfileDefaultも不要という方向になっています。 - 名前: 「Profile」より「Policy」が適切ではないかという意見がありました。FiloSottile は、Profile は具体的な設定の一式を指す言葉なので適切だとして、Profile を支持しています。
- 対象外とした論点: 環境変数でプロファイルを上書きする
GODEBUG=tlsprofile(qmuntal の提案)は別の proposal で扱うことになりました。どのプロファイルにどのパラメータを含めるかも、FiloSottile が別の proposal で扱う予定です。
関連リンク
- Proposal Issue github.com/golang/go
- Review Comment proposal review meeting
- #69393 crypto/tls: automatic CurvePreferences ordering
- #76163 policy for removing GODEBUG flags
- #75086 proposal: crypto/tls: support getting the TLS configuration from Windows
- Proposal Issue #79043
- Review Minutes
- #45430 crypto/tls: deprecate PreferServerCipherSuites and CipherSuites ordering