[インデックス 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証明書では、この曖昧さを解消するために、YY
が50
以上であれば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
パッケージのテストスイートに以下の具体的なテストケースを追加することで、ライブラリの堅牢性を向上させています。
-
BitString.At
メソッドのテスト拡充:BitString.At
は、BitString
内の指定されたインデックスのビット値(0または1)を返すメソッドです。- 追加されたテストケースでは、負のインデックス(
-1
)と、ビット列の長さよりも大きいインデックス(17
)が与えられた場合のAt
メソッドの挙動が検証されます。これらのエッジケースにおいて、メソッドが期待通りに0
を返すことを確認します。これは、配列の境界外アクセスや無効な入力に対する堅牢なハンドリングを保証するために重要です。
-
TestUTCTime
関数のテスト拡充:TestUTCTime
は、ASN.1のUTCTime
文字列をGoのtime.Time
型に正しくパースできるかを検証するテストです。- 特に注目すべきは、
"5105062345Z"
というテストケースの追加です。これは、2桁の年号51
が、X.509証明書などで一般的に採用されている「50
以上は19YY、50
未満は20YY」という世紀の解釈ルールに従って、1951年として正しくパースされることを確認します。このテストは、UTCTime
の世紀の曖昧さに対するGoのencoding/asn1
パッケージの挙動を明確にし、互換性を保証するために重要です。
-
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
が期待されます。
- 最初のケース: 完全に一致するOIDの比較。結果は
TestObjectIdentifierEqual
関数:oiEqualTests
スライスをイテレートし、各テストケースでObjectIdentifier.Equal
メソッドを呼び出し、期待される結果と実際の結果を比較します。これにより、Equal
メソッドがOIDの正確な比較ロジックを実装していることが検証されます。
これらの追加されたテストコードは、encoding/asn1
パッケージの重要なデータ型とメソッドの正確性と堅牢性を保証するために不可欠です。
関連リンク
- Go
encoding/asn1
パッケージのドキュメント: https://pkg.go.dev/encoding/asn1 - Go
time
パッケージのドキュメント: https://pkg.go.dev/time
参考にした情報源リンク
- ASN.1 (Abstract Syntax Notation One) - Wikipedia: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
- Distinguished Encoding Rules (DER) - Wikipedia: https://en.wikipedia.org/wiki/Distinguished_Encoding_Rules
- BIT STRING (ASN.1) - OSS Nokalva: https://www.oss.com/asn1/resources/asn1-made-simple/bit-string.html
- UTCTime (ASN.1) - OSS Nokalva: https://www.oss.com/asn1/resources/asn1-made-simple/utc-time.html
- Object Identifier (OID) - OSS Nokalva: https://www.oss.com/asn1/resources/asn1-made-simple/object-identifier.html
- RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile (特に4.1.2.5. UTCTime): https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5