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

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

このコミットは、Go言語の標準ライブラリ crypto/hmac パッケージ内の hmac_test.go ファイルに対する変更です。具体的には、HMAC (Keyed-Hash Message Authentication Code) のテストスイートに、Size() メソッドと BlockSize() メソッドの検証を追加しています。

コミット

commit 351caa4b9109a3d307557b539427869abefbf815
Author: Shawn Smith <shawn.p.smith@gmail.com>
Date:   Sun Dec 29 20:56:05 2013 +1100

    crypto/hmac: add tests for Size() and BlockSize()
    
    R=golang-codereviews, dave
    CC=golang-codereviews
    https://golang.org/cl/41320044

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

https://github.com/golang/go/commit/351caa4b9109a3d307557b539427869abefbf815

元コミット内容

crypto/hmac: add tests for Size() and BlockSize()

R=golang-codereviews, dave
CC=golang-codereviews
https://golang.org/cl/41320044

変更の背景

このコミットの背景には、crypto/hmac パッケージが提供するHMAC実装の堅牢性を高める目的があります。HMACは、メッセージ認証コード (MAC) の一種であり、秘密鍵とハッシュ関数を組み合わせてメッセージの完全性と認証性を保証します。Go言語の hash パッケージには、ハッシュ関数が満たすべき hash.Hash インターフェースが定義されており、これには Size()BlockSize() メソッドが含まれています。

Size() メソッドはハッシュ値のバイト長を返し、BlockSize() メソッドはハッシュ関数が一度に処理するブロックのバイト長を返します。これらの値は、HMACの計算において内部的に使用される重要なパラメータです。

以前のテストスイートでは、HMACの出力値(ハッシュ値)の正確性は検証されていましたが、HMACオブジェクトが基盤となるハッシュ関数の Size()BlockSize() を正しく反映しているかどうかのテストが不足していました。このコミットは、これらの重要なプロパティがHMAC実装によって正しく扱われていることを保証するために、テストカバレッジを向上させることを目的としています。これにより、将来的な変更や異なるハッシュ関数の統合があった場合でも、HMACの動作が期待通りであることを確認できます。

前提知識の解説

HMAC (Keyed-Hash Message Authentication Code)

HMACは、メッセージの完全性と認証性を検証するために使用される特定のタイプのメッセージ認証コード (MAC) です。秘密鍵と暗号学的ハッシュ関数(例: SHA-1, SHA-256, MD5)を組み合わせて動作します。HMACは、メッセージが送信中に改ざんされていないこと、およびメッセージが秘密鍵を知っている正当な送信者によって生成されたことを保証します。

HMACの計算は以下のステップで行われます:

  1. 秘密鍵 K をハッシュ関数のブロックサイズに合わせてパディングまたはハッシュ化します。
  2. 内部パディング ipad と外部パディング opad を定義します。
  3. K XOR ipad とメッセージ M を連結し、ハッシュ関数を適用します。
  4. K XOR opad と上記の結果を連結し、再度ハッシュ関数を適用します。

Go言語の hash.Hash インターフェース

Go言語の crypto パッケージ群では、ハッシュ関数は hash.Hash インターフェースを実装します。このインターフェースは、すべてのハッシュ関数が共通して持つべきメソッドを定義しています。

type Hash interface {
    // Write (via the embedded io.Writer interface) adds more data to the running hash.
    // It never returns an error.
    io.Writer

    // Sum appends the current hash to b and returns the resulting slice.
    // It does not change the underlying hash state.
    Sum(b []byte) []byte

    // Reset resets the Hash to its initial state.
    Reset()

    // Size returns the number of bytes Sum will return.
    Size() int

    // BlockSize returns the hash's underlying block size.
    // The Write method must be able to accept any amount of data, but it may operate more efficiently if all writes are a multiple of the block size.
    BlockSize() int
}
  • Size() int: このメソッドは、ハッシュ関数が生成するハッシュ値のバイト長を返します。例えば、SHA-256であれば32バイト(256ビット)を返します。
  • BlockSize() int: このメソッドは、ハッシュ関数が内部的にデータを処理する際のブロックサイズをバイト単位で返します。例えば、SHA-256のブロックサイズは64バイトです。ハッシュ関数は、入力データをこのブロックサイズに分割して処理します。

HMACの実装では、基盤となるハッシュ関数の Size()BlockSize() の値が正しくHMACオブジェクトに反映されていることが重要です。これは、HMACの内部計算や、HMACオブジェクト自体が hash.Hash インターフェースを実装している場合に、そのインターフェースの契約を満たすために必要となります。

技術的詳細

