[インデックス 16588] ファイルの概要
このコミットは、Go言語の標準ライブラリである crypto/x509
パッケージに、RFC 5280 で定義されている証明書失効リスト (CRL) 配布ポイントのサポートを追加するものです。具体的には、X.509 証明書から CRL 配布ポイント情報をパースし、また証明書を生成する際にこの情報を組み込む機能が実装されました。これにより、Goアプリケーションが証明書の失効状態を確認するための重要なメカニズムに対応できるようになります。
コミット
commit 4bd79e742a50281a2897eb84de7cf81a211c5dd4
Author: Paul van Brouwershaven <paul@vanbrouwershaven.com>
Date: Mon Jun 17 14:56:45 2013 -0700
crypto/x509: Added RFC 5280, section 4.2.1.14 to parseCertificate and buildExtensions
Support for CRL Distribution Points
R=golang-dev, agl, bradfitz
CC=golang-dev
https://golang.org/cl/10258043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4bd79e742a50281a2897eb84de7cf81a211c5dd4
元コミット内容
crypto/x509: Added RFC 5280, section 4.2.1.14 to parseCertificate and buildExtensions
Support for CRL Distribution Points
変更の背景
デジタル証明書は、公開鍵の所有者を検証するために広く利用されています。しかし、証明書が発行された後でも、秘密鍵の漏洩、組織名の変更、証明書ポリシーの違反など、様々な理由でその有効性が失われることがあります。このような場合、証明書は「失効」される必要があります。
証明書の失効情報を配布する主要なメカニズムの一つが、証明書失効リスト (CRL) です。CRL は、認証局 (CA) によって発行され、失効した証明書のシリアル番号のリストを含んでいます。クライアントは、証明書を検証する際に、その証明書が失効していないことを確認するために、関連する CRL を取得してチェックする必要があります。
このコミット以前の crypto/x509
パッケージは、X.509 証明書内の CRL 配布ポイント拡張を適切にパースまたは生成する機能を持っていませんでした。これにより、Goアプリケーションが証明書の失効状態を効率的かつ標準的な方法で確認することが困難でした。この変更は、Goの crypto/x509
ライブラリが、より堅牢な証明書検証機能を提供し、RFC 5280 に準拠した形で CRL 配布ポイントを扱うことを可能にするために行われました。
前提知識の解説
X.509 証明書
X.509 は、公開鍵証明書の標準フォーマットを定義するITU-Tの標準です。デジタル証明書は、公開鍵と、その公開鍵の所有者に関する情報(名前、組織など)を関連付け、認証局 (CA) によってデジタル署名されます。これにより、証明書の信頼性が保証されます。
証明書失効リスト (CRL)
CRL は、認証局 (CA) によって発行される、失効したデジタル証明書のリストです。各エントリには、失効した証明書のシリアル番号と、失効日時、失効理由などが含まれます。クライアントは、証明書を検証する際に、このリストを参照して、対象の証明書が失効していないことを確認します。
CRL 配布ポイント (CRL Distribution Points)
CRL 配布ポイントは、X.509 証明書の拡張フィールドの一つで、関連する CRL がどこで取得できるかを示す情報(通常はURL)を含んでいます。RFC 5280 のセクション 4.2.1.14 で定義されており、クライアントが適切な CRL を効率的に見つけ出すためのメカニズムを提供します。この拡張は、複数の配布ポイントを持つことができ、それぞれが異なるプロトコル(HTTP, LDAPなど)や場所を指し示すことがあります。
ASN.1 (Abstract Syntax Notation One)
ASN.1 は、データ構造を記述するための標準的な記法です。X.509 証明書や CRL は、ASN.1 を用いて定義された構造に従ってエンコードされます。Goの encoding/asn1
パッケージは、ASN.1 構造のエンコードとデコードをサポートします。
OID (Object Identifier)
OID は、情報オブジェクトを一意に識別するための階層的な命名システムです。X.509 証明書の拡張フィールドは、それぞれ固有の OID を持ちます。CRL 配布ポイント拡張の OID は 2.5.29.31
です。
技術的詳細
このコミットの主要な技術的変更点は、crypto/x509
パッケージが CRL 配布ポイント拡張 (OID 2.5.29.31
) を適切に処理できるようにしたことです。
-
Certificate
構造体の拡張:Certificate
構造体にCRLDistributionPoints []string
フィールドが追加されました。これにより、パースされた証明書から CRL 配布ポイントのURLリストを直接取得できるようになります。 -
ASN.1 構造体の定義: RFC 5280, 4.2.1.14 に従って、
distributionPoint
およびdistributionPointName
という内部的なASN.1構造体が定義されました。これらは、CRL 配布ポイント拡張のASN.1エンコーディングをGoの構造体にマッピングするために使用されます。distributionPoint
: 個々の配布ポイントを表し、配布ポイント名、失効理由、CRL発行者などの情報を含みます。distributionPointName
: 配布ポイントの名前を表し、完全な名前 (fullName
) または相対名 (nameRelativeToCRLIssuer
) のいずれかを取ります。このコミットでは、主にfullName
(通常はURL) の処理に焦点を当てています。
-
parseCertificate
関数でのパース処理:parseCertificate
関数は、証明書の拡張を処理する際に、OID2.5.29.31
(CRL Distribution Points) を認識するようになりました。- 拡張の値 (ASN.1エンコードされたバイト列) を
distributionPoint
のスライスとしてアンマーシャルします。 - 各
distributionPoint
からDistributionPoint.FullName
を抽出し、そのBytes
フィールドを再度ASN.1アンマーシャルしてasn1.RawValue
を取得します。 asn1.RawValue
のTag
が6
(IA5String、通常はURL) であることを確認し、そのBytes
を文字列としてCertificate.CRLDistributionPoints
に追加します。これにより、URL形式の配布ポイントが抽出されます。
- 拡張の値 (ASN.1エンコードされたバイト列) を
-
buildExtensions
関数での生成処理:buildExtensions
関数は、Certificate
テンプレートに基づいて証明書の拡張を構築する際に、template.CRLDistributionPoints
が空でない場合に CRL 配布ポイント拡張を生成するようになりました。template.CRLDistributionPoints
の各URL文字列に対して、対応するdistributionPoint
構造体を作成します。distributionPointName.FullName
には、URL文字列をasn1.RawValue
(Tag: 6, Class: 2, Bytes: URLバイト列) としてエンコードしたものを設定します。- 構築された
distributionPoint
のスライスをASN.1エンコードし、その結果を拡張の値として設定します。 buildExtensions
関数内で、拡張を格納するスライスの初期サイズが8
から9
に増やされ、新しい拡張のためのスペースが確保されました。
-
テストの追加:
x509_test.go
に、CRL 配布ポイントを含む自己署名証明書を生成し、それが正しくパースされることを検証するテストケースが追加されました。これにより、実装の正確性が保証されます。
これらの変更により、Goの crypto/x509
パッケージは、X.509 証明書における CRL 配布ポイントの標準的な利用パターンを完全にサポートするようになりました。
コアとなるコードの変更箇所
src/pkg/crypto/x509/x509.go
Certificate
構造体にCRLDistributionPoints []string
フィールドを追加。distributionPoint
およびdistributionPointName
構造体を定義。parseCertificate
関数内で、OID2.5.29.31
(CRL Distribution Points) の拡張をパースするロジックを追加。- ASN.1の
SEQUENCE OF DistributionPoint
をアンマーシャルし、各DistributionPoint
からFullName
(URL) を抽出。
- ASN.1の
oidExtensionCRLDistributionPoints
(OID2.5.29.31
) を定義。buildExtensions
関数内で、template.CRLDistributionPoints
に基づいて CRL 配布ポイント拡張を構築するロジックを追加。ret
スライスの初期サイズを8
から9
に変更。
src/pkg/crypto/x509/x509_test.go
TestCreateSelfSignedCertificate
関数内で、テスト用の証明書テンプレートにCRLDistributionPoints
を追加。- 生成された証明書の
CRLDistributionPoints
がテンプレートと一致するかを検証するreflect.DeepEqual
チェックを追加。
コアとなるコードの解説
src/pkg/crypto/x509/x509.go
の変更
// Certificate struct: Added CRLDistributionPoints field
type Certificate struct {
// ... existing fields ...
// CRL Distribution Points
CRLDistributionPoints []string
// ... existing fields ...
}
// New ASN.1 structs for CRL Distribution Points
// RFC 5280, 4.2.1.14
type distributionPoint struct {
DistributionPoint distributionPointName `asn1:"optional,tag:0"`
Reason asn1.BitString `asn1:"optional,tag:1"`
CRLIssuer asn1.RawValue `asn1:"optional,tag:2"`
}
type distributionPointName struct {
FullName asn1.RawValue `asn1:"optional,tag:0"`
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
// parseCertificate function: Handling of OID 2.5.29.31
func parseCertificate(in *certificate) (*Certificate, error) {
out := new(Certificate)
// ... existing parsing logic ...
for _, e := range in.Extensions {
switch {
// ... existing extension parsing cases ...
case e.Id.Equal(oidExtensionCRLDistributionPoints): // OID 2.5.29.31
var cdp []distributionPoint
_, err := asn1.Unmarshal(e.Value, &cdp)
if err != nil {
return nil, err
}
for _, dp := range cdp {
var n asn1.RawValue
// Unmarshal the FullName bytes to get the actual value
_, err = asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n)
if err != nil {
return nil, err
}
// Check if the tag is IA5String (tag 6), which is typically a URL
if n.Tag == 6 {
out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes))
}
}
continue
// ... other extension parsing cases ...
}
}
return out, nil
}
// OID definition for CRL Distribution Points
var (
// ... existing OID definitions ...
oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
)
// buildExtensions function: Building CRL Distribution Points extension
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
// Increased slice size to accommodate the new extension
ret = make([]pkix.Extension, 9 /* maximum number of elements. */)
n := 0
// ... existing extension building logic ...
if len(template.CRLDistributionPoints) > 0 {
ret[n].Id = oidExtensionCRLDistributionPoints
var crlDp []distributionPoint
for _, name := range template.CRLDistributionPoints {
// Marshal the URL string as an IA5String (tag 6, class 2)
rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
dp := distributionPoint{
DistributionPoint: distributionPointName{
FullName: asn1.RawValue{Tag: 0, Class: 2, Bytes: rawFullName}, // Tag 0 for FullName choice
},
}
crlDp = append(crlDp, dp)
}
ret[n].Value, err = asn1.Marshal(crlDp) // Marshal the slice of distributionPoint
if err != nil {
return
}
n++
}
// ... final return ...
return ret[:n], nil // Return only the used part of the slice
}
src/pkg/crypto/x509/x509_test.go
の変更
func TestCreateSelfSignedCertificate(t *testing.T) {
// ... existing test setup ...
template := Certificate{
// ... existing template fields ...
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PermittedDNSDomains: []string{".example.com", "example.com"},
// Added CRL Distribution Points to the template
CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
}
// ... certificate creation ...
// Added check for CRL Distribution Points
if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) {
t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints)
}
// ... existing checks ...
}
関連リンク
- RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile:
- https://datatracker.ietf.org/doc/html/rfc5280
- 特にセクション 4.2.1.14 "CRL Distribution Points" が関連します。
参考にした情報源リンク
- Go CL 10258043: このコミットの元の変更リスト。
- Go
crypto/x509
package documentation: - Go
encoding/asn1
package documentation: - Wikipedia - X.509:
- Wikipedia - 証明書失効リスト:
- RFC 5280 の日本語訳 (非公式):
- RFC 5280 の日本語訳は公式には存在しませんが、関連する技術ブログや解説記事で部分的な翻訳や説明が見られます。