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

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

このコミットは、Go言語の標準ライブラリencoding/asn1パッケージ内のテストケースを拡充するものです。具体的には、BitString.Atメソッド、TestUTCTime関数、およびObjectIdentifier.Equalメソッドに対する新たなテストが追加されています。これにより、これらの機能の堅牢性と正確性が向上し、特にエッジケースや異なる入力値に対する挙動がより厳密に検証されるようになります。

コミット

commit c22e79b37b95c1313ec9bee70147cade6461fb29
Author: Shawn Smith <shawn.p.smith@gmail.com>
Date:   Wed Dec 18 10:19:07 2013 -0800

    encoding/asn1: add more test cases for BitString.At and TestUTCTime, add test for ObjectIdentifier.Equal
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/42740043

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

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

元コミット内容

encoding/asn1: add more test cases for BitString.At and TestUTCTime, add test for ObjectIdentifier.Equal

変更の背景

このコミットの背景には、encoding/asn1パッケージのテストカバレッジと堅牢性の向上という目的があります。encoding/asn1は、ASN.1 (Abstract Syntax Notation One) 形式のデータをGoのデータ構造との間でエンコード/デコードするための重要なパッケージであり、特にX.509証明書のようなセキュリティ関連のプロトコルで広く利用されています。

既存のテストではカバーしきれていなかった、BitString.Atメソッドにおける負のインデックスや範囲外のインデックスの扱い、UTCTimeの世紀の解釈(特に1950年代の年号)、そしてObjectIdentifier.Equalメソッドの正確な比較ロジックといったエッジケースや特定のシナリオに対する検証が不足していました。これらのテストケースを追加することで、ライブラリの信頼性を高め、将来的なバグの混入を防ぐことが意図されています。

前提知識の解説

このコミットを理解するためには、以下の概念についての前提知識が必要です。

ASN.1 (Abstract Syntax Notation One)

