No293 サンプルで理解するハッシュ関数
このメルマガではハッシュ関数に関する解説を今までに何度かお送りしています。
ですが、ハッシュ関数とは何か?までは解説していますが、実際の計算方法については一度もお話ができていません。
今回はその解説を行います。
ハッシュ関数って何?どこで使うの?
ハッシュ関数というのは、元の情報をルールに従って計算する計算方法のことを言います。この計算結果を「ハッシュ値」と呼びます。
なんとか関数というと数学の公式のようなものをイメージされるかもしれませんが、そんな大層なものではないです。単にハッシュ値を得る計算方法の総称です。
もっとも、ハッシュ関数と「関数」が付きますので、数学がらみの用語であるのは確かです。
さて、このハッシュ値を自分自身で使ってる方はごく少ないのですが、皆さんのパソコンの中では毎日のようにハッシュ関数が使われています。
皆さんも日常的にインターネット上のニュースやSNS(Facebook、Twitterなどのソーシャルネットワークサービス)を使っていますよね?
こういったサービスではHTTPSという通信方法を使うのですが、このHTTPSでは内部でハッシュ関数を使いまくっています。
数回前のメルマガ(No290 意外に難しい乱数の話)でも書きましたが、コンピュータにとってはランダムな値を得るということは非常に難しいのです。
一方、質の良いハッシュ関数はランダムとしか思えないような値を簡単に得ることができます。このハッシュ関数の特徴をうまく活かすことでHTTPSでは高い暗号強度の通信を実現しています。
超絶シンプルなハッシュ関数
上記のHTTPSなどで使われる実用的なハッシュ関数というのは、かなり複雑な仕組みとなっています。これを詳細にお話しても退屈ですのでここでは触れません。
ただ、そのエッセンスは意外にシンプルです。
論より証拠。
まず、最初に超絶シンプルなハッシュ関数(ハッシュA)を定義しましょう。
ハッシュA:与えられた全ての値を足す。
さて、このハッシュAに以下のデータを与えてみます。
1 2 3 4 5 6 7 8 9
ハッシュAでハッシュ値を求めてみます。
1+2+3+4+5+6+7+8+9 = 45
となりますので、ハッシュ値は 45 です。
「なんだよ、それ。これが何の役に立つの?」とお考えでしょうか?
こんな単純なハッシュ関数でもメリットがあります。
全データを検査しなくてもハッシュ値だけで(ある程度)データの正しさが検証できることです。
例えば、与えたデータが次のように末尾だけ違っていたとします。
1 2 3 4 5 6 7 8 8
当然、ハッシュAの結果は違ってきます。
1+2+3+4+5+6+7+8+8 = 44
となり、ハッシュ値は 44 です。
全てのデータをつぶさに見なくても、ハッシュ値を見るだけで元データが違っていることがわかります。
ところで、このハッシュAには致命的な欠点があります。
それは、値が入れ換わっていると差異が検出できないという点です。
例えば、与えたデータの末尾が入れ換わっていたとします。
1 2 3 4 5 6 7 9 8
この場合、ハッシュAの計算は次のようになります。
1+2+3+4+5+6+7+9+8 = 45
となり、元データが違っているにも関わらず、得られるハッシュ値が同じになってしまいます。
前章で書いた通り、質の良いハッシュ関数にはランダムとしか思えないようなハッシュ値が得られることを求められています。これは暗号強度を保つために決定的に重要です。
その意味ではこのハッシュAは全くハッシュ関数として目的が達成できていません。
ちょっと改善したハッシュ関数
さすがにハッシュAは単純すぎました。
なので、ハッシュBを定義します。
ハッシュB:足し算と引き算を交互に行う
今度はどうでしょうか。
ハッシュBに以下のデータ(最初と同じパターン)を与えます。
1 2 3 4 5 6 7 8 9
1+2-3+4-5+6-7+8-9 = -3
今度はハッシュ値が -3 となりました。
次に末尾が8のケースです。
1 2 3 4 5 6 7 8 8
1+2-3+4-5+6-7+8-8 = -2
ハッシュ値は -2 となりました。
さらに末尾を入れ換えるとどうなるでしょうか?
1 2 3 4 5 6 7 9 8
1+2-3+4-5+6-7+9-8 = -1
ハッシュ値は -1 となりました。
今度は最初のハッシュAより、スジが良さそうです。
ですが、末尾をこんな風に入れ換えると...
1 2 3 4 5 8 9 6 7
1+2-3+4-5+8-9+6-7 = -3
ハッシュ値は -3 になってしまいました。
ハッシュBもやはり優秀とは言えません。
もうちょっと工夫したハッシュ関数
めげずにもう一種類考えてみます。
今度はハッシュCです。
ハッシュC:全ての値を10倍してから足す
これならどうでしょうか?
1 2 3 4 5 6 7 8 9
1 + 20 + 300 + 4,000 + 50,000 + 600,000 + 7,000,000 + 80,000,000 + 900,000,000
= 987654321
1 2 3 4 5 6 7 8 8
1 + 20 + 300 + 4,000 + 50,000 + 600,000 + 7,000,000 + 80,000,000 + 800,000,000
= 887654321
1 2 3 4 5 8 9 6 7
1 + 20 + 300 + 4,000 + 50,000 + 800,000 + 9,000,000 + 60,000,000 + 700,000,000
= 769854321
今度は3パターンとも値が異なっています。(やたらと大きな値になりましたが)
ハッシュA、ハッシュBに比べれば、かなり質は良さそうですが、元データが増えれば増えただけ大きな値になってしまいますので、これはこれで問題があります。
現実的な品質のハッシュ関数
ここまでハッシュAからハッシュCまで3パターンのハッシュ関数の計算を行ってきました。
ここではごく単純なものしか書いていませんが、元データによって異なるハッシュ値を得られるようなハッシュ関数を考案することはかなり難しそうだ、というのはご理解いただけたのではないかと思います。
実際、現状で使われているハッシュ関数はSHA256(シャー256)などの数少ない方式に限られています。
まとめ
ハッシュ関数というのは、ハッシュ値という値を求めるための計算方法のことを示します。
コンピュータはランダムな値を得ることが極端に苦手です。
一方で、暗号化を行った時の暗号強度の向上のためには、ランダムな値を使って暗号化を行うことがとても大切です。(いくら優秀な暗号方式だって、鍵がランダムでなければ、カンタンに解けてしまいます)
このランダム値を得る方法としてハッシュ関数が頻繁に使われています。
皆さんが日常的にアクセスしているインターネットのサイトもその大半が暗号化通信を行っていて、その裏方にはハッシュ関数が大活躍をしています。
今回はそんなハッシュ関数の基本的な考え方について解説しました。
次回は、続編としてSHA256を中心にもう少し踏み込んだ解説をします。
次回もお楽しみに。
(本稿は 2023年2月に作成しました)
本Noteはメルマガ「がんばりすぎないセキュリティ」からの転載です。
当所はセミナーなどを通して皆さんが楽しく笑顔でITを利用いただくために、 難しいセキュリティ技術をやさしく語ります。
公式サイトは https://www.egao-it.com/ です。