今更ながら、ハッシュ化の手法を勉強中。
この世界にも歴史があって、いたちごっこで成長しているので、基礎的なことから知らないと全然話についていけないし、ググって得た知識が古いのか新しいのかも判断できない。(投稿する人のレベルもあるので、記事の投稿日時は頼りにならない。)
ということで、この記事は素人が書いています。
基本的に古い知識&間違いもあろうと思いますので、穏やかな目でご覧いただきご指導いただけると幸いです。m(_ _)m
IDとパスワードのハッシュ化について
- あるシステムへのIDとパスワードを、システム内で保持し、ユーザーが入力した際に照合することを考える。
- そのIDとパスワードの一覧・テーブルが丸っと流出した場合でも、「それでも割と安全、簡単にはログインはできない」と言える状態を目指す。
- 異なるユーザーが同じパスワードを使った場合、システム内に保持する文字列を一致させないようにする。なるべく。
- クラッカーが"cracker1"のパスワードを"password"とかでシステム登録して、そのハッシュを得られた場合、そのハッシュを持つ別のユーザーのパスワードが"password"であることがバレてしまうことを避けたい。
- memo
- 弱衝突耐性: 特定のハッシュを持つデータを求めることの難しさ
- こちらの方が難しい
- 強衝突耐性: 同じハッシュを持つ2つのデータの組を求めることの難しさ
- 23人集まると、誰かと誰かが同じ誕生日の2人がいる確率は50%以上で、意外と多いという話
- 弱衝突耐性: 特定のハッシュを持つデータを求めることの難しさ
有名なクラック手法
-
レインボーテーブル
- 仮のパスワードをたくさん用意する
- "abcd"とか、"password"とか、機械的に1文字ずつずらして自動生成したもの等を膨大に
- それらをすべてmd5、sha256などでハッシュ化して、仮のパスワードとハッシュ化した文字列の対応表を作っておく
- パスワード候補が多い場合はかなり時間はかかるが、クラッカー視点では、アタックとは別の時に延々とできるので、問題はない。
- 2012年の記事で、8文字英数字の総当たり(220兆パターン)のハッシュを20分で作れるパソコンの記述あり
- インターネット上でも簡単に入手できそう
- パスワード候補が多い場合はかなり時間はかかるが、クラッカー視点では、アタックとは別の時に延々とできるので、問題はない。
- 対応表を使い、流出して入手したデータのハッシュ値から、それに対応するパスワードを検索する
- 瞬間的に検索できる
- パスワードを手入力して、システムへログインする
- ⇒ これに対抗できる必要がある
- 仮のパスワードをたくさん用意する
- 伸長攻撃
- パスワードmに対するハッシュがわかった場合、mの後ろに文字を付けたハッシュも計算できるという特性を利用し、1文字とか短いパスワードのハッシュをもとにしてパスワードを延ばし(伸長)、長いパスワードのハッシュを計算する方法
- SHA1、SHA2、MD5などはこの特性を持つ。
対応方法
- salt
- 元のパスワードに、秘密の固定の文字列(saltと呼ぶ)を追加し、それをハッシュ化し、システム内に保持する
- これによりレインボーテーブルで復元できたとしても、元のパスワードに当たれない
- システム全体で1つのsaltを使うのでなく、IDからsaltを生成させる(つまりIDごとにsaltが違う)と、解読難易度がさらに上がる
- iteration
- 生成したハッシュを、元の文章だと思ってもう一度ハッシュ化する、これを繰り返す
- 繰り返す回数は秘密の回数
- 適切な回数は、1万、10万、と参考文献によってさまざまだが、コンピューターの性能に依存するので、おそらく年々上がる
- 一方、上げると突き合わせの時間がちょっと増える
- クラック側への影響ほどではないが
- HMAC(Hash Based Message Authentication Code)
- saltを固定値Aに対して排他的論理和をかけsalt-Aとし、固定値Bにも同様に算出しsalt-Bとする
- 元のパスワードにsalt-Aを加えハッシュ化し、h-Aとする
- h-Aにsalt-Bを加えハッシュ化し、h-Bとする
- h-Bを保存する
- ⇒ これにより、伸長攻撃に対する耐性と、強衝突耐性が上がる(らしい)
参考
- 【Cryptography】Pythonでデータを暗号化する
- 【Python】hashlibによるハッシュ化
- ソルトとハッシュ関数だけでパスワードをハッシュ化するのが微妙な理由
- いまさら聞けないパスワードの取り扱い方
素朴な疑問メモ
- iterationをしてる間の、例えば100回に一度、前半分と後ろ半分をごそっと入れ替えるとか、換字暗号化するとか、ハッシュ手法変えるとか、そういう非公開のローカルロジックを入れると、耐性がめちゃ上がるのでは?