23
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C#】チェックサム/ハッシュアルゴリズム実践ガイド

Posted at

はじめに

ファイル転送やバックアップ、ログ保管――データが壊れていないかを確実に判定 するしくみは、あらゆるシステムで欠かせません。

そこで登場するのが チェックサムハッシュ関数 。しかし名前が似ていても 目的・性能・安全性 は大きく異なります。

そこで... C#(.NET 8 以降) で扱える代表的アルゴリズムを整理し、目的別の最適解 を整理してみました。これは自分メモも兼ねています。

チェックサム vs. 暗号学的ハッシュ

まずは、チェックサムと暗号学的ハッシュの違いを再確認してみます。

8 (1).png

種類 主目的 改ざん検知 衝突耐性 代表例
チェックサム 偶発的エラー検出 CRC32、CRC64
暗号学的ハッシュ 意図的改ざん検知 SHA-256、BLAKE3

ポイントはここ!

  • チェックサムはビット反転・ノイズ混入など偶発エラーを高効率で検知
  • 暗号学的ハッシュは衝突計算が事実上不可能な構造で、意図的改ざんまで発見

利用シーン

それぞれの利用シーンをまとめてみました。

001 (1).png

002 (1).png

代表アルゴリズムと C# 実装

CRC32 ― 転送エラー検出の定番

C#
using System.IO.Hashing;
using System.Text;

byte[] data = Encoding.UTF8.GetBytes("Hello World");
uint crc = Crc32.HashToUInt32(data);
Console.WriteLine($"CRC32  : {crc:X8}");
  • 32 bit 出力・超高速・意図的改ざんには弱い
  • .NET 8 以降は System.IO.Hashing 標準

MD5 / SHA-1 ― レガシー互換のみ

アルゴリズム 出力長 現状
MD5 128 bit 衝突コスト ≈ 数千ドル※1―新規開発非推奨
SHA-1 160 bit 2017 年 Google が衝突実証―段階的廃止

AWS/GCP の GPU で衝突が実用的に生成可能

SHA-256 ― 現行スタンダード

C#
using var sha256 = SHA256.Create();
string hex = Convert.ToHexString(sha256.ComputeHash(data));
  • 256 bit・高い安全性
  • HMACSHA256 で共有鍵を混ぜると改ざん+なりすましを同時に防止
C#
byte[] tag = new HMACSHA256(secretKey).ComputeHash(data);

SHA-3 ― 次世代標準(普及途上)

NISTが2015年にSHA-3を標準化したものの、まだ普及度は低く、多くのシステムではSHA-2系(SHA-256等)が主流です。C#でも .NET標準ライブラリには含まれておらず、サードパーティライブラリが必要です。

C#
using SHA3.Net;
byte[] hash = Sha3.Sha3256().ComputeHash(data);
string hex = Convert.ToHexString(hash);

XXH3 ― CRC 並の速度+そこそこの衝突耐性

C#
using System.IO.Hashing;
ulong xxh = XxHash64.HashToUInt64(data);   // .NET 8 標準
  • ファイル重複検出・キャッシュキー向け
  • ⚠️ 重要:セキュリティ目的には絶対に使用しない(暗号学的強度なし)

BLAKE3 ― 高速 & セキュア & 並列化

