🎉

【Go】弱いハッシュ関数を自作、衝突耐性を突破するサンプルコード

に公開

概要

  • 暗号技術入門 第3版に出てきたハッシュ関数を自作してみた。
  • 衝突を検出する関数も書いてみた

サンプルコード

ハッシュ関数

func fakeOneWayHash(s string) int {
	hash := 0

	// 文字列の各文字について処理
	for _, r := range s {
		// 単純な加算と乗算のみを使用
		hash = hash*31 + int(r)
	}

	// 正の32ビット整数に変換
	return hash & 0x7FFFFFFF
}

// 実行結果
// fakeOneWayHash("cat")
// ハッシュ値: 98262

第二現像攻撃による弱衝突を検出する関数

func verifyWeakCollision(targetString string) {
	targetHash := fakeOneWayHash(targetString)
	fmt.Printf("対象文字列: %s\n", targetString)
	fmt.Printf("対象ハッシュ値: %d\n", targetHash)

	// 小文字、大文字、数字を含む文字セット
	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	found := false

	// 3文字の全パターンを総当たり
	for _, c1 := range letters {
		for _, c2 := range letters {
			for _, c3 := range letters {
				s := string([]rune{c1, c2, c3})
				if fakeOneWayHash(s) == targetHash && s != targetString {
					fmt.Printf("衝突を発見: %s (ハッシュ値: %d)\n", s, fakeOneWayHash(s))
					found = true
				}
			}
		}
	}

	if !found {
		fmt.Println("衝突する文字列は見つかりませんでした")
	}
}

// 実行結果
// verifyWeakCollision("cat")
// 対象文字列: cat
// 対象ハッシュ値: 98262
// 衝突を発見: cbU (ハッシュ値: 98262)
// 衝突を発見: cc6 (ハッシュ値: 98262)
// 衝突を発見: dBt (ハッシュ値: 98262)
// 衝突を発見: dCU (ハッシュ値: 98262)
// 衝突を発見: dD6 (ハッシュ値: 98262)

衝突攻撃による強衝突を検出する関数

func verifyStrongCollision() {
	// ハッシュ値と文字列のマッピングを保持するマップ
	hashMap := make(map[int]string)
	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	found := false

	// ランダムな文字列を生成して衝突を探す
	for i := 0; i < 1000000; i++ { // 最大100万回試行
		// 3文字のランダムな文字列を生成
		s := string([]rune{
			letters[rand.Intn(len(letters))],
			letters[rand.Intn(len(letters))],
			letters[rand.Intn(len(letters))],
		})

		hash := fakeOneWayHash(s)

		// 同じハッシュ値を持つ文字列が既に存在するかチェック
		if existing, exists := hashMap[hash]; exists && existing != s {
			fmt.Printf("強衝突を発見:\n")
			fmt.Printf("文字列1: %s (ハッシュ値: %d)\n", existing, hash)
			fmt.Printf("文字列2: %s (ハッシュ値: %d)\n", s, hash)
			found = true
			break
		}

		// 現在の文字列とハッシュ値をマップに保存
		hashMap[hash] = s
	}

	if !found {
		fmt.Println("強衝突は見つかりませんでした")
	}
}

// 実行結果
// verifyStrongCollision()
// 強衝突を発見:
// 文字列1: vxX (ハッシュ値: 117206)
// 文字列2: vy9 (ハッシュ値: 117206)

まとめ

  • ハッシュ関数は自作せずSHA2-, SHA-3など安全性のあるアルゴリズムを使用しましょう
GitHubで編集を提案

Discussion