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

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

コミット

commit cca48f1a577bc5eb8363ef4ce63af6a9b30a164a
Author: David du Colombier <0intro@gmail.com>
Date:   Wed Sep 26 14:47:47 2012 -0400

    crypto/x509: add Plan 9 root certificate location
    
    R=golang-dev
    CC=golang-dev, rsc
    https://golang.org/cl/6571056

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

https://github.com/golang/go/commit/cca48f1a577bc5eb8363ef4ce63af6a9b30a164a

元コミット内容

crypto/x509: add Plan 9 root certificate location

R=golang-dev
CC=golang-dev, rsc
https://golang.org/cl/6571056

変更の背景

このコミットは、Go言語のcrypto/x509パッケージにPlan 9オペレーティングシステム用のルート証明書(CA証明書)の探索パスを追加するものです。GoのプログラムがTLS/SSL通信を行う際、通信相手の証明書が信頼できるものであるかを確認するために、システムにインストールされている信頼されたルート証明書を利用します。

従来のGoのcrypto/x509パッケージは、Linux、macOS (Darwin)、Windowsなどの主要なOS環境におけるルート証明書の探索パスをサポートしていましたが、Plan 9オペレーティングシステムには対応していませんでした。この不足により、Plan 9上で動作するGoアプリケーションがTLS/SSL通信を行う際に、システムが提供する信頼されたルート証明書を自動的に利用できず、証明書の検証に失敗する可能性がありました。

このコミットの目的は、Plan 9環境においてもGoアプリケーションがセキュアな通信を円滑に行えるよう、Plan 9の標準的なルート証明書パスである/sys/lib/tls/ca.pemを認識させ、自動的にロードする機能を追加することにあります。これにより、Goのクロスプラットフォーム対応がさらに強化され、Plan 9ユーザーもGoのネットワーク機能をより安全に利用できるようになります。

前提知識の解説

1. X.509証明書とルート証明書

X.509は、公開鍵証明書の標準フォーマットです。インターネット上の通信において、サーバーやクライアントの身元を確認し、通信の暗号化を確立するために広く利用されています。X.509証明書は、公開鍵、所有者の情報、発行者の情報、有効期間、デジタル署名などを含みます。

ルート証明書(Root Certificate)は、認証局(CA: Certificate Authority)によって自己署名された証明書であり、信頼の鎖(Chain of Trust)の最上位に位置します。Webブラウザやオペレーティングシステムには、信頼できる主要な認証局のルート証明書があらかじめインストールされており、これらが通信相手の証明書を検証する際の信頼の起点となります。

2. TLS/SSL通信と証明書検証

TLS (Transport Layer Security) およびその前身であるSSL (Secure Sockets Layer) は、インターネット上での安全なデータ通信を可能にする暗号化プロトコルです。TLS通信では、サーバーがクライアントに自身のX.509証明書を提示し、クライアントはその証明書が信頼できる認証局によって発行されたものであるか、また改ざんされていないかなどを検証します。この検証プロセスにおいて、クライアントは自身のシステムに保存されているルート証明書を利用して、提示された証明書の信頼性を確認します。

3. Go言語のcrypto/x509パッケージ

Go言語の標準ライブラリに含まれるcrypto/x509パッケージは、X.509証明書の解析、生成、検証などの機能を提供します。特に、x509.SystemCertPool()関数は、オペレーティングシステムが提供する信頼されたルート証明書のプールをロードする役割を担っています。このプールは、TLSクライアントがサーバー証明書を検証する際に使用されます。

4. ビルドタグ(Build Tags)

Go言語には「ビルドタグ」という機能があります。これは、ソースコードファイルの先頭に// +build tagnameのようなコメントを記述することで、特定の環境や条件でのみそのファイルをコンパイル対象とする仕組みです。例えば、// +build linuxと書かれたファイルはLinux環境でのみコンパイルされ、他のOSでは無視されます。これにより、OS固有のコードや機能を持つファイルを、単一のコードベース内で管理することが可能になります。

5. Plan 9オペレーティングシステム

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの概念をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現し、それらをネットワーク越しに透過的にアクセスできるという特徴を持ちます。Go言語の開発者の一部はPlan 9の開発にも携わっており、Go言語自体もPlan 9の設計思想から影響を受けている部分があります。Plan 9におけるTLS/SSL関連のファイルは、通常/sys/lib/tls/ディレクトリに配置されます。

技術的詳細

このコミットは、Go言語のcrypto/x509パッケージにおけるシステムルート証明書のロードロジックに、Plan 9オペレーティングシステム固有のパスを追加するものです。

具体的には、以下の2つのファイルが変更されています。

  1. src/pkg/crypto/x509/root_plan9.go (新規作成):

    • このファイルは、// +build plan9というビルドタグを持っています。これは、このファイルがPlan 9環境でのみコンパイルされることを意味します。
    • certFilesという文字列スライスが定義されており、Plan 9におけるルート証明書の標準的なパスである"/sys/lib/tls/ca.pem"が格納されています。
    • initSystemRoots()関数が実装されています。この関数は、certFilesに定義されたパスを順に試行し、最初に読み込みに成功した証明書ファイルをPEM形式で読み込み、x509.CertPoolに追加します。これにより、Plan 9システムが提供する信頼されたルート証明書がGoの証明書プールにロードされます。
    • systemVerify()関数は、Plan 9環境では証明書のシステム検証をサポートしないため、nil, nilを返します。これは、Goのcrypto/x509パッケージが提供する一般的な証明書検証ロジックを使用することを意味し、OS固有の検証メカニズムには依存しないことを示唆しています。
  2. src/pkg/crypto/x509/root_stub.go (変更):

    • このファイルは、元々// +build plan9 darwin,!cgoというビルドタグを持っていました。これは、Plan 9環境、またはCgoを使用しないDarwin(macOS)環境でコンパイルされることを意味していました。
    • 今回の変更で、ビルドタグからplan9が削除され、// +build darwin,!cgoとなりました。
    • これにより、root_stub.goはPlan 9環境ではコンパイルされなくなり、代わりに新しく追加されたroot_plan9.goがPlan 9固有のルート証明書ロードロジックを提供することになります。root_stub.goは、システムルート証明書をロードできない環境(例えば、CgoなしのmacOSなど)のためのスタブ実装として機能し続けます。

