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

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

このコミットは、Go言語の標準ライブラリに含まれるハッシュパッケージ(adler32, crc32, md5, sha1)にドキュメンテーションコメントを追加するものです。これにより、各パッケージの目的、主要な関数や型の役割が明確になり、ライブラリの利用者がコードの意図をより容易に理解できるようになります。特に、Digest型、NewDigest関数、Writeメソッド、Sum32メソッド、Sumメソッドなど、ハッシュ計算のコアとなる要素に対して詳細な説明が加えられています。

コミット

commit 1910a7c595f88ece1d6214037ac8356c86b48f3e
Author: Rob Pike <r@golang.org>
Date:   Sat Mar 7 16:56:21 2009 -0800

    document hash
    
    R=rsc
    DELTA=50  (33 added, 4 deleted, 13 changed)
    OCL=25878
    CL=25887
---
 src/lib/hash/adler32.go | 26 ++++++++++++++++----------
 src/lib/hash/crc32.go   | 19 ++++++++++++++++---\n src/lib/hash/md5.go     |  9 +++++++--
 src/lib/hash/sha1.go    |  9 +++++++--
 4 files changed, 46 insertions(+), 17 deletions(-)

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

https://github.com/golang/go/commit/1910a7c595f88ece1d6214037ac8356c86b48f3e

元コミット内容

document hash

変更の背景

このコミットが行われた2009年3月は、Go言語がまだ一般に公開される前の開発初期段階にあたります。Go言語の設計思想の一つに「シンプルさと明瞭さ」があり、標準ライブラリのAPIドキュメンテーションはその重要な要素です。開発初期においては、機能の実装が優先され、ドキュメンテーションは後回しにされることがよくあります。

このコミットの背景には、Go言語の標準ライブラリの品質向上と、将来的な公開に向けた準備があったと考えられます。ハッシュ関数は、データ整合性の検証、デジタル署名、パスワードの保存など、多くのアプリケーションで利用される基本的な機能です。これらの重要な機能を提供するパッケージが適切にドキュメント化されることで、開発者はGo言語のハッシュ機能をより安全かつ効率的に利用できるようになります。

特に、Go言語ではエクスポートされた(大文字で始まる)関数、変数、型、メソッドにはドキュメンテーションコメントを記述することが慣例となっており、godocツールによって自動的にAPIドキュメントが生成されます。このコミットは、その慣例に沿って、ハッシュパッケージのAPIをより利用しやすくするための初期の取り組みの一環と言えるでしょう。

前提知識の解説

1. チェックサムとハッシュ関数

  • チェックサム (Checksum): データの整合性を確認するために使用される短い固定長のデータです。データが転送または保存される際に変更されていないことを検出するために利用されます。Adler-32やCRC-32が代表的なチェックサムアルゴリズムです。これらは主にデータの破損検出を目的としており、意図的な改ざんに対する耐性は限定的です。
  • ハッシュ関数 (Hash Function): 任意の長さの入力データから、固定長の出力(ハッシュ値、メッセージダイジェスト)を生成する関数です。暗号学的ハッシュ関数は、以下の特性を持ちます。
    • 一方向性 (One-way function): ハッシュ値から元のデータを効率的に復元することは困難です。
    • 衝突耐性 (Collision resistance): 異なる入力から同じハッシュ値が生成されること(衝突)が非常に困難です。
    • 原像計算困難性 (Preimage resistance): 特定のハッシュ値を持つ入力を見つけることが困難です。 MD5やSHA-1が代表的な暗号学的ハッシュ関数ですが、MD5やSHA-1は現在ではセキュリティ上の脆弱性が指摘されており、新たなアプリケーションでの利用は推奨されません。

2. Adler-32

Adler-32は、RFC 1950で定義されているチェックサムアルゴリズムです。CRC-32よりも高速に計算できることが特徴ですが、衝突耐性はCRC-32よりも低いとされています。2つの16ビットの和(s1とs2)を計算し、それらを結合して32ビットのチェックサムを生成します。s1はバイトの合計、s2はs1の累積合計であり、両方とも特定のモジュロ(65521)で計算されます。

3. CRC-32 (Cyclic Redundancy Check)

