いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

ハッシュ値を試す

 ハッシュ値について前、簡単に説明しました。
www.omoshiro-suugaku.com
「このデータは誰か改ざんしていないだろうか?」という疑問に対して、ハッシュ関数が答えてくれます。ハッシュ関数チェックサムのようなものです。チェックサムとは、データ(数値の並びです)たちの和です。40人の試験の結果をファイルに入力してどこかに保存しておきます。翌日そのファイルを開いたとき「夕べのうちに誰か改ざんしているかも知れない」と心配になることがあるかも知れません。そのため、入力したときに数値の合計を求めておくのです。それが1840だったとしましょう。翌日、合計を調べます。1843になっていたら「誰かがデータのどこかをいじった!」と分かります。これがチェックサムです。でももうお気づきのように1人を+3点、別の1人を-3点してあっても分かりません。A君とB君の得点を入れ替えても分かりません。こうしたときチェックサムの代わりに使うのがハッシュ値なのです。後で実例を挙げますが、うまくできていて、データのどこかを少しでも変えると値はまるで違ったものになってしまうのです。少し前はMD5などの計算法が使われていました。が、欠点が明らかになり、最近では前回少し書いたSHA256などが使われています。ハッシュ値は改ざんを積極的に防ぐのではなく、改ざんを検出します。MD5、SHA256などはハッシュ関数と呼ばれます。
 まずMD5を使ってみましょう。"konnnitiha"というデータからMD5ハッシュ値を求めます。

import hashlib
data = "konnnitiha"
hs = hashlib.md5(data.encode()).hexdigest())
print(hs)

実行結果は以下の通りです。
163e0e1fcac14b3332ff8ad04bca857f
次にデータを少し変えます。data = "konnnitihb" と変更すると実行結果は
b3aab9f6d55ed8831b0da4412eb0d7d7
です。データが一部でも変わると似ても似つかない値になることが分かります。
 ハッシュ関数としてSHA256を使うには以下のようにします。

import hashlib
data = "konnnitiha"
hs = hashlib.sha256(data.encode()).hexdigest())
print(hs)

実行結果は次です。
f5377a764c2e6246a1d511e23287d35ff00e2f6f41695f64c28b47937227f6e0
data = "konnnitihb" と変更すると
82b7e54c9ad9e9e9434568d3985b16bc8d67730499766ebcd5a29c52940c12b3
となり、データは1文字変えただけですがまるで違うハッシュ値になります。
 ハッシュ値チェックサムと同様、その値からもとのデータを(事実上)推測することができません。ウェブサイトなどでユーザーにパスワードを入力させ、登録してあるパスワードと比較して一致していたら正規のユーザーと判断する、というような仕組みを使っている場合、そのプログラムのソースが誰かの手に渡ればパスワードの一覧が流出、ということになります。しかし予めパスワードからハッシュ値を求めておき、ソースコードにはこのハッシュ値を書いておくことにすれば心配要りません。ユーザーが入力したパスワードからハッシュ値を求め、それを比較すればよいのです。

 ハッシュ値はメッセージダイジェストとも呼ばれます。データを「要約」したもの、ということですね。今回は短いデータを使いましたが、1万文字のデータでもハッシュ値のバイト数は変わりません。MD5は16バイト、SHA256は32バイト(256ビット)と決まっています。「要約」なのです。