Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12434] ファイルの概要

このコミットは、Go言語の標準ライブラリにおける crypto/x509 パッケージの依存関係を緩和するものです。具体的には、crypto/x509 が CGO (C言語との相互運用) および io/ioutil パッケージを使用することを許可するように変更されています。これは、システムルート証明書の取得ロジックを crypto/tls から crypto/x509 へ移行するための準備として行われました。

コミット

commit 3ea3a7c9a5e0926940b341fde56f968de152edaf
Author: Adam Langley <agl@golang.org>
Date:   Tue Mar 6 17:18:09 2012 -0500

    deps: allow crypto/x509 cgo and io/ioutil.
    
    In order to land 5700087 (which moves the knowledge of how to get the
    root certificates for the system from crypto/tls to crypto/x509), we
    need to relax the restrictions on crypto/x509. Afterwards, we can
    probably tighten them up in crypto/tls.
    
    R=golang-dev, rsc, krautz
    CC=golang-dev
    https://golang.org/cl/5753060

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/3ea3a7c9a5e0926940b341fde56f968de152edaf

元コミット内容

deps: allow crypto/x509 cgo and io/ioutil.

このコミットは、crypto/x509 パッケージが CGO および io/ioutil を使用できるように依存関係の制約を緩和します。これは、システムルート証明書を取得するロジックを crypto/tls から crypto/x509 へ移行するコミット (5700087) を適用するために必要でした。この変更後、crypto/tls の制約は再び厳しくできる可能性があります。

変更の背景

このコミットの主な背景は、Go言語の標準ライブラリにおけるTLS (Transport Layer Security) およびX.509証明書管理のアーキテクチャ変更にあります。

以前のGoのバージョンでは、システムにインストールされているルート証明書(信頼された認証局の証明書)を取得するロジックが crypto/tls パッケージ内に存在していました。しかし、このロジックはTLS通信だけでなく、一般的なX.509証明書の検証においても必要とされる機能です。そのため、より汎用的な証明書管理を担う crypto/x509 パッケージにこの機能の責任を移すことが計画されました。

コミットメッセージに記載されている 5700087 というコミット(Change List ID)が、まさにこの「システムルート証明書の取得ロジックを crypto/tls から crypto/x509 へ移動する」変更を指しています。この変更を安全かつ適切に行うためには、crypto/x509 パッケージがシステム固有の証明書ストアにアクセスするための手段が必要となります。

システム固有の証明書ストアへのアクセスは、多くの場合、OSのネイティブAPIを呼び出す必要があります。Go言語でネイティブAPIを呼び出すには CGO (C言語との相互運用) が必要です。また、証明書ファイルを読み込むためにはファイルI/O操作が必要であり、io/ioutil パッケージがその役割を担います。

したがって、5700087 の変更を適用する前に、crypto/x509 がこれらの必要な機能(CGOとio/ioutil)を利用できるように、その依存関係の制約を緩和する必要がありました。このコミットは、その前提条件を満たすためのものです。

前提知識の解説

Go言語のパッケージ依存関係管理 (go/build/deps_test.go)

Go言語の標準ライブラリには、パッケージ間の不適切な依存関係を防ぐための内部的な仕組みがあります。src/pkg/go/build/deps_test.go ファイルは、この依存関係のルールを定義し、テストするためのものです。このファイルには、各パッケージが依存しても良い他のパッケージや機能(例えば、CGO、OS固有の機能、特定の暗号化機能など)がリストアップされています。

この仕組みは、Goの標準ライブラリがクリーンで、循環参照がなく、特定のプラットフォームや機能に不必要に依存しないようにするために重要です。例えば、net/http のような高レベルのパッケージが、低レベルの syscall パッケージに直接依存するのを防ぐ、といった目的があります。

crypto/x509 パッケージ

crypto/x509 パッケージは、X.509証明書と証明書失効リスト (CRL) の解析、検証、生成、署名などの機能を提供します。TLS/SSL通信だけでなく、コード署名、S/MIME、VPNなど、様々なセキュリティプロトコルで利用されるデジタル証明書の標準形式であるX.509を扱います。

crypto/tls パッケージ

crypto/tls パッケージは、TLS (Transport Layer Security) プロトコルを実装し、安全なネットワーク通信を提供します。HTTPS通信などで利用され、X.509証明書を用いてサーバーやクライアントの認証を行い、暗号化された通信チャネルを確立します。

CGO

CGOは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。これにより、Goで直接実装されていない、またはGoで実装するのが非効率なシステム固有のAPI(例えば、OSのセキュリティ機能、グラフィックライブラリなど)を利用することができます。CGOを使用すると、Goのクロスプラットフォーム性が一部損なわれる可能性があり、ビルドプロセスも複雑になるため、標準ライブラリではその使用が厳しく管理されています。

io/ioutil パッケージ

io/ioutil パッケージは、Go 1.16で非推奨となり、Go 1.18で削除されましたが、このコミットが作成された2012年当時は、ファイルやストリームからの読み書きを簡素化するためのユーティリティ関数を提供していました。例えば、ioutil.ReadFile はファイルの内容全体をバイトスライスとして読み込むのに便利でした。

ルート証明書とシステム証明書ストア

ルート証明書は、信頼された認証局 (CA) の公開鍵証明書です。これらの証明書は、オペレーティングシステムやブラウザに事前にインストールされており、他の証明書(例えばウェブサイトのSSL証明書)の信頼性を検証するための「信頼のアンカー」として機能します。システム証明書ストアは、これらのルート証明書や中間証明書が保存されている場所です。OSによってその場所や管理方法は異なります(例: Windowsの証明書ストア、macOSのKeychain、Linuxの /etc/ssl/certs など)。

