ハッシュ、ハッシュ値とはなにか?ハッシュついて分かりやすく解説!

まずは結論から、ハッシュとは、

  • ハッシュ関数と呼ばれる計算を使って、さまざまなデータから固定長の文字列を求めること
  • 求めた値を「ハッシュ値」と呼び、ハッシュ値と元データは1対1の関係になる
  • 元データが少しでも変わると、ハッシュ値は大きく変わる
  • 使用用途として、例えばデータの改ざん検知がある。データそのものを比較せずハッシュを比較すれば、データが変更されたかを簡単に判断できる

です。

ではこれから、ハッシュについてもう少し詳しく見ていきましょう!

ハッシュ、ハッシュ値とはなにか?

ハッシュとは、ハッシュ関数と呼ばれる計算手順を使って、あるデータから固定長の文字列を求めることを言います。
求めた値のことを「ハッシュ値」と呼びます。

単にハッシュと言うと、このハッシュ値を求める過程を指すことがあれば、ハッシュ値のことを指すこともあります。

オンラインでハッシュ計算ができるサービスがあるので、試してみましょう。
下記の例では、入力データとして日記のような文章を入れて、ハッシュを計算しています。

画像下部のMD5 HashとSHA1 Hashと書かれている箇所の文字列が計算したハッシュ値です。
2つの違いはハッシュの種類の違いです。(後述します)

このように、ハッシュ計算すると元のデータがまったくわからないハッシュ値を求めることができます。

ハッシュの特徴

ハッシュ関数は不可逆的な(元に戻すことができない)計算を行います。
この点を含めてハッシュにはいくつか特徴的な点がありますので、一つずつ見ていきましょう。

  • 同じデータからは常に同じハッシュ値が生成される

同じデータでハッシュ計算するとき、関数が同じであれば何度やっても同じハッシュ値が得られます。

このような、「同じデータ・同じ計算であればだれがやっても同じ結果になる」という特徴はさまざまな場面で役立ちます。

例えばメッセージを送信するとき、送信者と受信者が同じ計算方法でメッセージからハッシュ値を求めれば、まったく同じ値が得られます。これがもし異なれば、送信途中でメッセージが改ざんされていることになります。

  • データが少しでも変わるとハッシュ値が大きく変わる

データが少しでも違うと、ハッシュ値はまったく違うものが出てきます。

試しに、先ほどのハッシュ計算のデータの「1月」を「2月」に変更して再計算してみます。
すると次のようにまったく違うハッシュ値が出ました。

↓前回の結果

この特徴があるため、「ハッシュ値が1文字変わってるから、元データのここらへんが変わったんだろう」のように、ハッシュ値から元データの変更を推測できなくなります。

  • ハッシュ値から元データを再現することは限りなく不可

ハッシュ計算は不可逆的(元に戻すことができない)な計算を行います。
計算過程でデータが壊れてしまうため、ハッシュ値から元データを復元することはできません。

ハッシュ(hash)は「細かく切る」という意味の英単語です。
これはハッシュドポテトのハッシュと同じ単語で、あれはじゃがいもを細かく切って固めて揚げた料理ですよね。

ハッシュを復元しようとするのは、まるでハッシュドポテトから元のじゃがいもをきれいに復元しようとするのと同じことです。

※ただし、レインボー攻撃と呼ばれるハッシュから元データを解読する攻撃手口があります。ハッシュを復元しているわけではないのですが、こんな手口があるということで興味があれば調べてみてください。

ハッシュはなぜ必要?

ハッシュは先ほど挙げた特徴を持つことから、さまざまな場面で使われています。
主なケースは、

  • データの改ざん検知
  • 機密性の高いデータの保護

です。
ここではそれぞれ一つずつ、具体的な例をご紹介します。

  • 電子メールのセキュリティに利用(データの改ざん検知)

皆さんも日常でよくメールを使うと思いますが、世の中には第三者がメールの通信経路に介入しメールの内容を改ざんするというセキュリティ攻撃手法が存在します。

このような攻撃に対し、メールの改ざんを検出するためにハッシュが使われています。

送信者があらかじめメッセージのハッシュを計算し、メールと一緒に送ります。
受信者は受け取ったメッセージからハッシュを計算し、受け取ったハッシュ値と一致するか確認します。

データが少しでも改ざんされていたらハッシュは不一致になるはずなので、メッセージの改ざんを検出できます。
これらの一連の処理はメール通信に使われるプロトコルで内部的に行われています。

  • パスワードの保護に利用(機密性の高いデータの保護)

パスワードやセキュリティトークンなど、機密性の高い情報を保存するときにもハッシュが使われます。

例えばユーザーのパスワードをデータベースに保存するとき、パスワードをそのまま保存してしまうと、データベースに不正アクセスされ情報漏洩するリスクがあります。