ASN.1は、データ構造をプラットフォームやプログラミング言語に依存しない形で記述するための国際標準の記法です。主に通信プロトコルやデータ交換フォーマット、特に暗号化やセキュリティ関連の分野(例: X.509証明書、PKCS#7、LDAP)で広く利用されています。ASN.1は、データの型(例: INTEGER, BOOLEAN, OCTET STRING, SEQUENCE)と、それらの型を組み合わせた複雑なデータ構造を定義する能力を提供します。

DER (Distinguished Encoding Rules)

DERは、ASN.1で定義されたデータ構造をバイト列にエンコードするための規則の一つです。DERの最大の特徴は、同じASN.1データ構造に対して常に一意のバイト列を生成するという「一意性」です。この一意性は、デジタル署名のように、データのバイト表現が厳密に一致する必要がある場合に不可欠です。Goのencoding/asn1パッケージは、主にDERエンコーディングを扱います。

encoding/asn1パッケージ

Go言語のencoding/asn1パッケージは、ASN.1で定義されたデータ構造とGoの構造体との間で、DERエンコーディングを用いたマーシャリング(Goのデータ構造からバイト列への変換)とアンマーシャリング(バイト列からGoのデータ構造への変換)を行う機能を提供します。このパッケージは、X.509証明書の解析や生成など、GoアプリケーションでASN.1データを扱う際に中心的な役割を果たします。

BitString

ASN.1のBIT STRING型は、任意の長さのビット列を表すために使用されます。OCTET STRINGが8ビットの倍数である必要があるのに対し、BIT STRINGは任意のビット長を持つことができます。Goのencoding/asn1パッケージでは、BitString型がこれに対応し、ビット列の操作(例: 特定のインデックスのビット値の取得)を行うメソッドを提供します。

UTCTime

ASN.1のUTCTime型は、協定世界時(UTC)の日付と時刻を表すために使用されます。通常、YYMMDDhhmm[ss]ZまたはYYMMDDhhmm[ss](+|-)hhmmの形式で表現されます。UTCTimeの大きな特徴は、年が2桁(YY)で表現される点です。これにより、世紀の解釈に曖昧さが生じる可能性があります(例: 51が1951年を指すのか2051年を指すのか)。X.509証明書では、この曖昧さを解消するために、YY50以上であれば19YY、50未満であれば20YYと解釈するルールが一般的に適用されます。

ObjectIdentifier

ASN.1のOBJECT IDENTIFIER (OID) 型は、オブジェクト、概念、またはエンティティを一意に識別するためのグローバルな数値識別子です。OIDはドットで区切られた数値のシーケンス(例: 1.2.840.113549.1.1.1)で表現され、階層的なツリー構造を形成します。これにより、世界中で一意性が保証されます。OIDは、アルゴリズム、証明書ポリシー、データ構造など、様々な情報を識別するために、特に暗号化や電気通信の分野で広く使用されます。Goのencoding/asn1パッケージでは、ObjectIdentifier型がこれに対応し、OIDの比較などを行うメソッドを提供します。

技術的詳細

このコミットは、encoding/asn1パッケージのテストスイートに以下の具体的なテストケースを追加することで、ライブラリの堅牢性を向上させています。

  1. BitString.Atメソッドのテスト拡充:

    • BitString.Atは、BitString内の指定されたインデックスのビット値(0または1)を返すメソッドです。
    • 追加されたテストケースでは、負のインデックス(-1)と、ビット列の長さよりも大きいインデックス(17)が与えられた場合のAtメソッドの挙動が検証されます。これらのエッジケースにおいて、メソッドが期待通りに0を返すことを確認します。これは、配列の境界外アクセスや無効な入力に対する堅牢なハンドリングを保証するために重要です。
  2. TestUTCTime関数のテスト拡充:

    • TestUTCTimeは、ASN.1のUTCTime文字列をGoのtime.Time型に正しくパースできるかを検証するテストです。
    • 特に注目すべきは、"5105062345Z"というテストケースの追加です。これは、2桁の年号51が、X.509証明書などで一般的に採用されている「50以上は19YY、50未満は20YY」という世紀の解釈ルールに従って、1951年として正しくパースされることを確認します。このテストは、UTCTimeの世紀の曖昧さに対するGoのencoding/asn1パッケージの挙動を明確にし、互換性を保証するために重要です。
  3. ObjectIdentifier.Equalメソッドのテスト追加:

    • ObjectIdentifier.Equalは、2つのObjectIdentifierが等しいかどうかを比較するメソッドです。
    • このコミットでは、oiEqualTestという新しいテスト構造体とoiEqualTestsというテストデータスライスが導入され、TestObjectIdentifierEqual関数が追加されています。
    • テストケースには、完全に一致するOID、長さが異なるOID、そして値が異なるOIDの比較が含まれます。これにより、EqualメソッドがOIDの各要素と長さを正確に比較し、期待通りのブール値を返すことが検証されます。OIDの比較は、プロトコルにおける識別子の検証や、セキュリティポリシーの適用において非常に重要です。

これらのテストケースの追加は、encoding/asn1パッケージが様々な有効な入力だけでなく、無効な入力やエッジケースに対しても正しく、かつ予測可能な挙動を示すことを保証するためのものです。これにより、ライブラリの品質と信頼性が向上し、それを利用するアプリケーションの安定性にも寄与します。

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

このコミットによる変更は、src/pkg/encoding/asn1/asn1_test.goファイルに集中しています。

--- a/src/pkg/encoding/asn1/asn1_test.go
+++ b/src/pkg/encoding/asn1/asn1_test.go
@@ -171,6 +171,12 @@ func TestBitStringAt(t *testing.T) {
  	if bs.At(9) != 1 {
  		t.Error("#4: Failed")
  	}
+	if bs.At(-1) != 0 {
+		t.Error("#5: Failed")
+	}
+	if bs.At(17) != 0 {
+		t.Error("#6: Failed")
+	}
  }
  
  type bitStringRightAlignTest struct {
@@ -238,6 +244,7 @@ var utcTestData = []timeTest{
  	{"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))},
  	{"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)},
  	{"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)},
+	{"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)},
  	{"a10506234540Z", false, time.Time{}},
  	{"91a506234540Z", false, time.Time{}},
  	{"9105a6234540Z", false, time.Time{}},
@@ -509,6 +516,38 @@ func TestRawStructs(t *testing.T) {
  	}
  }
  
+type oiEqualTest struct {
+	first  ObjectIdentifier
+	second ObjectIdentifier
+	same   bool
+}
+
+var oiEqualTests = []oiEqualTest{
+	{
+		ObjectIdentifier{1, 2, 3},
+		ObjectIdentifier{1, 2, 3},
+		true,
+	},
+	{
+		ObjectIdentifier{1},
+		ObjectIdentifier{1, 2, 3},
+		false,
+	},
+	{
+		ObjectIdentifier{1, 2, 3},
+		ObjectIdentifier{10, 11, 12},
+		false,
+	},
+}
+
+func TestObjectIdentifierEqual(t *testing.T) {
+	for _, o := range oiEqualTests {
+		if s := o.first.Equal(o.second); s != o.same {
+			t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
+		}
+	}
+}
+
  var derEncodedSelfSignedCert = Certificate{
  	TBSCertificate: TBSCertificate{
  		Version:            0,

コアとなるコードの解説

TestBitStringAt関数への追加

既存のTestBitStringAt関数に、以下のテストケースが追加されました。

	if bs.At(-1) != 0 {
		t.Error("#5: Failed")
	}
	if bs.At(17) != 0 {
		t.Error("#6: Failed")
	}
  • bs.At(-1): BitString.Atメソッドに負のインデックスが渡された場合をテストします。期待される挙動は、無効なインデックスに対して0を返すことです。
  • bs.At(17): BitStringの実際の長さ(このテストケースではbsは10ビットのビット列)を超えるインデックスが渡された場合をテストします。これも同様に0を返すことが期待されます。

これらのテストは、BitString.Atメソッドが境界条件や無効な入力に対して堅牢であることを保証します。

utcTestDataへの追加

utcTestDataスライスに、UTCTimeの世紀の解釈に関するテストケースが追加されました。

	{"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)},
  • "5105062345Z": この文字列は、年号が51であるUTCTimeを表します。Goのencoding/asn1パッケージが、この51を1951年として正しく解釈し、対応するtime.Timeオブジェクトを生成できるかを検証します。これは、X.509証明書などで広く採用されている世紀の解釈ルールに準拠していることを確認するために重要です。

ObjectIdentifier.Equalメソッドのテスト追加

ObjectIdentifier.Equalメソッドのテストのために、新しい構造体とテスト関数が追加されました。

type oiEqualTest struct {
	first  ObjectIdentifier
	second ObjectIdentifier
	same   bool
}

var oiEqualTests = []oiEqualTest{
	{
		ObjectIdentifier{1, 2, 3},
		ObjectIdentifier{1, 2, 3},
		true,
	},
	{
		ObjectIdentifier{1},
		ObjectIdentifier{1, 2, 3},
		false,
	},
	{
		ObjectIdentifier{1, 2, 3},
		ObjectIdentifier{10, 11, 12},
		false,
	},
}

func TestObjectIdentifierEqual(t *testing.T) {
	for _, o := range oiEqualTests {
		if s := o.first.Equal(o.second); s != o.same {
			t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
		}
	}
}
  • oiEqualTest構造体: 比較対象の2つのObjectIdentifierと、それらが等しいと期待される結果(trueまたはfalse)を保持します。
  • oiEqualTestsスライス: 複数のテストシナリオを定義します。
    • 最初のケース: 完全に一致するOIDの比較。結果はtrueが期待されます。
    • 2番目のケース: 長さが異なるOIDの比較。結果はfalseが期待されます。
    • 3番目のケース: 長さは同じだが、要素の値が異なるOIDの比較。結果はfalseが期待されます。
  • TestObjectIdentifierEqual関数: oiEqualTestsスライスをイテレートし、各テストケースでObjectIdentifier.Equalメソッドを呼び出し、期待される結果と実際の結果を比較します。これにより、EqualメソッドがOIDの正確な比較ロジックを実装していることが検証されます。

これらの追加されたテストコードは、encoding/asn1パッケージの重要なデータ型とメソッドの正確性と堅牢性を保証するために不可欠です。

関連リンク

参考にした情報源リンク