[インデックス 17028] ファイルの概要
このコミットは、Go言語の標準ライブラリ crypto/cipher
パッケージに Galois/Counter Mode (GCM) を追加するものです。GCMは、認証付き暗号 (Authenticated Encryption with Associated Data, AEAD) モードの一種であり、データの機密性、完全性、および認証性を提供します。特にAES(Advanced Encryption Standard)と組み合わせて使用されることが一般的です。
コミット
commit 20a2b960898a37e646bf76dcf0e3fd067a387c5f
Author: Adam Langley <agl@golang.org>
Date: Mon Aug 5 14:31:58 2013 -0400
crypto/cipher: add GCM mode.
GCM is Galois Counter Mode, an authenticated encryption mode that is,
nearly always, used with AES.
R=rsc
CC=golang-dev
https://golang.org/cl/12375043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/20a2b960898a37e646bf76dcf0e3fd067a387c5f
元コミット内容
このコミットは、Go言語の crypto/cipher
パッケージにGCM (Galois Counter Mode) を追加することを目的としています。GCMは、認証付き暗号化モードであり、ほとんどの場合AESと組み合わせて使用されます。これにより、データの暗号化だけでなく、改ざん検出と認証も同時に行えるようになります。
変更の背景
GCMは、現代の暗号化において非常に重要なモードです。従来の暗号化モード(例: CBCモード)では、データの機密性(暗号化)は提供されますが、データの完全性(改ざんされていないこと)や認証性(送信者が正当であること)は別途MAC(Message Authentication Code)などのメカニズムで保証する必要がありました。これは「Encrypt-then-MAC」などの構成を必要とし、実装が複雑になりがちで、誤った実装はセキュリティ上の脆弱性につながる可能性がありました。
GCMは、認証付き暗号 (AEAD) の一種として、暗号化と認証を単一のアルゴリズムで効率的に提供します。これにより、実装の複雑さが軽減され、より安全な暗号化通信が実現できます。特にTLS/SSLなどのプロトコルでは、GCMのようなAEADモードが推奨されており、そのパフォーマンスとセキュリティ特性から広く採用されています。Go言語の標準ライブラリにGCMが追加されることで、Goアプリケーションで安全かつ効率的な認証付き暗号化を容易に利用できるようになることが、この変更の背景にあります。
前提知識の解説
認証付き暗号 (Authenticated Encryption with Associated Data, AEAD)
AEADは、データの機密性(暗号化)、完全性(改ざん検出)、および認証性(送信元認証)を同時に提供する暗号化方式です。さらに、"Associated Data" (追加データ、AD) と呼ばれる、暗号化されないが認証の対象となるデータを含めることができます。これは、ヘッダー情報など、暗号化する必要はないが、改ざんされると問題が生じるデータに利用されます。
Galois/Counter Mode (GCM)
GCMは、NISTによって標準化された認証付き暗号モードです。カウンタモード (CTR) と Galois Field Multiplication (GF(2^128) 上の乗算) を組み合わせたものです。
- カウンタモード (CTR): ブロック暗号をストリーム暗号のように動作させるモードです。各ブロックは、ユニークなカウンタ値と鍵を使って暗号化され、その結果と平文がXORされます。並列処理が可能で高速です。
- GHASH: GCMの認証部分を担うハッシュ関数です。Galois Field GF(2^128) 上での乗算に基づいています。暗号文と追加データを処理し、認証タグを生成します。
ノンス (Nonce)
Nonce (Number used once) は、暗号化操作ごとに一度だけ使用されるランダムまたは擬似ランダムな値です。GCMでは、同じ鍵で複数のメッセージを暗号化する際に、各メッセージに異なるノンスを使用することが極めて重要です。ノンスが重複すると、セキュリティ上の重大な脆弱性(例: 認証タグの偽造)につながります。
関連データ (Associated Data, AD)
前述の通り、暗号化はされないが認証の対象となるデータです。例えば、ネットワークプロトコルのヘッダー情報などがこれに該当します。
ガロア体 (Galois Field) GF(2^128)
GCMの認証部分であるGHASHは、有限体(ガロア体)GF(2^128) 上での演算に基づいています。これは、ビット列を多項式と見なし、特定の既約多項式を法として演算を行う数学的な構造です。GF(2^128) は、128ビットのブロックを扱うのに適しており、高速なハードウェア実装が可能です。
定数時間操作 (Constant-Time Operations)
暗号化アルゴリズムの実装において、処理時間が入力データ(特に秘密鍵や平文)に依存しないようにする技術です。処理時間がデータに依存すると、サイドチャネル攻撃(例: タイミング攻撃)によって秘密情報が漏洩する可能性があります。crypto/subtle
パッケージは、このような定数時間操作を支援する関数を提供します。
技術的詳細
Go言語の crypto/cipher
パッケージに追加されたGCM実装は、以下の主要なコンポーネントで構成されています。
-
AEAD
インターフェース: GCMは、AEAD
インターフェースを実装します。このインターフェースは、認証付き暗号の標準的なAPIを定義しており、NonceSize()
、Overhead()
、Seal()
(暗号化と認証)、Open()
(復号と認証)の各メソッドを含みます。 -
gcm
構造体: GCMモードの内部状態を保持する構造体です。cipher Block
: 基盤となるブロック暗号(例: AES)のインスタンス。productTable [16]gcmFieldElement
: GHASHの計算を高速化するための事前計算されたテーブル。GCMの鍵H
の16倍(0から15倍)の値を保持します。これらの値は、GF(2^128) 上の要素であり、ビット順序が逆転して格納されるという特殊な形式で扱われます。
-
gcmFieldElement
構造体: GF(2^128) 上の要素を表す構造体です。low
とhigh
の2つのuint64
フィールドで128ビットの値を表現します。GCM標準に合わせて、ビットが逆順に格納されるという特徴があります。 -
NewGCM
関数:Block
インターフェースを実装するブロック暗号(例: AES)を受け取り、新しいAEAD
インターフェース(gcm
のインスタンス)を返します。この関数内で、GHASHの計算に必要なproductTable
が初期化されます。productTable
の生成では、GF(2^128) 上での倍算 (gcmDouble
) と加算 (gcmAdd
) が使用されます。 -
Seal
メソッド: 平文 (plaintext
) と追加データ (data
) を暗号化・認証し、結果をdst
に追記します。- ノンス (
nonce
) とカウンタ値から初期カウンタブロックを生成します。 - 初期カウンタブロックを基に、ブロック暗号で
tagMask
を生成します。 - カウンタモードで平文を暗号化します (
counterCrypt
)。 - GHASHを計算し、認証タグを生成します (
auth
)。このタグはtagMask
とXORされます。 - 暗号文の末尾に認証タグを付加します。
- ノンス (
-
Open
メソッド: 暗号文 (ciphertext
) と追加データ (data
) を復号・認証し、成功すれば平文をdst
に追記します。- 暗号文から認証タグを分離します。
Seal
と同様に、ノンスとカウンタ値から初期カウンタブロックを生成し、tagMask
を生成します。- GHASHを計算し、期待される認証タグを生成します (
auth
)。 - 生成された認証タグと受信した認証タグを
subtle.ConstantTimeCompare
を用いて比較します。これにより、タイミング攻撃を防ぎます。 - 認証が成功した場合のみ、カウンタモードで暗号文を復号し (
counterCrypt
)、平文を返します。
-
GHASHの内部演算:
gcmAdd
: GF(2^128) 上の加算(ビットごとのXOR)。gcmDouble
: GF(2^128) 上の倍算。ビット順序が逆転しているため、実際には右シフトと既約多項式による剰余演算(0xe100000000000000
とのXOR)を行います。mul
: GHASHのコアとなるGF(2^128) 上の乗算。productTable
を利用して高速化されています。updateBlocks
/update
: GHASHの計算中に、入力データ(追加データや暗号文)を処理し、gcmFieldElement
の状態を更新します。
-
crypto/subtle
の利用:Open
メソッドでの認証タグの比較にsubtle.ConstantTimeCompare
が使用されています。これは、比較処理の実行時間が入力データに依存しないようにすることで、タイミング攻撃による情報漏洩を防ぐための重要なセキュリティ対策です。
コアとなるコードの変更箇所
このコミットで追加された主要なファイルと変更点は以下の通りです。
src/pkg/crypto/cipher/gcm.go
: GCMモードの主要な実装が含まれる新規ファイル。src/pkg/crypto/cipher/gcm_test.go
: GCMモードのテストケースが含まれる新規ファイル。NISTのテストベクトルを使用して、実装の正確性を検証しています。src/pkg/go/build/deps_test.go
: Goのビルドシステムにおけるパッケージ依存関係のテストファイル。crypto/cipher
がcrypto/subtle
に依存するようになった変更が反映されています。
コアとなるコードの解説
src/pkg/crypto/cipher/gcm.go
このファイルは、GCMモードのGo言語での実装を提供します。
-
AEAD
インターフェースの定義:type AEAD interface { NonceSize() int Overhead() int Seal(dst, nonce, plaintext, data []byte) []byte Open(dst, nonce, ciphertext, data []byte) ([]byte, error) }
認証付き暗号の標準的なインターフェースを定義しています。
-
gcmFieldElement
構造体:type gcmFieldElement struct { low, high uint64 }
GF(2^128) の要素を表現します。ビット順序が逆転して格納される点が特徴です。
-
gcm
構造体:type gcm struct { cipher Block productTable [16]gcmFieldElement }
GCMインスタンスの内部状態を保持します。
cipher
は基盤となるブロック暗号、productTable
はGHASH計算用の事前計算テーブルです。 -
NewGCM
関数:func NewGCM(cipher Block) (AEAD, error) { // ... // productTableの初期化ロジック // ... return g, nil }
GCMインスタンスを生成し、GHASHの計算に必要な
productTable
を初期化します。 -
Seal
メソッド:func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { // ... // カウンタモードでの暗号化 (g.counterCrypt) // GHASH計算と認証タグ生成 (g.auth) // ... return ret }
平文を暗号化し、追加データと共に認証タグを生成して暗号文に付加します。
-
Open
メソッド:func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { // ... // GHASH計算と期待される認証タグの生成 (g.auth) // 定数時間比較 (subtle.ConstantTimeCompare) // カウンタモードでの復号 (g.counterCrypt) // ... return ret, nil }
暗号文を復号し、認証タグを検証します。認証に失敗した場合はエラーを返します。
-
ヘルパー関数群:
reverseBits
,gcmAdd
,gcmDouble
,mul
,updateBlocks
,update
,gcmInc32
,sliceForAppend
,counterCrypt
,auth
,getUint64
,putUint64
など、GCMの内部演算(GF(2^128) 演算、カウンタ管理、GHASH計算など)を実装する多数のヘルパー関数が定義されています。
src/pkg/crypto/cipher/gcm_test.go
このファイルには、GCM実装の正確性を検証するためのテストケースが含まれています。
-
aesGCMTests
変数: NISTのAES-GCMテストベクトルが構造体のスライスとして定義されています。これには、鍵、ノンス、平文、追加データ、期待される結果(暗号文と認証タグの結合)が含まれます。 -
TestAESGCM
関数:aesGCMTests
の各テストベクトルに対して、以下の検証を行います。aes.NewCipher
とcipher.NewGCM
を使用してGCMインスタンスを生成します。Seal
メソッドで暗号化を行い、結果が期待される値と一致するかを確認します。Open
メソッドで復号を行い、復号された平文が元の平文と一致するかを確認します。- 追加データ、ノンス、または暗号文の一部を意図的に変更し、
Open
メソッドが正しく認証エラーを返すことを確認します。これにより、GCMの認証機能が正しく動作していることを検証します。
-
BenchmarkAESGCM
関数: GCMの暗号化パフォーマンスを測定するためのベンチマークテストです。
src/pkg/go/build/deps_test.go
このファイルは、Goのビルドシステムがパッケージ間の依存関係を正しく解決できることを確認するためのテストです。
crypto/cipher
の依存関係にcrypto/subtle
が追加されています。これは、GCM実装がsubtle.ConstantTimeCompare
を使用するためです。CRYPTO-SUPPORT
という中間的な依存関係グループが削除され、crypto/hmac
などが直接L3
に依存するように変更されています。これは、crypto/subtle
が直接crypto/cipher
から参照されるようになったため、より直接的な依存関係の記述に整理されたことを示唆しています。
関連リンク
- Go CL 12375043: https://golang.org/cl/12375043
参考にした情報源リンク
- NIST Special Publication 800-38D, Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
- Wikipedia - Galois/Counter Mode: https://en.wikipedia.org/wiki/Galois/Counter_Mode
- Wikipedia - Authenticated encryption: https://en.wikipedia.org/wiki/Authenticated_encryption
- Go Documentation - crypto/subtle: https://pkg.go.dev/crypto/subtle
- Go Documentation - crypto/cipher: https://pkg.go.dev/crypto/cipher
- Go Documentation - crypto/aes: https://pkg.go.dev/crypto/aes
- Galois Field Arithmetic for Cryptography: https://www.cs.umd.edu/class/spring2003/cmsc818e/slides/GF.pdf (GF(2^n)の解説に役立つ可能性のある一般的な情報源)
- Timing attacks: https://en.wikipedia.org/wiki/Timing_attack
- Constant-time programming: https://en.wikipedia.org/wiki/Constant-time_programming
- Go's crypto/cipher package: https://go.dev/src/crypto/cipher/ (Goのソースコードリポジトリ)
- Go's crypto/subtle package: https://go.dev/src/crypto/subtle/ (Goのソースコードリポジトリ)
- Go's crypto/aes package: https://go.dev/src/crypto/aes/ (Goのソースコードリポジトリ)
- Go's build/deps_test.go: https://go.dev/src/go/build/deps_test.go (Goのソースコードリポジトリ)