この変更により、Goのビルドシステムは、Plan 9環境でコンパイルする際にroot_plan9.goを選択し、他の環境では既存のOS固有のファイル(例: Linuxの場合はroot_unix.go、Windowsの場合はroot_windows.goなど)またはroot_stub.goを選択するようになります。

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

src/pkg/crypto/x509/root_plan9.go (新規追加)

// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build plan9

package x509

import "io/ioutil"

// Possible certificate files; stop after finding one.
var certFiles = []string{
	"/sys/lib/tls/ca.pem",
}

func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
	return nil, nil
}

func initSystemRoots() {
	roots := NewCertPool()
	for _, file := range certFiles {
		data, err := ioutil.ReadFile(file)
		if err == nil {
			roots.AppendCertsFromPEM(data)
			break
		}
	}

	systemRoots = roots
}

src/pkg/crypto/x509/root_stub.go (変更)

--- a/src/pkg/crypto/x509/root_stub.go
+++ b/src/pkg/crypto/x509/root_stub.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build plan9 darwin,!cgo
+// +build darwin,!cgo
 
 package x509
 

コアとなるコードの解説

root_plan9.go

  • // +build plan9: この行はGoのビルドタグです。Goコンパイラは、このタグが存在する場合にのみ、このファイルをPlan 9オペレーティングシステム向けにビルドする際に含めます。これにより、Plan 9固有のコードが他のOSのビルドに混入するのを防ぎます。
  • package x509: このファイルがcrypto/x509パッケージの一部であることを示します。
  • import "io/ioutil": ファイルの読み込みに必要なioutilパッケージをインポートしています。
  • var certFiles = []string{"/sys/lib/tls/ca.pem"}: Plan 9システムにおける信頼されたルート証明書ファイルが配置される可能性のあるパスを定義しています。Plan 9では、通常/sys/lib/tls/ca.pemにCA証明書が格納されます。
  • func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error): この関数は、Goのcrypto/x509パッケージが提供する証明書検証のインターフェースの一部です。Plan 9ではOSレベルでの証明書検証メカニズムに直接フックしないため、ここでは単にnil, nilを返しています。これは、Goの標準的な検証ロジックが適用されることを意味します。
  • func initSystemRoots(): この関数は、Goプログラムの起動時に一度だけ実行され、システムが提供するルート証明書をロードする役割を担います。
    • roots := NewCertPool(): 新しい証明書プールを作成します。このプールに信頼されたルート証明書が追加されます。
    • for _, file := range certFiles: certFilesに定義された各パスをループで処理します。
    • data, err := ioutil.ReadFile(file): 指定されたパスからファイルを読み込もうとします。
    • if err == nil: ファイルの読み込みが成功した場合、つまりそのパスに証明書ファイルが存在した場合。
    • roots.AppendCertsFromPEM(data): 読み込んだファイルの内容(PEM形式の証明書データ)を証明書プールに追加します。
    • break: 最初の有効な証明書ファイルが見つかり、ロードされた時点でループを終了します。これは、複数のパスが定義されている場合に、最初に見つかったものだけを使用するという戦略を示しています。
    • systemRoots = roots: グローバル変数systemRootsに、ロードされたルート証明書プールを設定します。このsystemRootsが、GoのTLSクライアントが証明書検証を行う際に参照する信頼された証明書の集合となります。

root_stub.go

  • // +build darwin,!cgo: 変更後のビルドタグです。元々含まれていたplan9が削除されています。これにより、このファイルはPlan 9環境ではコンパイルされなくなり、Cgoを使用しないmacOS環境でのみコンパイルされるようになります。root_stub.goは、システムルート証明書をロードできない環境のためのフォールバック(スタブ)実装として機能します。

この変更により、Goのビルドシステムは、Plan 9環境ではroot_plan9.goを、Cgoを使用しないmacOS環境ではroot_stub.goを、その他の主要なOS(Linux, Windowsなど)ではそれぞれのOS固有のルート証明書ロードロジックを持つファイルを適切に選択してコンパイルするようになります。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード(特にsrc/crypto/x509ディレクトリ内のファイル)
  • Plan 9オペレーティングシステムのファイルシステム構造に関する一般的な知識
  • X.509証明書とTLS/SSLプロトコルに関する一般的な知識
  • Go言語のビルドシステムに関するドキュメント
  • GitHubのコミット履歴と関連するコードレビューコメント
  • Go言語のIssueトラッカーやメーリングリストでの議論(該当する場合)
  • ioutil.ReadFileのGoドキュメント: https://pkg.go.dev/io/ioutil#ReadFile (Go 1.16以降はos.ReadFileが推奨)
  • x509.CertPoolのGoドキュメント: https://pkg.go.dev/crypto/x509#CertPool
  • x509.Certificate.VerifyのGoドキュメント: https://pkg.go.dev/crypto/x509#Certificate.Verify
  • x509.SystemCertPoolのGoドキュメント: https://pkg.go.dev/crypto/x509#SystemCertPool