MENU
なお
じゃぱざむ運営主
20歳 | WEBメディアの会社で部長をやりながら、じゃぱざむ・特化メディア・WEB制作~コンサル・SEOディレクター・投資・就活相談など幅広くやっています。
いまい
エンジニア志望の大学生
21歳 | 理系の大学3年生|Webアプリ開発を勉強中。クラウド系の自社開発企業に内定。じゃぱざむでは、IT系記事の執筆とアイキャッチ画像の作成をしています。
【完全ガイド】大学生でもプログラミングで稼ぎ始めるためのロードマップ

ハッシュ関数とハッシュ値とは?用途や性質もわかりやすく解説!

記事上バナー
テックキャンプの記事上バナー
レイズテックの記事上バナー
テックブーストの記事上バナー
  • ハッシュとは何かを知りたい方!
  • ハッシュ関数やハッシュ値とは何かを知りたい方!
  • どんな用途でハッシュ関数が使われているのかを知りたい方!
いまいのアイコン画像いまい
こんにちは!
今井(@ima_maru)です。

今回は、様々な用途で使われる「ハッシュ」について解説します。

今話題の「ブロックチェーン技術」の仕組みにもかかわっている重要な概念です。

初めに断っておきますが、ハッシュ関数自体の詳しい仕組み、アルゴリズムには触れません

ご了承ください。それでは解説していきます。

タップして好きなところから読めます

ハッシュ(hash)とは?

ハッシュとは、日本語では「細切れ」といった意味があります。

もっと言えば、「寄せ集め」という言葉が当てはまります。

しいて言うなら、「データをぐちゃぐちゃにして寄せ集める」といったようなイメージです。

IT用語では、「ハッシュ」というより、「ハッシュ関数」「ハッシュ値」「ハッシュ化」といったような熟語で使うのが一般的のように思います。

それらの関係性・定義を先に示しておきます。

「ハッシュ関数」:ある計算によって入力データから決められた長さの出力データを得る関数
「ハッシュ値」:ハッシュ関数から生成される値

言葉で説明するよりも、見てもらったほうが、簡単にわかると思います。

ハッシュ関数からハッシュ値が生成される流れを見てみましょう。

ハッシュ関数からハッシュ値が生成される流れ

まずは、「ハッシュ値」を生成するために必要な「ハッシュ関数」というものを用意します。

今回は、C++の標準ライブラリの「hash」を使います。

hash<string> hash_function;

これがC++の文字列用のハッシュ関数です。

hash_functionを名付けました。

いまいのアイコン画像いまい
ハッシュ関数の仕組み自体はとても難しいものなので、割愛します。
気になった方は、「SHA-2」などと検索してみてください。

次に、実際にデータからハッシュ値を生成する処理です。

size_t hash_value = hash_function(data);

このhash_functionの引数にデータを渡すと、ハッシュ値が返ってきます。

このハッシュ値をhash_valueと名付けることにします。

では、適当な文字列をデータとしてハッシュ関数に渡してみましょう。

ハッシュ関数からハッシュ値を得る

まずは、以下のような文字列のデータからハッシュ値を生成してみましょう。

int main()
{
	// データ
	string data = "吾輩は猫である。名前はまだ無い。";
	
	// ハッシュ関数
	hash<string> hash_function;

	// ハッシュ値の計算
	size_t hash_value = hash_function(data);

	// ハッシュ値の表示
	cout << bitset<40>(hash_value) << " : " << hash_value << endl;

	return 0;
}

そしてその文字列をハッシュ関数に通して、ハッシュ値を生成してみましょう。

そうすると、

0000000000101011101110101111100110110000 : 733673904

このようなハッシュ値が生成されます。(左が2進数表現40bit分で右が10進数表現です。)

同じデータは同じハッシュ値を生成する

次に、もう一回同じ文字列をハッシュ関数に渡したらどうなるのかを試してみましょう。

int main()
{
	// データ
	string data1 = "吾輩は猫である。名前はまだ無い。";
	string data2 = "吾輩は猫である。名前はまだ無い。";

	// ハッシュ関数
	hash<string> hash_function;

	// ハッシュ値の計算
	size_t hash_value1 = hash_function(data1);
	size_t hash_value2 = hash_function(data2);

	// ハッシュ値の表示
	cout << bitset<40>(hash_value1) << " : " << hash_value1 << endl;
	cout << bitset<40>(hash_value2) << " : " << hash_value2 << endl;

	return 0;
}

どちらも同じ値ですが、どうなるでしょう。

生成されたハッシュ値を見てみましょう。

0000000000101011101110101111100110110000 : 733673904 // 1回目
0000000000101011101110101111100110110000 : 733673904 // 2回目

