ファイルハッシュを計算することは「改ざん検知と整合性確認のための基本的なセキュリティ技術」です
業務システムや社内ツール、配布用バイナリ、ログファイルなどを扱う読者のみなさんにとって、 ファイルのハッシュ値を計算しておくことは、 「そのファイルが途中で書き換えられていないか」を確認するための重要な手段になります。
ここでは、プログラミング初心者の方にも分かるように、 C#でファイルハッシュを計算するユーティリティを ステップバイステップで解説しながら、 実務でそのまま使えるテンプレートとしてまとめていきます。
ファイルハッシュとは何か
ファイルハッシュの役割
ファイルハッシュとは、 ファイルの内容から「一方向の指紋」を計算したものです。
特徴は次のとおりです。
- 同じファイルからは必ず同じハッシュ値が得られる
- ファイルの内容が1バイトでも変わると、ハッシュ値はまったく違うものになる
- ハッシュ値から元のファイル内容を復元することは現実的には不可能
この性質を利用して、 「ファイルが改ざんされていないか」「配布時に壊れていないか」を確認します。
よく使われるハッシュアルゴリズム
ファイルハッシュでよく使われるアルゴリズムは次のとおりです。
- SHA-256
- SHA-512
- (古い例として)SHA-1(ただしセキュリティ用途には非推奨)
ここでは、実務でよく使われる SHA-256 と SHA-512 を前提に話を進めます。
C#でファイルハッシュを計算する基本ステップ
ファイルハッシュを計算する流れは、とてもシンプルです。
- ファイルをストリームとして開く
- ハッシュアルゴリズム(SHA-256 / SHA-512)を作成する
- ストリームからハッシュを計算する
- 計算結果(バイト配列)を Hex文字列に変換する
この流れをユーティリティとしてまとめることで、 どのプロジェクトでも再利用できる「業務用の部品」になります。
実務で使えるファイルハッシュ計算ユーティリティ(テンプレート)
まずは、アルゴリズムを選べる汎用的なユーティリティを作ります。
using System;
using System.IO;
using System.Security.Cryptography;
public static class FileHashUtility
{
/// <summary>
/// ファイルのハッシュを計算し、Hex形式で返します。
/// algorithmName には "SHA256" や "SHA512" を指定します。
/// </summary>
public static string ComputeFileHashHex(string filePath, string algorithmName = "SHA256")
{
using var stream = File.OpenRead(filePath);
using var algorithm = HashAlgorithm.Create(algorithmName);
if (algorithm == null)
throw new InvalidOperationException($"ハッシュアルゴリズム '{algorithmName}' を作成できませんでした。");
byte[] hash = algorithm.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
/// <summary>
/// SHA-256でファイルハッシュを計算するショートカット。
/// </summary>
public static string ComputeSha256Hex(string filePath)
{
return ComputeFileHashHex(filePath, "SHA256");
}
/// <summary>
/// SHA-512でファイルハッシュを計算するショートカット。
/// </summary>
public static string ComputeSha512Hex(string filePath)
{
return ComputeFileHashHex(filePath, "SHA512");
}
}
C#このユーティリティは、 「アルゴリズム名を指定してファイルハッシュを計算する汎用関数」と、 「SHA-256専用」「SHA-512専用」のショートカット関数を提供しています。
ユーティリティの使い方(例題)
例1:単純にファイルのハッシュを表示する
string path = @"C:\temp\sample.txt";
string sha256 = FileHashUtility.ComputeSha256Hex(path);
Console.WriteLine($"SHA-256: {sha256}");
string sha512 = FileHashUtility.ComputeSha512Hex(path);
Console.WriteLine($"SHA-512: {sha512}");
C#このようにすることで、 同じファイルからは常に同じハッシュ値が得られます。
例2:ダウンロードしたファイルが正しいか検証する
配布元が「このファイルのSHA-256はこれです」と公開している場合、 その値と自分で計算した値を比較することで、 途中で改ざんされていないか確認できます。
string path = @"C:\download\installer.exe";
string expectedHash = "公開されているSHA-256値";
string actualHash = FileHashUtility.ComputeSha256Hex(path);
if (string.Equals(expectedHash, actualHash, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("ファイルは正しい状態です。");
}
else
{
Console.WriteLine("ファイルが改ざんされている可能性があります。");
Console.WriteLine($"期待値: {expectedHash}");
Console.WriteLine($"現在値: {actualHash}");
}
C#ファイルハッシュの深掘り(重要ポイント)
なぜHex形式で扱うのか
ハッシュの計算結果はバイト配列ですが、 そのままだと人間には読みにくいので、 通常は16進数(Hex)文字列に変換して扱います。
- ログに出力しやすい
- データベースに保存しやすい
- 比較しやすい
というメリットがあります。
ハッシュは「改ざん検知」であり「暗号化」ではない
ここは初心者の方がよく誤解するポイントです。
- ハッシュは「元に戻せない指紋」です
- ハッシュ値から元のファイル内容を復元することはできません
- ハッシュは「同じかどうかを確認する」ためのものです
ファイルの内容を隠したい場合は、 AESなどの暗号化を別途使う必要があります。
ハッシュアルゴリズムの選び方
- 改ざん検知や整合性チェックには SHA-256 / SHA-512 が推奨
- SHA-1 は古く、セキュリティ用途には非推奨
- パスワード保存などには、そもそも「高速ハッシュ」であるSHA系ではなく、PBKDF2 / bcrypt / Argon2を使うべき
ファイル検証のような用途では、 SHA-256かSHA-512を選んでおけば問題になることはほとんどありません。
ファイルハッシュ計算で絶対にやってはいけないこと
- ハッシュ値を「暗号化」と誤解する
- ハッシュ値から元のファイルを復元できると勘違いする
- ハッシュ値を適当に更新してしまう(検証の意味がなくなる)
- 改ざん検知の結果を無視する
これらは、セキュリティ事故や運用トラブルの原因になります。
実務的ベストプラクティス
- 配布物や重要ファイルには、必ずハッシュ値を記録しておく
- ハッシュ値はHex形式で管理すると運用しやすい
- 検証処理をバッチやデプロイ後のチェックに組み込む
- 異常検知時にはログ・通知・隔離をセットで行う
- ハッシュ値を保存するテーブルや設定ファイルを用意しておく
まとめ:ファイルハッシュ計算は「見えない改ざんを見える化する技術」
ファイルハッシュ計算の本質は次の3つです。
- ファイル内容から一方向の「指紋」を作る
- 少しの変更でもまったく違うハッシュになる
- その指紋を基準値として保存し、後から検証できるようにする
このユーティリティを業務システムに組み込むことで、 「静かに進行する改ざん」や「意図しない破損」を 早い段階で検知できるようになります。
読者のみなさんがシステムを設計・実装する際、 ここで紹介したテンプレートをベースに、 自分たちの環境に合わせたファイル検証フローを組み立てていくとよいでしょう。
