No183 暗号っぽいけど暗号じゃないハッシュ関数ってナニ?

ハッシュ関数というものがあります。
今まで「がんばりすぎないセキュリティ」で幾度となく使っている
のですが、きちんと解説をしたことがありませんでした。

わかってしまえばどうということはないのですが、わかりにくい
部分もありますので、改めて解説しておこうと思います。


1. ハッシュ関数って数学?

関数というくらいですから、やはり数学に関係があります。

ハッシュ関数というのは、元のデータをルールに従って加工して
コンパクトなデータを得る計算方法のことを言います。

この計算で得た値のことをハッシュ値と言い、元データからハッ
シュ値を計算することをハッシュ化と言います。

と言葉だけだとよくわからないので、具体的な例でいきましょう。

まず、次の文をハッシュ関数の一つSHA256でハッシュ化してみます。

「短かい文」
   ↓
 0c192fff778a2d4c78b68599c3c465b328359d117e7c903feb46c9ef2112752e

なんだかよくわからない英数字の列が出てきました。
これがハッシュ値です。
え?ますますわからないって?

まあ、もう少しおつきあいください。
次に、もう少し長い文をハッシュ化してみます。

「がんばりすぎないセキュリティはえがおIT研究所が提供する
 メールマガジンです。」
   ↓
 9409822023bf04c0ceb516de9a26fc8c3d835b47c5e3e926852973182bca7dfe

またしてもランダムとしか思えない英数字が出てきました。
それに、よく見ると最初のハッシュ値と同じ文字数じゃないですか。

次に、末尾を「。」から「.」に変えてみます。
「がんばりすぎないセキュリティはえがおIT研究所が提供する
 メールマガジンです.」
   ↓
 adf05da48ac982729069334b805cdae04392d5946a4e5ef04e1ac918243ac0c5

次に、途中に「、」を入れてみます。
「がんばりすぎないセキュリティは、えがおIT研究所が提供する
 メールマガジンです.」
   ↓
 22107920658c2a2c376e5f9e6d12de3feb0ac99149ffbc2194ad70f4b653746a

どうでしょう。
少し変えただけなのに、どれも全く違ったハッシュ値になっていて
長さはどれも同じです。

では、もっと長い文をハッシュ化したらどうなるでしょう。
本メルマガの前回分(No182)の本文(約5.5KB)をまるごとハッ
シュ化してみましょう。
   ↓
 d37fe05563dfb9f000b6e3c84acfb9e91db159a8217a877e7effebaf1410b767

やはりパターンは違いますが、長さは同じです。

ここで使ったSHA256 というハッシュ関数では長さが必ず64文字に
なります。これはそういう計算を行っているからです。

このように元のデータが違っていると、ハッシュ値もそれぞれ違っ
たものになるのです。元のデータの特徴を示す指紋のようなもの、
と言ってもいいかもしれません。


2. ハッシュ関数って何に使うの?

このハッシュ関数というのは、意外に昔からあるのですが、こんな
計算結果を一体何に使うのでしょうか?

指紋を本人特定に使うのと同じく、元データを識別する情報として
ハッシュ値を使うのです。

このようなハッシュ値の身近な例として、クレジットカードの番号
チェックがあります。

通信販売サイトなどで、間違ったクレジットカード番号を入力する
と、データベースを調べたわけでもなさそうなのに即座に「カード
番号が間違っています」と表示される場合があります。

これは、カード番号にはカード番号の正しさを検証するための値を
持っているからできるマジックなのです。
クレジットカードは通常16ケタですが、そのうち1ケタは検証専用
となっています。
ですから、16ケタのうち先頭15ケタでちょっとした計算(足し算と
掛け算など)をした結果が、末尾の1ケタが合致していればOK、
不一致なら入力ミスが検出できるようになっているのです。

また、おなじみのバーコードも13ケタの数字のうち末尾の1ケタが
検証専用です。バーコードリーダで読み込んだ値から検算を行い、
末尾の1ケタと合わなければ読み込みエラーとわかる仕組みです。

1ケタの数字だけとはいえ、これはどちらもハッシュ値と言えます。


3. インターネットでのハッシュの使い方

では、上で書いたような64文字もの長いハッシュ値を一体どこで使うので
しょうか?インターネット上でそんなハッシュ値が便利なシーンがあるというのでしょうか?

その典形的な利用方法の一つにパスワードのやりとりがあります。

実はハッシュ関数を使うと、パスワードを送信せずにパスワードを伝え
られるのです。禅問答みたいですが、ホントにできるのですよ。

その手順は次の通りです。

今回の登場人物は利用者とサービスのシステムで、利用者はIDとパスワードを持っていて、サービス側も同じIDとパスワードを知っているものとします。(別に言うまでもなくごく普通の仕組みですよね)

ハッシュ関数なしだと次のような形でログイン処理が行われます。

1)利用者はIDとパスワードを入力し、それをサービス側に送ります。
  ※当然ですが、生のパスワードが回線上を流れます
2)サービス側はIDとパスワードを受け取りします。
3)サービス側は利用者IDを調べ、そのパスワードが正しければログイン
  を許可します。

ここまではごくあたりまえのことです。
一方、ハッシュ関数を使ってログインは次の通りです。

