Seita developer blog

ユーザ企業に努めるアプリケーションエンジニアがプログラミング、データベース、OS、SNS、ガジェットなどを中心に備忘録変わりに書いていきます。

【Tips】パスワードのデータベース保存の際のハッシュ化とソルト、ストレッチの考え方

今回はパスワードのハッシュ化保存に関する紹介です。

ユーザ情報のパスワードをデータベースに保存する際、平文(そのまま)保存するのは、現在のWebセキュリティの観点から非常に危険です。

普段実装する場合には「秘密鍵による暗号化」もしくは「ハッシュ化」をかけることが一般的ですが、今回はハッシュ化、またもう一つ踏み込んだ内容の紹介です。

 

[ハッシュ化]
特定のデータ(文字列やファイル)をハッシュにかけることにより固定長の文字列を得ることができます。

例えば「A」のMD5は「7fc56270e7a70fa81a5935b72eacbe29」が必ず返ってきます。

ただし、各言語仕様にごとに若干の差異が出てきます。

たとえば、Javaの標準APIでハッシュ化した場合、「JVM依存?」か、わかりませんが、String型のキャラクターセットに依存し、ハッシュ値が異なってくることがあります。

標準APIで実装する場合には、String型をキャラクタセットを明示的に指定しバイト配列に変換の上、ハッシュ化してください。

 ※もしくは「Apache Common Codec」を利用してください

なお、脆弱性の観点からハッシュ化アルゴリズムは「SHA-256」以上を推奨します。

 

[ソルト]

パスワードのハッシュ化は、パスワードの平文保存を避ける手段ではありますが前段で記述した「同じ文字列からは同じハッシュ値が必ず返ってくる」という特性があります。

つまり、パスワードが同じ人はハッシュ値が同じになり、例えば、私と読者が「abcde」というパスワードを使っていたとして、パスワードのハッシュ値が流出し、
私のパスワード(平文)が分かった場合、読者さんのパスワードもわかってしまいます。

それを避けるためにランダムな文字列を混ぜてハッシュ化し、それについても保存する考え方のことをソルトといいます。以下のような例を参考にしてください

 

  例) ※MD5をサンプルでは使っています。

     ・REY   パスワード: abcde ソルト:20160727

     ハッシュ化:"abcde"+"20160727"

       →ハッシュ値:c8e26fe1cc7ca77309ca11a8c6fe1ddd


     ・読者 パスワード: abcde ソルト:20160101

      ハッシュ化:"abcde"+"20160101"

       →ハッシュ値:46e70873b7b4d81641545775037ea43e

 

[ストレッチ]

文字列のハッシュ化には1つ問題があります。

それは「レインボーテーブル」とよばれるものであり、「1」....「x」と様々な文字列をあらかじめハッシュ化したものをデータベース化しておき、ディクショナリアタックのように使うという手法です。

 

たとえば、「REY」のMD5値は「f6e2516aa33fef5f8748da870d7ebf56」です。

しかし、これをグーグルで検索すると、以下のような形で、ハッシュ値がインターネット上で簡単に手に入ってしまいます。

 

www.hashhunters.net

 

 

f:id:rey1229:20160728104849p:plain

 

これを避けるために、「ストレッチ」とよばれるパスワードの隠ぺい方法があります。

ハッシュ化を複数回実施することでレインボーテーブルによるパスワードの逆算を防ぐ手法です。

ただし、「複数回ハッシュ化するアルゴリズム」自体がセキュア情報となるため注意が必要です。

 

[ハッシュ化の標準APIでの実装サンプル]

github.com

 

 

<参考>

www.atmarkit.co.jp

 

 

安全なパスワードの保存方法 | Webセキュリティの小部屋

 

www.atmarkit.co.jp