まったく同じハッシュ値が生成されていますね。

これらのことから、ハッシュ関数はどうやらランダムな処理ではないということがわかりますね。

入力データに対し、あるきまった処理をしていると予想がつきます。

このように、ハッシュ関数は、同じ入力データに対しては同じ出力を返します。

似ているようなデータでも全く異なるハッシュ値を生成する

では、つぎは似たような文字列データを入れてみましょう。

int main()
{
	// データ
	string data1 = "吾輩は猫である。名前はまだ無い。";
	string data2 = "吾輩は犬である。名前はまだ無い。";

	// ハッシュ関数
	hash<string> hash_function;

	// ハッシュ値の計算
	size_t hash_value1 = hash_function(data1);
	size_t hash_value2 = hash_function(data2);

	// ハッシュ値の表示
	cout << bitset<40>(hash_value1) << " : " << hash_value1 << endl;
	cout << bitset<40>(hash_value2) << " : " << hash_value2 << endl;

	return 0;
}

「猫」の部分を「犬」にしてみました。

文字列的には一文字違いという些細な違いですね。

そうすると、やはりハッシュ値も「少しぐらい」異なるのでしょうか?

生成されたハッシュ値を見てみましょう。

0000000011111111011001110101101110101100 : 4284963756 // 猫
0000000011011101000010001010110101100010 : 3708333410 // 犬

生成されたハッシュ値は「全くといっていいほど違う値」になりました。

このように、ハッシュ関数は、似たような値でも少しでも異なれば全く異なるハッシュ値を生成します。

ハッシュ関数は入力データの大きさによらず固定長の出力を返す

次は、先ほどよりもいくら長い文字列データを入れてみることにします。

以下のような長文を入れてみることにしました。(コード略)

吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。

これを入れてハッシュ値を計算してみました。

0000000011111111011001110101101110101100 : 4284963756 // 短文
0000000001001110001110110110001001111100 : 1312514684 // 長文

短文でも長文でもビット幅が足りないということはなさそうですね。

結果から言えば、これまでのハッシュ値はすべて、32ビットで収まっています

これから考えるに、C++のハッシュ関数固定長が32bitのハッシュ値を返すアルゴリズムになっていそうですね。

このように、ハッシュ関数は、あらかじめ決められた固定長の出力を返します。

「ハッシュ関数」「ハッシュ値」の関係性

ここで、もう一度「ハッシュ関数」「ハッシュ値」の関係を確認しておきましょう。

「ハッシュ関数」:ある計算によって入力データから決められた長さの出力データを得る関数
「ハッシュ値」:ハッシュ関数から生成される値

この意味が理解できましたでしょうか。

ざっくりとで大丈夫だと思います。

ここからは、「ハッシュ関数」「ハッシュ値」にはどんな性質があり、どんなふうに使われているのかを紹介しようと思います。

まず先に、「ハッシュ関数、ハッシュ値にどんな性質があるのか」からです。

ハッシュ関数の特徴・性質3つ

ハッシュ関数には、とても面白い性質があります。

この性質はいろいろな用途へと利用され、現在のセキュリティ技術などに貢献しています。

ここでは、ハッシュ関数の3つの性質をご紹介します。

ハッシュ関数の3つの性質
  • 入力するデータが少しでも違うと全く異なるハッシュ値を生成する
  • 入力するデータの大きさにかかわらず一定の長さのハッシュ値を生成する
  • 任意のハッシュ値を生成するのが困難

それぞれ紹介します。

入力するデータが少しでも違うと全く異なるハッシュ値を生成する

ハッシュ関数の性質その①は、

「入力するデータが少しでも違うと全く異なるハッシュ値を生成する」ということです。

これはさきほど「猫」と「犬」で確認した通りです。

もっといえば、ある1ビットが反転していただけでも、生成されるハッシュ値は全然違います

このように、少しの違いでもハッシュ値には大きな影響を及ぼします

入力するデータの大きさにかかわらず一定の長さのハッシュ値を生成する

ハッシュ関数の性質その②は、

「入力するデータの大きさにかかわらず一定の長さのハッシュ値を生成する」ということです。

これはさきほどの長文で確認した通りです。

長い文字列でも、短い文字列でも、一定の長さのハッシュ値を生成します。

今回用いたC++のhashは、32bitでしたね。つまり、

「00000000 00000000 00000000 00000000」~「11111111 11111111 11111111 11111111」

32bitの出力です。(正確に確認してはいないですがそうだと思います。)

どんなに大きな値を入れようとも、ハッシュ値はこのなかに収まります。

これは、大容量のデータでも同じことが言えます。