そんな時はパスワードのハッシュ値を代わりに保存します。
ログイン時などユーザーがパスワードを検証するときは、入力されたパスワードのハッシュ値を求め、データベースのハッシュ値と比較して一致したら正しいパスワードと判断します。

もしもハッシュ値が流出したとしても、ハッシュは不可逆性があるので、元のパスワードが推測される心配はありません。

ハッシュの種類

ハッシュを生成するハッシュ関数にはいくつかの種類があります。
それぞれ特徴が異なるので、要件や用途によって正しく使い分けることが大切です。

  • MD5 (Message Digest Algorithm 5)

MD5は128bitのハッシュ値を生成します。
かつては広く使われていましたが、現在では衝突(異なる入力で同じハッシュ値が生成されること)が発見されセキュリティ上の問題があるため、安全性が疑問視されています。

用途:簡単なデータの整合性確認に用いることができますが、セキュリティ目的での使用は避けるべきです。

  • SHA-1(Secure Hash Algorithm 1)

SHA-1は160ビットのハッシュ値を生成します。
SHA-1もまた衝突が見つかり、現在ではセキュリティ上の脆弱性が指摘されています。より強力なハッシュ関数への移行が推奨されています。

用途:MD5と同じくセキュリティ目的での使用は避けるべきです。

  • SHA-256(Secure Hash Algorithm 256-bit)

SHA-256は256ビットのハッシュ値を生成します。
SHA-256はSHA-1よりもセキュリティ強度が高く、現在では一般的に安全とされています。

用途:セキュリティ要件が高い場面やデジタル署名、暗号学的な応用に使用されます。

  • SHA-3(Secure Hash Algorithm 3)

SHA-3は可変長のハッシュ値を生成します。この中では一番新しいアルゴリズムです。
SHA-3は、NIST(米国国立標準技術研究所)という情報技術やセキュリティなどの分野でガイドラインを策定するアメリカの政府機関により標準として定義されました。
つまり公式に安全性と信頼性が認められているということです。

用途:主にセキュリティアプリケーションやデータ整合性の確認などで使用されます。

ハッシュキーってなに?

ハッシュキーという言葉も耳にするかもしれないのでここで取り上げます。
混乱しやすいのですが、ハッシュキーはハッシュテーブルというデータ構造で利用する言葉です。
この記事で取り上げる、データ改ざん検知などで使われるハッシュとは違う話になります。

ハッシュテーブルとは、キーとバリューのペアでデータを格納するデータ構造です。

wikipediaより

この時のキーがハッシュキーと呼ばれますが、その実態は「ハッシュ値」です。(上の画像はイメージなので実際の値が書かれています)
しかし、ハッシュテーブルのハッシュ値は高速な計算が必要なため、この記事で取り上げるデータの改ざん検知などで使うMD5やSHA256のようなハッシュ関数は使わず、別の計算を使うことが一般的です。

データをハッシュするという意味では同じですが、ハッシュキーと言われたらハッシュテーブルに関する話だと思っていただければ大丈夫です。

C#でハッシュを生成してみる

最後に、C#を例にハッシュを生成するコードを見てみましょう。
今回はSHA-256のハッシュを生成するSHA256クラスを使っています。

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

public class Program
{
    public static void Main()
    {
        // ハッシュ計算したいデータ(今回は文字列)
        string inputString = "Hello, Hash!";

        // SHA-256ハッシュ関数のインスタンスを作成
        SHA256 sha256 = SHA256.Create();
        // 文字列をバイト配列に変換
        byte[] inputBytes = Encoding.UTF8.GetBytes(inputString);

        // ハッシュ計算を行い、結果を取得
        byte[] hashBytes = sha256.ComputeHash(inputBytes);

        // ハッシュ値を16進数文字列に変換
        string hashString = BitConverter.ToString(hashBytes).Replace("-", String.Empty);

        // 結果を表示
        Console.WriteLine("入力データ: " + inputString);
        Console.WriteLine("ハッシュ値(SHA-256): " + hashString);
    }
}

SHA256クラスのComputeHashではハッシュ値がバイト(0と1のデータ)の配列で返ってくるので、これを扱いやすいように16進数に変換しています。

これを実行した結果です。


入力データ: Hello, Hash!
ハッシュ値(SHA-256): 2932639BD3E3DD545EBDA5FA3DB5B976B7D7E3EE73A171B3C5FA003ED3D988C9

終わりに

ハッシュは複数の種類がありますが、それぞれ計算速度や安全性が異なります。

本記事ではそこまで踏み込んで解説していないので、興味がある方はぜひ調べてみてください。(この記事が読まれるようであれば追記します)

それでは、最後までご覧いただきありがとうございました!

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です