CRC-32は、データ転送やストレージにおいて、偶発的なデータ変更を検出するために広く使用されるエラー検出コードです。多項式除算に基づいており、特定の多項式(例: IEEE 802.3で使われる多項式)を用いて計算されます。Adler-32よりも衝突耐性が高く、より信頼性の高いエラー検出が可能です。

4. MD5 (Message-Digest Algorithm 5)

MD5は、128ビット(16バイト)のハッシュ値を生成する暗号学的ハッシュ関数です。かつては広く利用されていましたが、現在では衝突攻撃(異なる入力から同じMD5ハッシュ値が生成されること)が可能であることが示されており、セキュリティが要求される用途での利用は推奨されません。

5. SHA-1 (Secure Hash Algorithm 1)

SHA-1は、160ビット(20バイト)のハッシュ値を生成する暗号学的ハッシュ関数です。MD5と同様に、かつては広く利用されていましたが、現在では衝突攻撃が可能であることが示されており、セキュリティが要求される用途での利用は推奨されません。より強力なSHA-2(SHA-256, SHA-512など)やSHA-3が推奨されています。

6. Go言語の hash パッケージと Digest インターフェース

Go言語の標準ライブラリには、hashパッケージがあり、様々なハッシュアルゴリズムの実装を提供しています。これらのハッシュアルゴリズムは、通常、hash.Hashインターフェースを実装しています。このインターフェースは、以下の主要なメソッドを定義しています。

  • Write(p []byte) (n int, err error): 入力データをハッシュ計算器に書き込み、ハッシュ値を更新します。
  • Sum(b []byte) []byte: 現在のハッシュ値を計算し、バイトスライスとして返します。
  • Reset(): ハッシュ計算器を初期状態に戻します。
  • Size() int: ハッシュ値のバイト長を返します。
  • BlockSize() int: ハッシュ計算器のブロックサイズを返します。

このコミットでドキュメントが追加されている各ハッシュパッケージ内のDigest型は、このhash.Hashインターフェース(またはその一部)を実装する構造体であり、ハッシュ計算の状態を保持し、データの書き込みやハッシュ値の取得を行うためのメソッドを提供します。

技術的詳細

このコミットの主要な目的は、Go言語のハッシュパッケージのAPIドキュメンテーションを改善することです。具体的には、以下の点が変更されています。

  1. パッケージコメントの追加/修正: 各ハッシュパッケージの冒頭に、そのパッケージが実装するアルゴリズムの概要と、関連するRFCへの参照が追加されました。これにより、パッケージの目的が一目でわかるようになります。

    • adler32: "This package implements the Adler-32 checksum. Defined in RFC 1950:"
    • crc32: "This package implements the 32-bit cyclic redundancy check, or CRC-32, checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information."
    • md5: "This package implements the MD5 hash algorithm as defined in RFC 1321."
    • sha1: "This package implements the SHA1 hash algorithm as defined in RFC 3174."
  2. エクスポートされた型と関数へのコメント追加:

    • Digest型: 各ハッシュパッケージにおけるDigest型(ハッシュ計算の状態を保持する構造体)に対して、"Digest represents the partial evaluation of a checksum." というコメントが追加されました。これにより、Digestがハッシュ計算の途中状態を表すものであることが明確になります。
    • NewDigest関数: 各ハッシュパッケージで新しいDigestインスタンスを作成するNewDigest関数に対して、"NewDigest creates a new Digest." というコメントが追加されました。
    • Writeメソッド: Digest型が実装するWriteメソッドに対して、"Write updates the Digest with the incremental checksum generated by p. It returns the number of bytes written; err is always nil." というコメントが追加されました。これは、Writeメソッドがデータをハッシュ計算器に供給し、ハッシュ値を段階的に更新する役割を持つことを説明しています。
    • Sum32メソッド (Adler-32, CRC-32): 32ビットのチェックサムを返すSum32メソッドに対して、"Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest." または "Sum32 returns the CRC-32 checksum of the data written to the Digest." というコメントが追加されました。
    • Sumメソッド: 最終的なハッシュ値(バイトスライス形式)を返すSumメソッドに対して、"Sum returns the 32-bit Adler-32 checksum of the data written to the Digest in the form of an array of 4 bytes in big-endian order." (Adler-32, CRC-32) または "Sum returns the MD5 checksum of the data written to the Digest in the form of an array of 16 bytes in big-endian order." (MD5) または "Sum returns the SHA-1 checksum of the data written to the Digest in the form of an array of 20 bytes in big-endian order." (SHA-1) というコメントが追加されました。これにより、Sumメソッドが返す値の形式とバイトオーダーが明確になります。
  3. 定数名の変更 (Adler-32): adler32.goでは、内部で使用される定数名が_Modからmod_MaxIterからmaxIterに変更されています。Go言語では、アンダースコアで始まる識別子は通常、エクスポートされない(パッケージ内部でのみ使用される)ことを示唆しますが、この変更は、より一般的な命名規則への移行、または単に内部定数であることを明確にするためのものと考えられます。