1)利用者がIDとパスワードを入力するとブラウザはパスワードをハッシュ
  化し、IDといっしょに送ります。
  ※生のパスワードは回線上を流れません。
2)サービス側はIDとハッシュ化したパスワードを受け取ります。
3)サービス側は利用者IDを調べ、そのパスワードを得ます。
4)サービス側はパスワード調べてハッシュ化します。
  (数学ですから、同じ手順でハッシュ化すれば必ず同じ結果です)
5)サービス側は受けとったハッシュ値と自分で計算したハッシュ値を
  比べ、一致していればログインを許可します。

このような手順を取れば、パスワードをネットワーク上に流すこと
なく、安全に本人確認が行えるわけです。

同時に64文字もの長いハッシュ値を使う理由もこれでわかるでしょう。
パスワードのハッシュ値が数字1ケタだと、10回やれば必ずログイン
できます。これは危険すぎますよね。

以下、余談です。
 実はこの方法だけではあまり安全とは言えません。
 この方法だとハッシュ値がいつも同じ値になるので、誰かに盗聴
 されると、パスワードなど知らなくてもハッシュ値でログインが
 できてしまいます。

 ですので、現実にはもう一捻りした方法を取ります。
 1)サービス側がランダムな値を利用者に送ります。
 2)利用者がIDとパスワードを入力します。
 3)ブラウザはパスワードにランダムをつないでからハッシュ化し、
   IDといっしょに送ります。
 4)サービス側はIDとハッシュ化したパスワードを受け取ります。
 5)サービス側は利用者IDを調べ、そのパスワードを得ます。
 6)サービス側はパスワード調べ、それにランダムをつないでから
   ハッシュ化します。
 7)サービス側は受けとったハッシュ値と自分で計算したハッシュ
   値を比べ、同じであればログインを許可します。

 これだと、パスワード+ランダム値でハッシュ値を求めますから、
 ログインの都度ハッシュ値も変わります。盗聴されても次回には使え
 ませんから安心なわけです。

これ以外に電子署名でもハッシュが活躍しますが、手順がかなり
複雑ですので、この仕組みについては別の機会に解説をしたいと
思います。

「ハッシュすごい。でもそれなら鍵交換もいらないのでは?」と
思われた方、残念ながらそうはいきません。

ハッシュ化では双方が元データを既に持っていることが前提です。
上の例ではパスワードを両者が持っているわけです。
それに対して鍵交換では、両者が共有できていない鍵を共有する
ことが目的ですから、ハッシュ化は鍵交換の代用にはなりません。

また、この方法をひと捻りするとシステムに不正侵入された時に
パスワード漏洩するリスクを避けられます。

つまり、サービス側ではパスワードそのものではなくハッシュ化
した状態のパスワードを覚えておくわけです。
存在しないパスワードはばれようがありませんからね。

さらに余談ですが、サービス側がハッシュ化したパスワードしか
保管していない場合、パスワードを忘れた利用者に対してもパス
ワードを教えられません。だってホントに生のパスワードは知ら
ないのですから。


4. ハッシュ関数と暗号化の違い

ハッシュ関数というのは暗号化の話の中でよく出てきますので、
ハッシュ化と暗号化を混同されている方がおられますが、
この二つは全く性質が違います。

暗号化データは復号(元に戻すこと)できます。
ですが、ハッシュ化したデータは元に戻せません。

どういうことでしょうか?

一般的に情報を暗号化しても含まれる情報量は変わりませんから、
元のサイズと同じサイズになります。(微妙に大きくなる程度)

ですが、一般的にハッシュ化を行うと固定サイズになります。
例えば SHA256 という方式でハッシュ化すれば、結果は必ず256ビット
(=32バイト)になります。
100Mバイトのデータでも32バイト、10ケタのパスワードでも32バイト
になるということで、最初から元に戻すことなど考えられていない
のです。

暗号化は復号できる変換ですから「可逆変換」と言い、ハッ
シュ化は元に戻せない変換なので「不可逆変換」と言います


5. ハッシュ関数の種類

最後に、インターネット上で実際に使われるハッシュ関数について
書いておきます。
これを書いている2020年時点では、ハッシュ関数はSHA2(シャーツー)
にほぼ集約されています。

以前はMD5(エムディーファイブ)やSHA1(シャーワン)もよく使
われていたのですが、いずれも役割を終えつつあります。

名前からわかると思いますが、SHA2というのはSHA1の後継です。
さらにその後継のSHA3も既に規定されているのですが、現時点では
SHA2でも安全と考られており、スグにSHA3に移行ということには
なっていません。

このSHA2にはいくつかのバリエーションがあり、256ビットのハッ
シュ値を得るSHA256、その512ビット版のSHA512の2つがよく利用
されています。

ただ、こういった安全性に関しては急に変わる場合があります。
それは専門家が集まる学会などで、安全性を疑われるような論文
が発表され、他の専門家も同意した時です。

実際にSHA1の時はそのような指摘があり、急速にSHA2に移行し
たのです。
このメルマガでもいつも言っていますが、特にセキュリティに関
しては情報の鮮度が非常に大切です。

皆さんもアンテナを高くして、情報収集を行ってください。

今回はハッシュ関数について解説をしました。
次回もお楽しみに。


この記事が気に入ったらサポートをしてみませんか?