このコミットは、crypto/hmac パッケージのテストファイル hmac_test.go に変更を加えています。主な変更点は以下の通りです。

  1. hmacTest 構造体の拡張: 既存の hmacTest 構造体に、size (ハッシュ値のサイズ) と blocksize (ハッシュ関数のブロックサイズ) という2つのフィールドが追加されました。これにより、各テストケースで期待される Size()BlockSize() の値を定義できるようになります。

    --- a/src/pkg/crypto/hmac/hmac_test.go
    +++ b/src/pkg/crypto/hmac/hmac_test.go
    @@ -15,10 +15,12 @@ import (
     )
     
     type hmacTest struct {
    -	hash func() hash.Hash
    -	key  []byte
    -	in   []byte
    -	out  string
    +	hash      func() hash.Hash
    +	key       []byte
    +	in        []byte
    +	out       string
    +	size      int
    +	blocksize int
     }
    
  2. テストケースへの sizeblocksize の追加: hmacTests スライス内の既存のHMACテストケースそれぞれに、対応するハッシュ関数の Size()BlockSize() の値が追加されました。例えば、SHA-1を使用するテストケースには sha1.Sizesha1.BlockSize が、MD5を使用するテストケースには md5.Sizemd5.BlockSize が設定されています。

    @@ -38,6 +40,8 @@ var hmacTests = []hmacTest{
     		},
     		[]byte("Sample #1"),
     		"4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a",
    +		sha1.Size,
    +		sha1.BlockSize,
     	},
     	{
     		sha1.New,
    
  3. TestHMAC 関数での Size()BlockSize() の検証: TestHMAC 関数内のテストループに、新しく追加された sizeblocksize フィールドを使用して、HMACオブジェクトの Size()BlockSize() メソッドが正しい値を返すことを検証するアサーションが追加されました。

    @@ -465,12 +515,20 @@ var hmacTests = []hmacTest{
     	},\n }\n \n func TestHMAC(t *testing.T) {\n \tfor i, tt := range hmacTests {\n \t\th := New(tt.hash, tt.key)\n+\t\tif s := h.Size(); s != tt.size {\n+\t\t\tt.Errorf("Size: got %v, want %v", s, tt.size)\n+\t\t}\n+\t\tif b := h.BlockSize(); b != tt.blocksize {\n+\t\t\tt.Errorf("BlockSize: got %v, want %v", b, tt.blocksize)\n+\t\t}\n \t\tfor j := 0; j < 2; j++ {\n \t\t\tn, err := h.Write(tt.in)\n \t\t\tif n != len(tt.in) || err != nil {\n    ```
    
    

これらの変更により、crypto/hmac パッケージのテストは、HMACオブジェクトが基盤となるハッシュ関数の特性(ハッシュ値のサイズとブロックサイズ)を正確に反映していることを保証するようになりました。これは、HMACの正しい動作と、hash.Hash インターフェースの契約遵守にとって不可欠です。

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

変更は src/pkg/crypto/hmac/hmac_test.go ファイルに集中しています。

  1. hmacTest 構造体の定義に size intblocksize int フィールドが追加されました。
  2. hmacTests スライス内の各テストケースに、対応するハッシュ関数の Size()BlockSize() の定数値が追加されました。
    • sha1.Size, sha1.BlockSize
    • md5.Size, md5.BlockSize
    • sha256.Size, sha256.BlockSize
    • sha256.Size224, sha256.BlockSize (SHA-224の場合)
    • sha512.Size384, sha512.BlockSize (SHA-384の場合)
    • sha512.Size, sha512.BlockSize
  3. TestHMAC 関数内で、hmac.New で作成されたHMACオブジェクト h に対して、h.Size()h.BlockSize() の戻り値が、テストケースで定義された期待値 (tt.sizett.blocksize) と一致するかどうかを検証するアサーションが追加されました。

コアとなるコードの解説

このコミットの核心は、hmac_test.go 内の TestHMAC 関数に追加された以下のコードブロックです。

		if s := h.Size(); s != tt.size {
			t.Errorf("Size: got %v, want %v", s, tt.size)
		}
		if b := h.BlockSize(); b != tt.blocksize {
			t.Errorf("BlockSize: got %v, want %v", b, tt.blocksize)
		}
  • h := New(tt.hash, tt.key): 各テストケースの冒頭で、指定されたハッシュ関数 (tt.hash) と鍵 (tt.key) を使用して新しいHMACオブジェクト h が作成されます。
  • if s := h.Size(); s != tt.size { ... }:
    • h.Size(): 作成されたHMACオブジェクトの Size() メソッドを呼び出し、HMACが生成するハッシュ値のバイト長を取得します。
    • s != tt.size: 取得したサイズ s が、テストケースで事前に定義された期待されるサイズ tt.size と異なる場合、テストは失敗します。
    • t.Errorf(...): エラーメッセージを出力し、テストの失敗を報告します。
  • if b := h.BlockSize(); b != tt.blocksize { ... }:
    • h.BlockSize(): 作成されたHMACオブジェクトの BlockSize() メソッドを呼び出し、HMACが内部的に使用するハッシュ関数のブロックサイズを取得します。
    • b != tt.blocksize: 取得したブロックサイズ b が、テストケースで事前に定義された期待されるブロックサイズ tt.blocksize と異なる場合、テストは失敗します。
    • t.Errorf(...): エラーメッセージを出力し、テストの失敗を報告します。

これらのアサーションは、crypto/hmac パッケージの New 関数が、基盤となるハッシュ関数の Size()BlockSize() の特性を正しくHMACオブジェクトに伝播させていることを確認します。これにより、HMACオブジェクトが hash.Hash インターフェースの契約を適切に満たし、その後のHMAC計算が期待通りに機能するための重要な前提条件が検証されます。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • RFC 2104
  • Go言語の crypto/hmac および hash パッケージのソースコード
  • Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/41320044
  • HMACに関する一般的な暗号学の知識