今回はハッシュ値についてまとめてみます。
ハッシュ値から元の値を推測するのが難しいことは理解していましたが、いろいろ混乱するような性質があったため、改めて頭の整理を兼ねてこの記事にまとめました。
そもそもハッシュ値とは
ハッシュ関数という特別な関数にデータを入力して出力されるビット列のことです。広く使われているものとして、SHA-256、SHA-512、RIPEMD-160などがあります。
ハッシュ関数が出力するハッシュ値には、異なるデータから同じハッシュ値が生成されないという特徴があり、この「同じハッシュ値が生成されないこと」を衝突耐性と呼びます。
この特徴から、ハッシュ関数は入力データが少しでも変わると出力されるハッシュ値も大きく変わります。これを利用してデータの改ざんチェックやデジタル署名の作成にも応用されています。
ハッシュ値の性質
引用元:ハッシュ値にはたくさんの特徴や役割がある!具体的な使い方を理解しよう!
思った以上に色々な性質、特徴があった。
衝突発見困難性
衝突発見困難性とは、同じハッシュ値になる元データを求めようとしても、計算量が大きいために困難であることをいいます。セキュリティの点から、ハッシュ値が同じになるような元データを求めることが物理的に困難であることが性質として求められます。
簡単に言えば、異なるデータで同じハッシュ値を見つけるのが非常に難しいという性質です。
偶然、別々のファイルから同じハッシュ値が生成されるという衝突を意図的に探すのは非常に困難なので、データの改ざんを防ぐことができます。
原像計算困難性
原像計算困難性とは、あるハッシュ値について、その元データを求めようとしても、計算量が大きいために困難であることをいいます。ハッシュ値から元データの予測や分析、復元ができないことがハッシュ関数に求められます。
あるハッシュ値から元のデータを推測するのが非常に難しいという性質です。例えば、友達からハッシュ値を渡されて「元のデータを当ててみろ」と言われても無理ゲーということですね。
第2原像計算困難性
第2原像計算困難性とは、ある元データとそれに対するハッシュ値が与えられたときに、そのハッシュ値と一致するような別のデータを求めることが困難であることをいいます。一つ一つのハッシュ値がユニークなものである以上、同一のハッシュ値になるような元データを求められるようなことがあってはいけないためです。
既に出力されたハッシュ値と同じハッシュ値を持つ「別のデータ」を見つけるのが非常に難しいという性質です。これにより、悪意のある者が別のデータを作成してハッシュ値を偽装することを防ぐことができます。
Rubyでの計算方法
実際にRubyでハッシュ値を使う場合、標準ライブラリのdigestを利用して文字列からハッシュ値を計算できます。Ruby 3.3リファレンスマニュアル module Digest
主なハッシュ関数として、前述のSHA-256やSHA-512、RIPEMD-160が用意されています。
Digest::SHA256
Digest::SHA512
Digest::RMD160
メソッドにはdigest、hexdigestがあり、それぞれハッシュデータをバイナリデータで返すものと、16進数で返すものがある
// 組み込みライブラリではないので、requireが必要
require 'digest'
p Digest::SHA256.digest('Qiitaテストでございます')
p Digest::SHA256.hexdigest('Qiitaテストでございます')
実行結果
// digest
"\x1C\x01\x13d\xA1\xF4_\xFFEUgW\xC4[\xC1\xCE\x9FG\xFE\xDD\xA4Tk\xD3\x9ECouH:\xDC\xCE"
// hexdigest
"1c011364a1f45fff45556757c45bc1ce9f47fedda4546bd39e436f75483adcce"
今回はハッシュ関数について整理しました。
仕事で使うことも時折あるので、改めて頭の中を整理できて良かったと思います。
おしまい