なので、ハッシュ値を計算すると、圧倒的にコンパクトなbit列に収まるというメリットがあります。

任意のハッシュ値を生成するのが困難

ハッシュ関数の性質その③は、

「任意のハッシュ値を生成するのが困難」ということです。

言い換えれば、「どんなデータならばこのハッシュ値になるだろうか」という予想がつかないということです。

この性質が、セキュリティの技術に活きてきます。

ハッシュ関数の用途3つ

ハッシュ関数の用途は多岐にわたります。

今回は、主なハッシュ関数の用途3つを紹介します。

主なハッシュ関数の用途
  • 暗号化技術・セキュリティ
  • データの検証用・整合性チェック
  • ハッシュテーブル

暗号化技術・セキュリティ

ハッシュ関数の用途として、暗号化技術があります。

主に「改ざんされているかいないかの確認」です。

例えば、今話題のブロックチェーン技術情報セキュリティでは欠かせない「電子署名といった技術にもそのような用途で使われています。

今後記事を追加する予定です。

あわせて読みたい
ブロックチェーンとは?仕組みやメリットをわかりやすく解説!
ブロックチェーンとは?仕組みやメリットをわかりやすく解説!ブロックチェーンとは何かを知りたい方!ブロックチェーンの構造や仕組みを知りたい方!ブロックチェーンの特徴やメリットを知りたい方!ブロックチェーンは何に使える...

※「電子署名の解説記事」近日公開。

データの検証用・整合性チェック

別のハッシュ関数の用途として、データの検証があります。

例えば、大容量かつとても重要なデータをダウンロードしてくるときに活躍します。

私が普段使う例でいえば、OSのダウンロードです。

OSというのは、パソコンを動かすとても重要なソフトウェアであり、データの欠損やウイルスの混入といったことは許されません。

しかも結構容量が大きいです。

私は、OSのダウンロードが終わり次第、ダウンロードしたデータのハッシュ値を計算します。(そういう機能があります。)

そして、計算したハッシュ値を、公式サイトで掲載されているハッシュ値と見比べます

これで、その値があっていれば、ちゃんとダウンロードできたということになり、違っていれば公式サイトのデータとはどこかが異なっているということになります。

これは、ハッシュ関数の持つ「入力するデータの大きさにかかわらず一定の長さのハッシュ値を生成する」という性質のおかげです。

つまり、大容量のデータを超シンプルに表した「ハッシュ値」という存在のおかげでダウンロードがしっかりできたか否かを判別できるのです。

ごくまれに、違うデータでもハッシュ値が被ること(ハッシュ値の衝突)がありますが、こういった場面では気にならないほどです。

ハッシュテーブル

別のハッシュ関数の用途として、ハッシュテーブルという技術があります。

これは少し難しいのですが、データ検索の高速化の技術とでもいえばよいでしょう。

今後記事を追加する予定です。

※「ハッシュテーブル解説記事」近日公開。

まとめ

今回は、「ハッシュ」というワードについて解説しました。

まず初めに、ハッシュの意味や「ハッシュ関数」「ハッシュ値」といったワードの関係性を紐解きました。

ハッシュとは何なの!?
  • ハッシュの日本語になおすと「細切れ」「寄せ集め」といった意味。
  • ハッシュ関数とは、ある計算によって入力データから決められた長さの出力データを得る関数である。
  • ハッシュ値とはハッシュ関数から生成される値である。

次に、ハッシュ関数の性質という側面に注目しました。

ハッシュ関数の3つの性質
  • 入力するデータが少しでも違うと全く異なるハッシュ値を生成する
  • 入力するデータの大きさにかかわらず一定の長さのハッシュ値を生成する
  • 任意のハッシュ値を生成するのが困難

最後に、ハッシュ関数がどんなところに使われているのかという側面に注目しました。

主なハッシュ関数の用途
  • 暗号化技術・セキュリティ
  • データの検証用・整合性チェック
  • ハッシュテーブル

ここまでで解説を終わります。

以下は余談です。

私は大学の授業で聞いて、「ハッシュ関数」や「ハッシュ値」をなんとなくわかっていました。

そんな時に、ブロックチェーン技術の仕組みを調べていて「ハッシュ」が出てきたのでさらに興味を持ち、再勉強をしました。

もしかしたら、ここが違うよ!というところがあるかもしれませんので、見つけたらTwitter(@ima_maru)までリプライをくださいませ!

以上「ハッシュ関数とハッシュ値とは?用途や性質もわかりやすく解説!」でした!

いまいのアイコン画像いまい
最後までご覧いただきありがとうございます。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
タップして好きなところから読めます
閉じる