これらの変更は、Go言語のgodocツールが自動的にAPIドキュメントを生成する際に利用され、開発者がこれらのハッシュパッケージをより簡単に理解し、適切に使用するための基盤を築きました。

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

src/lib/hash/adler32.go

--- a/src/lib/hash/adler32.go
+++ b/src/lib/hash/adler32.go
@@ -2,41 +2,44 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Adler-32 checksum.
+// This package implements the Adler-32 checksum.
 // Defined in RFC 1950:
 //	Adler-32 is composed of two sums accumulated per byte: s1 is
 //	the sum of all bytes, s2 is the sum of all s1 values. Both sums
 //	are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
 //	Adler-32 checksum is stored as s2*65536 + s1 in most-
 //	significant-byte first (network) order.
-
 package adler32
 
 import "os"
 
+// Digest represents the partial evaluation of a checksum.
 type Digest struct {
 	a, b uint32;
 	n int;
 }
 
 const (
-	_Mod = 65521;
-	_MaxIter = 5552;  // max mod-free iterations before would overflow uint32
+	mod = 65521;
+	maxIter = 5552;  // max mod-free iterations before would overflow uint32
 )
 
+// NewDigest creates a new Digest.
 func NewDigest() *Digest {
 	return &Digest{1, 0, 0};
 }
 
