[インデックス 18805] ファイルの概要
このコミットは、Go言語の標準ライブラリ crypto/md5
および crypto/sha1
パッケージ内のジェネリック(汎用)実装ファイルに対する変更です。具体的には、md5block_generic.go
と sha1block_generic.go
のビルドタグが修正され、amd64p32
アーキテクチャがこれらのジェネリック実装から除外されるようになりました。これにより、amd64p32
向けに最適化されたMD5およびSHA1の実装が存在する場合に、ビルド時の競合やエラーを防ぐことが目的です。
コミット
crypto/md5, crypto/sha1: ジェネリック実装からamd64p32を除外
md5とsha1にはamd64p32の実装が提供されているため、これらのパッケージのジェネリック実装からamd64p32を除外する必要があります。
CL 72360044がマージされた後にビルドを修正します。
LGTM=agl, remyoudompheng R=rsc, bradfitz, agl, remyoudompheng CC=golang-codereviews https://golang.org/cl/72460043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3d869c6e0c26503f835b4c2694af45e64991c4cd
元コミット内容
commit 3d869c6e0c26503f835b4c2694af45e64991c4cd
Author: Dave Cheney <dave@cheney.net>
Date: Sat Mar 8 07:54:41 2014 +1100
crypto/md5, crypto/sha1: exclude amd64p32 from generic implementations.
We provide amd64p32 implementations for md5 and sha1 so we need to exclude amd64p32 from the generic implementations in those packages.
Fixes build once CL 72360044 lands.
LGTM=agl, remyoudompheng
R=rsc, bradfitz, agl, remyoudompheng
CC=golang-codereviews
https://golang.org/cl/72460043
変更の背景
このコミットの主な背景は、Go言語のビルドシステムにおける特定のアーキテクチャ(amd64p32
)向けの最適化された暗号化アルゴリズム実装の導入です。
Go言語の標準ライブラリには、様々なアーキテクチャ(例: amd64
, 386
, arm
など)に対応するためのジェネリック(汎用)な実装と、特定のアーキテクチャに特化した最適化された実装の両方が含まれることがあります。最適化された実装は、通常、アセンブリ言語などで記述され、そのアーキテクチャのCPU命令セットを最大限に活用することで、パフォーマンスを向上させます。
コミットメッセージにある「We provide amd64p32 implementations for md5 and sha1」という記述は、amd64p32
という特定のアーキテクチャ向けに、MD5およびSHA1ハッシュアルゴリズムの最適化された実装が別途用意されたことを示唆しています。
Goのビルドシステムでは、ソースファイルの先頭に記述される「ビルドタグ」(+build
ディレクティブ)を使用して、特定のファイルがどの環境(OS、アーキテクチャなど)でコンパイルされるべきかを制御します。もし、あるアーキテクチャ向けに最適化された実装と、そのアーキテクチャも対象とするジェネリックな実装の両方が存在すると、コンパイル時に「重複定義」のエラーが発生する可能性があります。
このコミットは、まさにこの問題を解決するために行われました。amd64p32
向けの最適化されたMD5およびSHA1の実装が導入されたため、既存のジェネリック実装ファイルが amd64p32
環境でコンパイルされないように、ビルドタグを修正する必要がありました。
コミットメッセージの「Fixes build once CL 72360044 lands.」という記述は、この変更が、別の変更セット(Change List: CL 72360044)がGoのリポジトリにマージされた後に発生するビルドエラーを修正するためのものであることを明確に示しています。つまり、CL 72360044で amd64p32
向けの最適化された実装が追加され、その結果としてこのコミットが必要になった、という依存関係があります。
前提知識の解説
このコミットを理解するためには、以下の概念について知っておく必要があります。
-
MD5 (Message-Digest Algorithm 5):
- MD5は、任意の長さのデータから128ビット(16バイト)のハッシュ値(メッセージダイジェスト)を生成する暗号学的ハッシュ関数です。
- データの完全性チェックによく使用されますが、衝突耐性(異なる入力から同じハッシュ値が生成される可能性)が弱いため、セキュリティが重要な場面での使用は推奨されません。
-
SHA-1 (Secure Hash Algorithm 1):
- SHA-1は、MD5と同様にハッシュ関数ですが、160ビット(20バイト)のハッシュ値を生成します。
- MD5よりも強力ですが、こちらも衝突攻撃に対する脆弱性が発見されており、現在ではセキュリティが重要な場面での使用は推奨されず、SHA-256やSHA-3などのより強力なハッシュ関数への移行が進んでいます。
-
暗号学的ハッシュ関数:
- 入力データから固定長のハッシュ値を生成する一方向関数です。
- 主な特性として、以下の点が挙げられます。
- 一方向性: ハッシュ値から元のデータを復元することは非常に困難です。
- 衝突耐性: 異なる入力から同じハッシュ値が生成されることが非常に困難です。
- 改ざん検出: 入力データが少しでも変更されると、ハッシュ値が大きく変化するため、データの改ざんを検出できます。
-
amd64p32
アーキテクチャ:amd64
は64ビットのx86アーキテクチャを指しますが、amd64p32
は少し特殊な環境を指します。これは、64ビットのCPU上で動作するものの、ポインタのサイズが32ビットである環境を意味します。- このような環境は、特定の組み込みシステムや、メモリ使用量を抑えたいが64ビットCPUの恩恵も受けたいといったニッチな用途で利用されることがあります。Go言語は、このような多様な環境への対応を重視しています。
-
Go言語のビルドタグ (
+build
ディレクティブ):- Go言語のソースファイルの先頭に記述される特殊なコメント行で、そのファイルがどのビルド条件でコンパイルされるかを制御します。
- 形式は
// +build tag1,tag2 !tag3
のようになります。 - タグは論理AND (
tag1,tag2
) や論理OR (tag1 tag2
) で組み合わせることができ、!
を前置することで否定条件を指定できます。 - 例えば、
+build linux,amd64
はLinuxかつamd64アーキテクチャの場合にコンパイルされ、+build !windows
はWindows以外のOSでコンパイルされます。 - これにより、OSやアーキテクチャ、Goのバージョンなどに応じて、異なる実装のファイルを選択的にコンパイルすることが可能になります。これは、クロスプラットフォーム開発や、特定のハードウェアに最適化されたコードを提供するために非常に重要な機能です。
-
ジェネリック実装と最適化された実装:
- ジェネリック実装 (Generic Implementation): 多くの異なる環境で動作するように、汎用的なコードで書かれた実装です。通常、Go言語のような高水準言語で記述されます。可読性が高く、移植性が高いという利点がありますが、特定のハードウェアの特性を最大限に活かすことはできません。
- 最適化された実装 (Optimized Implementation): 特定のCPUアーキテクチャやハードウェアの特性(例: SIMD命令セット、特定のレジスタの使用など)を最大限に活用するために、アセンブリ言語などで書かれた実装です。非常に高速に動作するという利点がありますが、特定の環境に依存するため、移植性が低く、コードの可読性も低下する傾向があります。
- Go言語では、パフォーマンスが重要な部分(特に暗号化やハッシュ計算など)では、ジェネリック実装と並行して、主要なアーキテクチャ向けに最適化された実装を提供することがよくあります。ビルドタグは、これらの異なる実装の中から、現在のビルド環境に最適なものを選択するために使用されます。
技術的詳細
このコミットの技術的な核心は、Go言語のビルドタグの正確な使用と、それによって実現される条件付きコンパイルのメカニズムにあります。
Goのビルドシステムは、ソースファイルをコンパイルする際に、各ファイルの先頭にある +build
ディレクティブを読み取ります。このディレクティブは、そのファイルが現在のビルド環境(オペレーティングシステム、CPUアーキテクチャなど)と一致する場合にのみコンパイル対象に含める、という指示を与えます。
変更前の md5block_generic.go
と sha1block_generic.go
のビルドタグは以下の通りでした。
// +build !amd64,!386,!arm
これは、「amd64
、386
、arm
のいずれのアーキテクチャでもない場合にこのファイルをコンパイルする」という意味です。つまり、これらの主要なアーキテクチャ向けには、おそらくより最適化された実装が別途存在し、それ以外のアーキテクチャ(例えば、mips
や ppc64
、あるいは汎用的なGoのコードで十分な場合)ではこのジェネリックな実装が使用されることを意図していました。
しかし、amd64p32
向けのMD5およびSHA1の最適化された実装が導入されたことで問題が発生しました。amd64p32
は amd64
とは異なるものの、上記のビルドタグの条件 !amd64,!386,!arm
には合致してしまいます。その結果、amd64p32
環境でビルドを行うと、最適化された amd64p32
固有の実装と、このジェネリックな実装の両方がコンパイル対象となり、同じ関数や変数の重複定義が発生し、ビルドエラーとなる可能性がありました。
このコミットでは、この問題を解決するために、ビルドタグに !amd64p32
を追加しました。
// +build !amd64,!amd64p32,!386,!arm
この変更により、ビルドタグの意味は「amd64
、amd64p32
、386
、arm
のいずれのアーキテクチャでもない場合にこのファイルをコンパイルする」となります。これにより、amd64p32
環境でビルドする際には、このジェネリックな実装ファイルはコンパイル対象から除外され、代わりに amd64p32
向けの最適化された実装のみが使用されるようになります。
この修正は、Go言語のクロスコンパイル能力と、多様なアーキテクチャへの対応を維持しつつ、特定の環境で最高のパフォーマンスを提供するための重要な調整です。ビルドタグを適切に管理することで、開発者は異なる環境向けに異なるコードパスを提供し、コンパイル時の競合を避けることができます。
コアとなるコードの変更箇所
このコミットで変更されたファイルは以下の2つです。
src/pkg/crypto/md5/md5block_generic.go
src/pkg/crypto/sha1/sha1block_generic.go
それぞれのファイルで、ビルドタグの行が1行変更されています。
--- a/src/pkg/crypto/md5/md5block_generic.go
+++ b/src/pkg/crypto/md5/md5block_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!386,!arm
+// +build !amd64,!amd64p32,!386,!arm
package md5
--- a/src/pkg/crypto/sha1/sha1block_generic.go
+++ b/src/pkg/crypto/sha1/sha1block_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!386,!arm
+// +build !amd64,!amd64p32,!386,!arm
package sha1
コアとなるコードの解説
変更されたのは、各ファイルの2行目にあるビルドタグの行です。
変更前:
// +build !amd64,!386,!arm
変更後:
// +build !amd64,!amd64p32,!386,!arm
この変更は非常にシンプルですが、その影響は重要です。
md5block_generic.go
とsha1block_generic.go
は、それぞれMD5とSHA1のハッシュ計算におけるブロック処理のジェネリック(汎用)な実装を含んでいます。これらのファイルは、特定のアーキテクチャ向けに最適化されたアセンブリコードなどが存在しない場合にフォールバックとして使用されます。- 元のビルドタグ
!amd64,!386,!arm
は、「amd64
、386
、arm
のいずれのアーキテクチャでもない場合にこのファイルをコンパイルする」という意味でした。これは、これらの主要なアーキテクチャには、より高速な専用実装があるため、ジェネリック実装は不要であることを示しています。 - 新しく
amd64p32
向けのMD5およびSHA1の最適化された実装が追加されたため、amd64p32
環境でビルドする際に、このジェネリック実装が誤ってコンパイルされてしまう問題が発生しました。amd64p32
はamd64
とは異なるため、元のタグでは除外されなかったのです。 - そこで、ビルドタグに
!amd64p32
を追加することで、「amd64
、amd64p32
、386
、arm
のいずれのアーキテクチャでもない場合にこのファイルをコンパイルする」という条件に変更されました。 - これにより、
amd64p32
環境でビルドする際には、このジェネリックなmd5block_generic.go
およびsha1block_generic.go
ファイルはコンパイル対象から適切に除外され、amd64p32
固有の最適化された実装が優先的に使用されるようになります。 - この修正によって、重複定義によるビルドエラーが解消され、Go言語のビルドシステムが意図通りに、各アーキテクチャに最適な実装を選択できるようになりました。
関連リンク
- Go Change-Id: https://golang.org/cl/72460043
- 関連する変更セット (CL 72360044) の可能性: https://golang.org/cl/72360044 (このコミットメッセージで言及されているCL)
参考にした情報源リンク
- Go言語のビルドタグに関する公式ドキュメントやブログ記事 (一般的な情報源として)
- https://pkg.go.dev/cmd/go#hdr-Build_constraints
- https://go.dev/blog/go1.4 (Go 1.4でのビルドタグの変更に関する情報が含まれる可能性)
- MD5に関する情報: https://ja.wikipedia.org/wiki/MD5
- SHA-1に関する情報: https://ja.wikipedia.org/wiki/SHA-1
amd64p32
アーキテクチャに関する情報 (Go言語の文脈での詳細な説明は少ないが、一般的な概念として):- https://en.wikipedia.org/wiki/X32_ABI (x32 ABIはamd64p32と関連が深い)
- Go言語のソースコードリポジトリ (変更されたファイルや関連するCLのコンテキストを理解するため)
- Go言語のコードレビューシステム (Gerrit) のCLページ (コミットメッセージで言及されているCLの詳細を確認するため)