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

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

このコミットは、Go言語の標準ライブラリであるcrypto/tlsパッケージ内のgenerate_cert.goファイルに対する更新です。具体的には、GoのtimeパッケージのAPI変更に対応し、証明書生成スクリプトにおける時刻の取得と期間計算の方法を現代的なAPIに移行しています。

コミット

commit d5e6b8d016774776d3ca6af72839a9138e2fe996
Author: Adam Langley <agl@golang.org>
Date:   Wed Jan 4 14:56:16 2012 -0500

    crypto/tls: update generate_cert.go for new time package
    
    Fixes #2635.
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/5512043

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

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

元コミット内容

--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/pkg/crypto/tls/generate_cert.go
@@ -31,7 +31,7 @@ func main() {
 		return
 	}
 
-	now := time.Seconds()
+	now := time.Now()
 
 	template := x509.Certificate{
 		SerialNumber: new(big.Int).SetInt64(0),
@@ -39,8 +39,8 @@ func main() {
 			CommonName:   *hostName,
 			Organization: []string{"Acme Co"},
 		},
-		NotBefore: time.SecondsToUTC(now - 300),
-		NotAfter:  time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
+		NotBefore: now.Add(-5 * time.Minute).UTC(),
+		NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
 
 		SubjectKeyId: []byte{1, 2, 3, 4},
 		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,

変更の背景

この変更の背景には、Go言語の標準ライブラリにおけるtimeパッケージの進化があります。初期のGoでは、時刻の取得や操作にtime.Seconds()のような関数が使われることがありましたが、これはfloat64型で秒数を返すため、型安全性が低く、時間の概念を正確に表現する上で不十分な点がありました。また、期間の計算も秒数を直接加減算する形で行われており、特に年単位のような期間を扱う際にはうるう年などを考慮しない単純な秒数計算では不正確になる可能性がありました。

Go開発チームは、より堅牢で表現力豊かな時刻・期間操作APIを提供するため、time.Time構造体を中心とした新しいAPIを導入しました。これには、現在の時刻をtime.Time型で返すtime.Now()time.Duration型を用いた期間の加減算を行うTime.Add()、そして年・月・日単位での期間加算を正確に行うTime.AddDate()などが含まれます。

このコミットは、generate_cert.goという証明書生成スクリプトが、これらの新しいtimeパッケージのAPIに準拠するように更新されたものです。これにより、証明書の有効期間(NotBeforeNotAfter)の設定が、より正確かつGoのイディオムに沿った形で行われるようになります。コミットメッセージにあるFixes #2635は、この変更が特定の課題(おそらく古いtimeパッケージAPIの使用に関する問題や、より新しいAPIへの移行の必要性)を解決したことを示しています。

前提知識の解説

  • Go言語のtimeパッケージ: Go言語で時刻と期間を扱うための標準パッケージです。
    • time.Time: 特定の時点を表す構造体です。ナノ秒単位の精度を持ち、タイムゾーン情報も保持できます。
    • time.Duration: 期間を表す型です。ナノ秒単位で内部的に表現され、time.Secondtime.Minuteのような定数を使って直感的に期間を指定できます。
    • time.Now(): 現在のローカル時刻をtime.Time型で返します。
    • Time.Add(d Duration): TimeDurationを加算した新しいTimeを返します。
    • Time.AddDate(years int, months int, days int): Timeに指定された年、月、日を加算した新しいTimeを返します。これは、うるう年や各月の異なる日数などを考慮して正確な日付計算を行います。
    • Time.UTC(): TimeをUTC(協定世界時)に変換した新しいTimeを返します。
  • crypto/tlsパッケージ: Go言語でTLS(Transport Layer Security)およびSSL(Secure Sockets Layer)プロトコルを実装するためのパッケージです。安全なネットワーク通信を提供します。
  • x509パッケージ: X.509証明書を解析、生成、検証するためのパッケージです。
    • x509.Certificate: X.509証明書の構造を表す型です。
    • NotBefore: 証明書が有効になる開始日時を示すフィールドです。
    • NotAfter: 証明書が有効でなくなる終了日時を示すフィールドです。
  • big.Int: 任意精度の整数を扱うための型です。ここでは証明書のシリアル番号を設定するために使用されています。
  • UTC (Coordinated Universal Time): 協定世界時。世界の標準時であり、タイムゾーンの影響を受けない普遍的な時刻表現です。証明書の有効期間は通常UTCで指定されます。

技術的詳細

このコミットの核心は、GoのtimeパッケージにおけるAPIのパラダイムシフトを反映したものです。

  1. 時刻の取得:

    • 変更前: now := time.Seconds()
      • time.Seconds()は、Unixエポック(1970年1月1日00:00:00 UTC)からの秒数をfloat64型で返していました。これは、時刻を数値として扱うため、型安全性が低く、時間の概念を直接的に表現するtime.Time型に比べて直感的ではありませんでした。
    • 変更後: now := time.Now()
      • time.Now()は、現在のローカル時刻をtime.Time型の値として返します。time.Timeは、年、月、日、時、分、秒、ナノ秒、タイムゾーン情報など、時刻に関する豊富な情報を持つ構造体であり、より正確で型安全な時刻表現を可能にします。
  2. 期間の計算とUTC変換:

    • 変更前:
      • NotBefore: time.SecondsToUTC(now - 300)
      • NotAfter: time.SecondsToUTC(now + 60*60*24*365)
      • 古いAPIでは、nowfloat64の秒数であるため、期間の加減算も秒数の直接的な加減算で行われていました(例: now - 300で5分前、60*60*24*365で1年)。
      • time.SecondsToUTC()は、秒数をUTCのtime.Timeに変換する関数でした。
      • この方法では、特に1年間の有効期間を計算する際に、うるう年を考慮しないため、厳密には不正確になる可能性がありました。
    • 変更後:
      • NotBefore: now.Add(-5 * time.Minute).UTC()
      • NotAfter: now.AddDate(1, 0, 0).UTC()
      • 新しいAPIでは、nowtime.Time型であるため、そのメソッドを使って期間を操作します。
      • now.Add(-5 * time.Minute): time.Time型のnowからtime.Duration型の-5 * time.Minute(-5分)を減算し、新しいtime.Timeを生成します。time.Minutetime.Duration型の定数であり、期間の指定が非常に明確になります。
      • now.AddDate(1, 0, 0): time.Time型のnowに1年、0ヶ月、0日を加算した新しいtime.Timeを生成します。このメソッドは、うるう年などの暦の規則を正確に考慮して日付を計算するため、証明書の有効期間のような厳密な日付計算に適しています。
      • .UTC(): 最後にUTC()メソッドを呼び出すことで、計算された時刻を協定世界時(UTC)に変換しています。これは、証明書の有効期間が通常UTCで指定されるという慣習に沿ったものです。

この変更により、コードの可読性が向上し、時刻と期間の計算がより正確かつ堅牢になりました。

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

src/pkg/crypto/tls/generate_cert.goファイルにおいて、以下の3行が変更されています。

  1. 時刻の現在値取得:
    -	now := time.Seconds()
    +	now := time.Now()
    
  2. 証明書の有効開始日時 (NotBefore) の設定:
    -		NotBefore: time.SecondsToUTC(now - 300),
    +		NotBefore: now.Add(-5 * time.Minute).UTC(),
    
  3. 証明書の有効終了日時 (NotAfter) の設定:
    -		NotAfter:  time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
    +		NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
    

コアとなるコードの解説

  • now := time.Now():

    • これは、現在のシステム時刻をtime.Time型の変数nowに格納する変更です。古いtime.Seconds()float64で秒数を返していたのに対し、time.Now()はGoのtimeパッケージが提供する豊富な機能を持つtime.Time構造体を返します。これにより、後続の時刻操作がよりオブジェクト指向的かつ安全に行えるようになります。
  • NotBefore: now.Add(-5 * time.Minute).UTC():

    • 証明書の有効開始日時を設定する行です。
    • 変更前は、現在の秒数から300秒(5分)を減算し、それをUTCに変換していました。
    • 変更後は、time.Time型のnowに対してAddメソッドを使用しています。-5 * time.Minuteという表現は、time.Duration型を利用して「5分前」という期間を明確に示しており、コードの意図が非常に読みやすくなっています。最後に.UTC()を呼び出すことで、結果の時刻が協定世界時であることを保証しています。
  • NotAfter: now.AddDate(1, 0, 0).UTC():

    • 証明書の有効終了日時を設定する行です。
    • 変更前は、現在の秒数に1年分の秒数(60*60*24*365)を単純に加算し、それをUTCに変換していました。この方法はうるう年を考慮しないため、厳密な1年後の日付を保証できませんでした。
    • 変更後は、time.Time型のnowに対してAddDateメソッドを使用しています。AddDate(1, 0, 0)は、nowに1年、0ヶ月、0日を加算することを意味します。このメソッドは、うるう年や各月の異なる日数を自動的に考慮するため、暦上の正確な1年後の日付を計算できます。これにより、証明書の有効期間の計算がより堅牢かつ正確になりました。同様に、最後に.UTC()を呼び出してUTCに変換しています。

これらの変更は、Goのtimeパッケージが提供する現代的でイディオムに沿ったAPIを活用することで、コードの品質、可読性、そして正確性を向上させています。

関連リンク

参考にした情報源リンク