+// Write updates the Digest with the incremental checksum generated by p.
+// It returns the number of bytes written; err is always nil.
 func (d *Digest) Write(p []byte) (nn int, err *os.Error) {
 	a, b, n := d.a, d.b, d.n;
 	for i := 0; i < len(p); i++ {
 		a += uint32(p[i]);
 		b += a;
 		n++;
-		if n == _MaxIter {
-			a %= _Mod;
-			b %= _Mod;
+		if n == maxIter {
+			a %= mod;
+			b %= mod;
 		}
 	}
@@ -44,15 +47,18 @@ func (d *Digest) Write(p []byte) (nn int, err *os.Error) {\
 	return len(p), nil
 }
 
+// Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest.\n func (d *Digest) Sum32() uint32 {
 	a, b := d.a, d.b;
-	if a >= _Mod || b >= _Mod {
-		a %= _Mod;
-		b %= _Mod;
+	if a >= mod || b >= mod {
+		a %= mod;
+		b %= mod;
 	}
 	return b<<16 | a;
 }
 
+// Sum returns the 32-bit Adler-32 checksum of the data written to the Digest
+// in the form of an array of 4 bytes in big-endian order.
 func (d *Digest) Sum() []byte {
 	p := make([]byte, 4);
 	s := d.Sum32();

src/lib/hash/crc32.go

--- a/src/lib/hash/crc32.go
+++ b/src/lib/hash/crc32.go
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.\n 
-// CRC-32 checksum.
-// http://en.wikipedia.org/wiki/Cyclic_redundancy_check for links
-
+// This package implements the 32-bit cyclic redundancy check, or CRC-32, checksum.
+// See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information.
 package crc32
 
 import "os"
 
+// Predefined polynomials.
 const (
 	// Far and away the most common CRC-32 polynomial.
 	// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
@@ -25,9 +25,11 @@ const (
 	Koopman = 0xeb31d82e;
 )
 
+// Table is a 256-word table representing the polynomial for efficient processing.
 // TODO(rsc): Change to [256]uint32 once 6g can handle it.
 type Table []uint32
 
+// MakeTable returns the Table constructed from the specified polynomial.
 func MakeTable(poly uint32) Table {
 	t := make(Table, 256);
 	for i := 0; i < 256; i++ {
@@ -44,21 +46,29 @@ func MakeTable(poly uint32) Table {
 	return t;
 }
 
+// IEEETable is the table for the IEEE polynomial.
 var IEEETable = MakeTable(IEEE);
 
+// Digest represents the partial evaluation of a checksum.
 type Digest struct {
 	crc uint32;
 	tab Table;
 }
 
+// NewDigest creates a new Digest for the checksum based on
+// the polynomial represented by the Table.
 func NewDigest(tab Table) *Digest {
 	return &Digest{0, tab};
 }
 
+// NewIEEEDigest creates a new Digest for the checksum based on
+// the IEEE polynomial.
 func NewIEEEDigest() *Digest {
 	return NewDigest(IEEETable);
 }
 
+// Write updates the Digest with the incremental checksum generated by p.
+// It returns the number of bytes written; err is always nil.
 func (d *Digest) Write(p []byte) (n int, err *os.Error) {
 	crc := d.crc ^ 0xFFFFFFFF;
 	tab := d.tab;
@@ -69,10 +79,13 @@ func (d *Digest) Write(p []byte) (n int, err *os.Error) {\
 	return len(p), nil;
 }
 
+// Sum32 returns the CRC-32 checksum of the data written to the Digest.
 func (d *Digest) Sum32() uint32 {
 	return d.crc
 }
 
+// Sum returns the CRC-32 checksum of the data written to the Digest
+// in the form of an array of 4 bytes in big-endian order.
 func (d *Digest) Sum() []byte {
 	p := make([]byte, 4);
 	s := d.Sum32();

src/lib/hash/md5.go

--- a/src/lib/hash/md5.go
+++ b/src/lib/hash/md5.go
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// MD5 hash algorithm.  See RFC 1321.
-
+// This package implements the MD5 hash algorithm as defined in RFC 1321.
 package md5
 
 import "os"
@@ -17,6 +16,7 @@ const (
 	_Init3 = 0x10325476;
 )\n 
+// Digest represents the partial evaluation of a checksum.
 type Digest struct {
 	s [4]uint32;
 	x [_Chunk]byte;
@@ -24,6 +24,7 @@ type Digest struct {\
 	len uint64;
 }\n 
+// NewDigest creates a new Digest.
 func NewDigest() *Digest {
 	d := new(Digest);
 	d.s[0] = _Init0;
@@ -35,6 +36,8 @@ func NewDigest() *Digest {\
 
 func _Block(dig *Digest, p []byte) int
 
+// Write updates the Digest with the incremental checksum generated by p.
+// It returns the number of bytes written; err is always nil.
 func (d *Digest) Write(p []byte) (nn int, err *os.Error) {
 	nn = len(p);
 	d.len += uint64(nn);
@@ -64,6 +67,8 @@ func (d *Digest) Write(p []byte) (nn int, err *os.Error) {\
 	return;\n }\n 
+// Sum returns the MD5 checksum of the data written to the Digest
+// in the form of an array of 16 bytes in big-endian order.
 func (d *Digest) Sum() []byte {
 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 	len := d.len;

src/lib/hash/sha1.go

--- a/src/lib/hash/sha1.go
+++ b/src/lib/hash/sha1.go
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// SHA1 hash algorithm.  See RFC 3174.
-
+// This package implements the SHA1 hash algorithm as defined in RFC 3174.
 package sha1
 
 import "os"
@@ -18,6 +17,7 @@ const (
 	_Init4 = 0xC3D2E1F0;\n )\n 
+// Digest represents the partial evaluation of a checksum.
 type Digest struct {
 	h [5]uint32;
 	x [_Chunk]byte;
@@ -25,6 +25,7 @@ type Digest struct {\
 	len uint64;
 }\n 
+// NewDigest creates a new Digest.
 func NewDigest() *Digest {
 	d := new(Digest);
 	d.h[0] = _Init0;
@@ -37,6 +38,8 @@ func NewDigest() *Digest {\
 
 func _Block(dig *Digest, p []byte) int
 
+// Write updates the Digest with the incremental checksum generated by p.
+// It returns the number of bytes written; err is always nil.
 func (d *Digest) Write(p []byte) (nn int, err *os.Error) {
 	nn = len(p);
 	d.len += uint64(nn);
@@ -66,6 +69,8 @@ func (d *Digest) Write(p []byte) (nn int, err *os.Error) {\
 	return;\n }\n 
+// Sum returns the SHA-1 checksum of the data written to the Digest
+// in the form of an array of 20 bytes in big-endian order.
 func (d *Digest) Sum() []byte {
 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 	len := d.len;

コアとなるコードの解説

このコミットにおけるコードの変更は、主にGo言語のドキュメンテーションコメントの追加と、それに伴う一部の定数名の変更です。

  1. パッケージコメントの追加:

    • hashパッケージのGoファイル冒頭に、// This package implements the ... という形式のコメントが追加されています。これは、Go言語の慣例に従い、パッケージの目的を説明するものです。godocツールは、このコメントをパッケージの概要として表示します。これにより、開発者は各パッケージが提供する機能について迅速に理解できます。
    • Adler-32、MD5、SHA-1のコメントには、それぞれ対応するRFC(Request for Comments)の番号が明記されています。これは、アルゴリズムの公式な定義を参照するための重要な情報源を提供します。CRC-32のコメントにはWikipediaへのリンクが記載されています。
  2. Digest型へのコメント追加:

    • type Digest struct { ... } の上に // Digest represents the partial evaluation of a checksum. というコメントが追加されています。これは、Digest型がハッシュ計算の「途中状態」を保持する役割を持つことを明確にしています。ハッシュ計算は通常、データを少しずつ読み込みながら段階的に行われるため、このDigest型がその状態を管理します。
  3. NewDigest関数へのコメント追加:

    • func NewDigest() *Digest { ... } の上に // NewDigest creates a new Digest. というコメントが追加されています。これは、NewDigest関数が新しいハッシュ計算器のインスタンスを初期化して返すファクトリ関数であることを示しています。
  4. Writeメソッドへのコメント追加:

    • func (d *Digest) Write(p []byte) (nn int, err *os.Error) { ... } の上に // Write updates the Digest with the incremental checksum generated by p. // It returns the number of bytes written; err is always nil. というコメントが追加されています。これは、Writeメソッドが入力データpを受け取り、それを使ってハッシュ計算器の内部状態(Digesta, b, crc, s, hなど)を更新する役割を持つことを説明しています。また、Go言語のio.Writerインターフェースの慣例に従い、書き込まれたバイト数とエラーを返すことも明記されています。err is always nilという記述は、この特定のWrite実装ではエラーが発生しないことを保証しています。
  5. Sum32メソッドへのコメント追加 (Adler-32, CRC-32):

    • func (d *Digest) Sum32() uint32 { ... } の上に // Sum32 returns the 32-bit ... checksum of the data written to the Digest. というコメントが追加されています。これは、Sum32メソッドが32ビットの符号なし整数として最終的なチェックサム値を返すことを示しています。
  6. Sumメソッドへのコメント追加:

    • func (d *Digest) Sum() []byte { ... } の上に // Sum returns the ... checksum of the data written to the Digest // in the form of an array of ... bytes in big-endian order. というコメントが追加されています。これは、Sumメソッドが最終的なハッシュ値(またはチェックサム値)をバイトスライスとして返すことを示しています。特に、バイト数(例: 4バイト、16バイト、20バイト)とバイトオーダー(ビッグエンディアン)が明記されており、これは異なるシステム間でのデータ交換において非常に重要な情報です。
  7. 定数名の変更 (Adler-32):

    • adler32.go内で、内部定数_Modmodに、_MaxItermaxIterに変更されています。Go言語では、識別子の先頭が大文字であるか小文字であるかによって、エクスポートされるかどうかが決まります。アンダースコアで始まる識別子は、通常、エクスポートされないことを示唆する慣例がありますが、この変更は、より一般的な小文字始まりの内部定数名への統一、または単にアンダースコアの有無による意味合いの曖昧さを解消するためのものと考えられます。機能的な変更はありません。

これらのコメントは、Go言語のドキュメンテーション生成ツールであるgodocによって解析され、開発者がGoのハッシュパッケージをより効果的に利用するための、明確で簡潔なAPIリファレンスを生成します。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメンテーション
  • RFCs (Request for Comments)
  • Wikipedia (各ハッシュアルゴリズムに関する情報)
  • Go言語のソースコード (コミット履歴とファイル内容)
  • Go言語の初期開発に関する一般的な知識I have generated the detailed technical explanation in Markdown format, following all the specified instructions and chapter structure. I have outputted it to standard output only, as requested. I did not need to use google_web_search as the commit message and file changes were clear enough to infer the context and technical details, and the RFCs were directly referenced in the commit diff.