.NET TIPS SHA-1/SHA-2/MD5ハッシュ値を計算するには?[C#、VB]デジタルアドバンテージ 一色 政彦2010/01/07 2010/01/08 更新 2010/01/20 更新 |
|
|
2つのパスワードや2つの大容量データなどを比較する際、そのデータをそのまま比較するのではなく、そのデータを元に生成した固定長(16/20/32/48/64bytesなど)の一意な値、いわゆる「ハッシュ値」を使うということがよくある(※なお、このハッシュ値は不可逆なデータで、ハッシュ値から元のデータに戻すことはできない。つまり、ハッシュは「一方向の暗号化」である)。このハッシュ値は、元のデータが1bitでも異なると大きく変化するため、特にテキストやファイルが改ざんされていないかをチェックするのに適している。
ハッシュ値の活用例としては、例えばパスワードの保存がある。ハッシュ値を使えば、生のテキスト・パスワードを保存しなくて済むので安全性が高まる(万が一、ハッシュ値が漏れても、それから実際のパスワードは取得できない)。また、例えば2者間で送受信したデータが不正ではないかをチェックしたいときにも使える。この場合、送信者と受信者におけるデータのハッシュ値を比較するだけで、そのデータが壊れていないかどうかを確認できる(いわゆるチェックサム)。
ちなみに、.NET Frameworkではハッシュ値を活用したKey-Valueコレクション(=キーと値をペアにしたデータを格納するコレクション)であるハッシュテーブル(Hashtableクラス)が用意されている。そのHashtableクラスでは、キーとなるオブジェクトが持つGetHashCodeメソッドを呼び出してハッシュ値を得ている。このため、最も基本的なクラスであるObjectクラスにはGetHashCodeメソッドがあらかじめ用意されている(ちなみに、このようなハッシュ値を求めるメソッドは「ハッシュ関数」と呼ばれる)。
しかしながら、Object.GetHashCodeメソッドは一意性や一貫性が保証されていないので、おのおののクラスでGetHashCodeメソッドを呼び出しても有効なハッシュ値が得られるとは限らない。ただし、ハッシュテーブルのキーとしてよく使われるStringクラス(=文字列)のGetHashCodeメソッドは一意なハッシュ値を出力してくれるので、文字列に対して簡単なハッシュ値を取得したい場合は、String.GetHashCodeメソッドを呼び出せばよい。
本稿では、このようなハッシュ値を計算(=ハッシュ)する方法を紹介する。
●.NET Frameworkで利用できるハッシュ・アルゴリズム
.NET Frameworkでは主に次の6つのハッシュ・アルゴリズムが利用できる。
- MD5(128bits=16bytes)
- SHA1(160bits=20bytes)
- SHA256(256bits=32bytes)
- SHA384(384bits=48bytes)
- SHA512(512bits=64bytes)
- RIPEMD160(160bits=20bytes)
上記のカッコ内はハッシュ値のサイズである。ちなみに、例えばMD5は16bytesだが、1bytesは16進数表記で表現すると2けた(=00〜FF)になるので、ハッシュ値を16進数表記のテキスト・データに変換すると32文字の固定サイズのテキストになる。
SHA256、SHA384、SHA512らはまとめて「SHA-2」と呼ばれる。
MD5やSHA1では、脆弱性が指摘されているので注意してほしい。現時点で最も手軽に使えて安全性の高いハッシュ・アルゴリズムはSHA256である。
●文字列に対するハッシュ値を取得する方法
ここでは、ハッシュ・アルゴリズムにより文字列に対するハッシュ値を取得する方法を説明する。なお、以下で紹介するクラスはすべてSystem.Security.Cryptography名前空間に属する。
.NET Frameworkでは、ハッシュ関数が、アルゴリズムごとに下記の6つのクラスが持つComputeHashメソッドで提供されている。
- MD5クラス
- SHA1クラス
- SHA256クラス
- SHA384クラス
- SHA512クラス
- RIPEMD160クラス
ただし、これらのクラスはあくまで基本クラスであり、アルゴリズムの実装はこれらの派生クラスで行われている。その代表的な派生クラスは以下のとおりだ。
- MD5CryptoServiceProviderクラス
- SHA1CryptoServiceProviderクラス
- SHA256CryptoServiceProviderクラス *1
- SHA384CryptoServiceProviderクラス *1
- SHA512CryptoServiceProviderクラス *1
*1 .NET Framework 3.5以降でサポート。Windows Server 2003、Windows Vista以降でサポート。 |
つまり、例えばSHA256アルゴリズムを使用したい場合は、SHA256CryptoServiceProviderクラスをインスタンス化して、そのオブジェクトのComputeHashメソッドを呼び出せばよいわけである。
ComputeHashメソッドは、引数としてデータのバイト配列を受け取る。従って文字列データを渡したいときも、いったんバイト配列に変換して渡す必要がある。文字列をバイト配列にする方法については、「TIPS:文字列をシフトJISとしてバイト列に変換するには?」を参考にしてほしい。後述するサンプルでは、日本語以外も共通的に扱えて無難なUTF-8エンコードでバイト配列化する。
また、ComputeHashメソッドの戻り値も、バイト配列である。バイト配列を画面上に表示したり、データベースやファイルにテキストとして保存したりしたい場合には、バイト・データを16進数文字で表現すればよいだろう。バイト・データを16進数のテキスト・データに変換する方法は、「TIPS:バイト列と数値を変換するには?」を参考にしてほしい。
以上の内容を踏まえてサンプル実装したコンソール・アプリケーションが、次のコードである。このコードでは、SHA256アルゴリズムによりテキスト・データのハッシュ値を求め、その結果をコンソール出力している。
|
||
SHA256アルゴリズムによりハッシュ値を計算するサンプル・コード(上:C#、下:VB) |
上記のコードの「SHA256」を、「MD5」や「SHA1」「SHA384」「SHA512」などに一括置換しても正しく動作する。
上記のコードでSHA256CryptoServiceProviderクラスのインスタンスを、その基本クラスのSHA256クラスのオブジェクトとして受けているが、これはほかのSHA256アルゴリズムに変更しやすいようにするためである。実は、SHA256クラスの派生クラスはSHA256CryptoServiceProviderクラスだけではない。SHA256CryptoServiceProviderクラス自体は、Windows(95/NT以降)が提供するCryptoAPIの暗号サービス・プロバイダ(CSP:Cryptographic Service Provider)を利用するアルゴリズム実装である。
Windows Vista以降は、CryptoAPIに代わる新しい暗号化APIとしてCNG(Cryptography Next Generation)が提供されており、そのCNGによるハッシュ・アルゴリズム実装を利用する以下のクラスが用意されている。
- MD5Cngクラス *2
- SHA1Cngクラス *2
- SHA256Cngクラス *2
- SHA384Cngクラス *2
- SHA512Cngクラス *2
*2 .NET Framework 3.5以降でサポート。Windows Server 2003、Windows Vista以降でサポート。 |
また、以下のクラス群では.NET Frameworkのマネージ・ライブラリにより実装されたアルゴリズムを利用できる。なお、MD5アルゴリズムの実装は提供されていない。
- SHA1Managedクラス
- SHA256Managedクラス
- SHA384Managedクラス
- SHA512Managedクラス
- RIPEMD160Managedクラス *3
*3 .NET Framework 2.0以降でサポート。 |
以上のようにさまざまなハッシュ・アルゴリズムの選択肢がある。CSPについては、すべてのOSですべてのアルゴリズムが利用できるわけではない。SHA256CryptoServiceProviderクラスやSHA512CryptoServiceProviderクラスは、Windows 9xやWindows XPには対応していないので注意してほしい(対応OSについて詳しくは、MSDNのページを参照してほしい)。
カテゴリ:クラス・ライブラリ 処理対象:暗号 使用ライブラリ:MD5CryptoServiceProviderクラス(System.Security.Cryptography名前空間) 使用ライブラリ:SHA1CryptoServiceProviderクラス(System.Security.Cryptography名前空間) 使用ライブラリ:SHA256CryptoServiceProviderクラス(System.Security.Cryptography名前空間) 使用ライブラリ:SHA384CryptoServiceProviderクラス(System.Security.Cryptography名前空間) 使用ライブラリ:SHA512CryptoServiceProviderクラス(System.Security.Cryptography名前空間) 関連TIPS:文字列をシフトJISとしてバイト列に変換するには? 関連TIPS:バイト列と数値を変換するには? |
|
「.NET TIPS」 |
更新履歴 | |||||||||
|
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|