.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アルゴリズムによりテキスト・データのハッシュ値を求め、その結果をコンソール出力している。

using System;
using System.Security.Cryptography;
using System.Text;

class Program
{
  static void Main()
  {
    string originalText = "ThisIsPassword";
    Console.WriteLine("元のテキスト:" + originalText);

    // テキストをUTF-8エンコードでバイト配列化
    byte[] byteValue = Encoding.UTF8.GetBytes(originalText);

    // SHA256のハッシュ値を取得する
    SHA256 crypto = new SHA256CryptoServiceProvider();
    byte[] hashValue = crypto.ComputeHash(byteValue);

    // バイト配列をUTF8エンコードで文字列化
    StringBuilder hashedText = new StringBuilder();
    for (int i = 0; i < hashValue.Length; i++)
    {
      hashedText.AppendFormat("{0:X2}", hashValue[i]);
    }
    Console.WriteLine("ハッシュ値:" + hashedText.ToString());
    Console.WriteLine("文字数:" + hashedText.Length.ToString());

    // 出力例:
    // 元のテキスト:ThisIsPassword
    // ハッシュ値:9E4095417158189AD876ACBBA90C1C61D5767C2E1A507910C4A37CD8A7271D12
    // 文字数:64

    // 出力を確認するために実行を停止
    Console.ReadLine();
  }
}
Imports System
Imports System.Security.Cryptography
Imports System.Text

Module Module1

  Sub Main()

    Dim originalText = "ThisIsPassword"
    Console.WriteLine("元のテキスト:" & originalText)

    ' テキストをUTF-8エンコードでバイト配列化
    Dim byteValue As Byte() = Encoding.UTF8.GetBytes(originalText)

    ' SHA256のハッシュ値を取得する
    Dim crypto As SHA256 = New SHA256CryptoServiceProvider()
    Dim hashValue As Byte() = crypto.ComputeHash(byteValue)

    ' バイト配列をUTF8エンコードで文字列化
    Dim hashedText As New StringBuilder()
    For i As Integer = 0 To hashValue.Length - 1
      hashedText.AppendFormat("{0:X2}", hashValue(i))
    Next

    Console.WriteLine("ハッシュ値:" & hashedText.ToString())
    Console.WriteLine("文字数:" & hashedText.Length.ToString())

    ' 出力例:
    ' 元のテキスト:ThisIsPassword
    ' ハッシュ値:9E4095417158189AD876ACBBA90C1C61D5767C2E1A507910C4A37CD8A7271D12
    ' 文字数:64

    ' 出力を確認するために実行を停止
    Console.ReadLine()
  End Sub

End Module
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のページを参照してほしい)。End of Article

カテゴリ:クラス・ライブラリ 処理対象:暗号
使用ライブラリ: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
進行状況を表示しながらハッシュ値を計算するには?
バイト列と数値を変換するには?
WebClientクラスでWebページを取得するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」

更新履歴
【2010/01/20】 .NET FrameworkおよびOSの対応状況を注釈として書き加えました。


【2010/01/08】 以下のような誤りがありました。これに伴い、RIPEMD160クラスとRIPEMD160Managedクラスに関する記述を追加しました。お詫びして訂正させていただきます。


.NET Frameworkでは次の5つのハッシュ・アルゴリズムが利用できる。
.NET Frameworkでは主に次の6つのハッシュ・アルゴリズムが利用できる。


以下のような誤りがありました。お詫びして訂正させていただきます。

以上のようにさまざまなハッシュ・アルゴリズムの選択肢があるわけだが、現時点での対応OSや安定性、利便性などを総合的に考えると、やはりサンプルで示したSHA256CryptoServiceProviderクラスが最も使い勝手がよいだろう。
以上のようにさまざまなハッシュ・アルゴリズムの選択肢がある。CSPについては、すべてのOSですべてのアルゴリズムが利用できるわけではない。SHA256CryptoServiceProviderクラスSHA512CryptoServiceProviderクラスは、Windows 9xやWindows XPには対応していないので注意してほしい(対応OSについて詳しくは、MSDNのページを参照してほしい)。



Insider.NET フォーラム 新着記事
  • 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間