C#
using Blake3;
string hex = Hasher.Hash(data).ToHex();
  • SHA-256 の 2〜10 倍速 (CPU に依存)
  • NuGet Isopoh.Cryptography.Blake3 等を利用(メンテナンス継続中の実装を選択
  • 並列ストリーム API があり巨大ファイルで真価
  • 注意:公式にFIPS認定はまだ(企業環境では要確認)

速度 vs セキュリティ強度マップ

004 (1).png

図は「速度とセキュリティ強度の相対的な目安」です。
XXH3/CRC32 は高速ですが暗号学的強度がないため、改ざん検知用途には使用できません。

アルゴリズム選択マトリクス

速度 衝突耐性 改ざん検知 主用途
CRC32 ★★★★★ ★★ 転送エラー検出
XXH3 ★★★★★ ★★★ 重複検出/キャッシュキー
SHA-256 ★★ ★★★★★ 改ざん検知・署名
BLAKE3 ★★★★ ★★★★★ 巨大ファイル/高速改ざん検知

用途別 C# サンプル

用途別のサンプルをいくつか置いておきます。

ファイル転送の破損検知 (CRC32)

ネットワーク転送やファイルコピー時の偶発的なビット反転を検出するシンプルな例です。送信側で計算したCRC32値と受信側で再計算した値を比較します。

C#
uint expected = 0x4A17B156;
bool ok = Crc32.HashToUInt32(File.ReadAllBytes(path)) == expected;

ソフトウェア配布の署名検証 (SHA-256)

ダウンロードサイトで提供される公式ハッシュ値と実際のファイルを照合し、改ざんされていないことを確認します。

C#
// ダウンロードファイルの整合性検証例
string downloadedFile = "setup.exe";
string expectedHash = "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3";

using var sha256 = SHA256.Create();
byte[] fileHash = sha256.ComputeHash(File.ReadAllBytes(downloadedFile));
string actualHash = Convert.ToHexString(fileHash);

bool isValid = string.Equals(expectedHash, actualHash, StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"ファイル検証: {(isValid ? "OK" : "NG")}");

ログ改ざん検知 (HMAC-SHA256)

アプリケーションログが後から書き換えられていないかを検証します。秘密鍵を使ったHMACにより、内容の完全性と真正性を同時に担保できます。

C#
// ログファイルの改ざん検知システム例
string logContent = File.ReadAllText("app.log");
byte[] secretKey = Convert.FromBase64String("your-secret-key");

// ハッシュ生成
byte[] hash = new HMACSHA256(secretKey)
    .ComputeHash(Encoding.UTF8.GetBytes(logContent));
string hashHex = Convert.ToHexString(hash);

// 検証
bool isValid = new HMACSHA256(secretKey)
    .ComputeHash(Encoding.UTF8.GetBytes(logContent))
    .SequenceEqual(Convert.FromHexString(storedHashHex));

重複ファイル削除ツール (XXH3)

大量のファイルから重複を高速検出する際に活用します。暗号学的強度は不要で、速度重視のため非暗号ハッシュXXH3が最適です。

C#
// 高速な重複ファイル検出
var fileHashes = new Dictionary<ulong, List<string>>();

foreach (string file in Directory.EnumerateFiles(targetDir, "*", SearchOption.AllDirectories))
{
    ulong hash = XxHash64.HashToUInt64(File.ReadAllBytes(file));
    
    if (!fileHashes.ContainsKey(hash))
        fileHashes[hash] = new List<string>();
    
    fileHashes[hash].Add(file);
}

// 重複ファイル表示
foreach (var (hash, files) in fileHashes.Where(kv => kv.Value.Count > 1))
{
    Console.WriteLine($"重複グループ (Hash: {hash:X16}):");
    foreach (string file in files)
        Console.WriteLine($"  {file}");
}

実装時の落とし穴

  1. Dispose 忘れ
    HashAlgorithmusing で確実に解放。
  2. 大小文字比較
    StringComparison.OrdinalIgnoreCase を必ず指定。
  3. I/O と CPU の分離
    await file.CopyToAsync() など I/O 非同期を優先、Task.Run 連発は避ける。
  4. 平文ハッシュの過信
    ハッシュ値をそのまま公開するとリプレイ攻撃の温床。秘密鍵入り HMAC か署名を。
  5. XXH3 の誤用
    高速だがセキュリティ強度なし。改ざん検知には使用禁止。

選択フロー(まとめ)

003 (1).png

参考資料

おわりに

「早い=安全」ではありません。 目的に合ったアルゴリズムを選び、必要なら HMAC やデジタル署名を組み合わせてこそ、パフォーマンスと信頼性の両立が実現できます。

23
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?