技術的詳細

このコミットの技術的な核心は、Goのビルドシステムがパッケージの依存関係をどのように管理しているか、そしてその管理がどのように変更されたかという点にあります。

src/pkg/go/build/deps_test.go ファイルは、Goの標準ライブラリ内の各パッケージが依存できる「機能」や「他のパッケージ」を明示的に定義しています。これは、Goの設計哲学の一つである「明確な依存関係」を強制するためのものです。

変更前、crypto/x509 パッケージの依存関係は以下のようになっていました。

"crypto/x509":      {"L3", "CRYPTO-MATH", "crypto/x509/pkix", "encoding/pem"},

ここで定義されているのは:

  • L3: レベル3のパッケージ(具体的な意味はGoの内部ビルドシステムに依存しますが、一般的には特定の抽象度や依存関係の深さを示します)。
  • CRYPTO-MATH: 暗号数学関連の機能への依存。
  • crypto/x509/pkix: X.509証明書のPKIX (Public Key Infrastructure X.509) 関連の機能を提供する内部パッケージへの依存。
  • encoding/pem: PEM (Privacy-Enhanced Mail) エンコーディング/デコーディング機能への依存。

この定義には、OS (オペレーティングシステム固有の機能) や CGO (C言語との相互運用) は含まれていませんでした。これは、crypto/x509 が純粋なGoコードで、OS固有のAPIやC言語のライブラリに依存しないように設計されていたことを意味します。

しかし、システムルート証明書を取得するためには、OS固有の証明書ストアにアクセスする必要があり、これは通常、CGOを介してOSのネイティブAPIを呼び出すか、OS固有のファイルパスから証明書ファイルを読み込むことによって行われます。後者の場合、ファイルI/Oのために io/ioutil (当時) が必要になります。

このコミットでは、crypto/x509 の依存関係に OSCGO を追加しています。

"crypto/x509":      {"L3", "CRYPTO-MATH", "OS", "CGO", "crypto/x509/pkix", "encoding/pem"},

この変更により、crypto/x509 パッケージは、OS 固有の機能(例えば、Windowsの証明書ストアAPIやLinuxのファイルシステムパス)を利用できるようになり、また CGO を使用してこれらのOS固有のAPIを呼び出すことが可能になります。これにより、crypto/x509 がシステムルート証明書を直接取得する責任を負うための技術的な前提が整いました。

コミットメッセージにある「Afterwards, we can probably tighten them up in crypto/tls.」という記述は、crypto/x509 がシステムルート証明書の取得を担うようになった後、crypto/tls はその機能への直接的な依存を減らし、より高レベルのTLSプロトコル実装に集中できるようになることを示唆しています。これにより、Goの標準ライブラリのモジュール性が向上し、各パッケージの責任範囲がより明確になります。

コアとなるコードの変更箇所

diff --git a/src/pkg/go/build/deps_test.go b/src/pkg/go/build/deps_test.go
index 89033e9c57..432f754d32 100644
--- a/src/pkg/go/build/deps_test.go
+++ b/src/pkg/go/build/deps_test.go
@@ -293,7 +293,7 @@ var pkgDeps = map[string][]string{
 		"L3", "CRYPTO-MATH", "CGO", "OS",
 		"crypto/x509", "encoding/pem", "net", "syscall",
 	},\n-\t"crypto/x509":      {"L3", "CRYPTO-MATH", "crypto/x509/pkix", "encoding/pem"},\n+\t"crypto/x509":      {"L3", "CRYPTO-MATH", "OS", "CGO", "crypto/x509/pkix", "encoding/pem"},\n \t"crypto/x509/pkix": {"L3", "CRYPTO-MATH"},\n 
 	// Simple net+crypto-aware packages.\n

コアとなるコードの解説

変更は src/pkg/go/build/deps_test.go ファイル内の pkgDeps というマップ(Goのマップ型)に対して行われています。このマップは、Goの標準ライブラリ内の各パッケージが依存できる要素を定義しています。

具体的には、"crypto/x509" キーに対応する値(文字列のスライス)が変更されています。

  • 変更前:

    "crypto/x509":      {"L3", "CRYPTO-MATH", "crypto/x509/pkix", "encoding/pem"},
    

    この行は、crypto/x509 パッケージが L3CRYPTO-MATHcrypto/x509/pkixencoding/pem に依存することを許可していました。

  • 変更後:

    "crypto/x509":      {"L3", "CRYPTO-MATH", "OS", "CGO", "crypto/x509/pkix", "encoding/pem"},
    

    この行では、既存の依存関係に加えて、新たに "OS""CGO" が追加されています。

この変更により、Goのビルドシステムは、crypto/x509 パッケージがオペレーティングシステム固有の機能(OS)やC言語との相互運用(CGO)を利用することを許可するようになります。これにより、crypto/x509 は、システムにインストールされているルート証明書を読み込むために必要なOSネイティブAPIの呼び出しや、ファイルシステムからの証明書ファイルの読み込み(io/ioutil を介して)を行うことができるようになります。

この deps_test.go ファイルは、Goのビルドプロセスの一部として実行されるテストによって検証されます。もしパッケージがここで定義されていない依存関係を持とうとすると、ビルド時にエラーが発生し、不適切な依存関係が導入されるのを防ぎます。したがって、この変更は、crypto/x509 が新しい役割(システムルート証明書の取得)を果たすために必要な権限を正式に与えるものです。

関連リンク

参考にした情報源リンク