以下の記事で、パスワードは平文で保存しないことと、パスワードを保護することは Webアプリケーション提供側の責任と解説しました。
では、具体的に安全なパスワードの保存方法について解説します。
まず、パスワードを、MD5, SHA1 などのハッシュ関数でハッシュ化すれば安全なのでしょうか?
ハッシュ関数とは、文字列の内容を一定長の文字列に変換する関数で、ハッシュ化された値をハッシュ値と呼びます。ハッシュ値から元の文字列を計算できないという一方向性が特徴です(不可逆的な一方向の関数)。
ハッシュ関数の定義からすると安全な方法のように感じますが、MD5, SHA1 によって作成されたハッシュ値は、レインボーテーブルを使用したレインボー攻撃という方法によって、短時間で解読されてしまいます。MD5, SHA1 はすでに脆弱な方式なのです。そのため、現在は通常のハッシュ化では SHA256 を使用することが推奨されます。
ですが、パスワードの保存には、BCrypt や PBKDF2、Argon2といったアルゴリズムを採用している、パスワードの保存に適したハッシュ関数を使用することが推奨されます。
各言語での具体的な実装は、以下の記事を参照してください。
今まではパスワードの保存方法について解説してきましたが、ここでパスワードの種類と長さについても触れておきたいと思います。
言うまでもなく、パスワードは文字の種類が増え、長くなれば、より強固なパスワードになります。なお、Amazon のパスワードは128文字も指定できるそうです。これを受けて、当サイトの推奨としてはパスワードの種類と長さを以下のようにしたいと思います。
- 全てのASCII文字を使用可能
- パスワードは最低8文字以上
- パスワードの最大長は128文字
パスワードの保存方法、パスワードの文字種類、パスワードの長さ。これらを組み合わせることで、安全なパスワードを持つ Webアプリケーションにすることができます。
- パスワードの保存方法は、パスワード専用ハッシュ関数の使用を推奨
- パスワードの文字種類は多く、パスワードは長く設定する
以下は、以前は推奨されていましたが、現在は推奨されない方法になります。ですが、パスワードを安全に保存する理解の助けになるよう記述を残しておきます。
パスワードを安全に保存するためには、最低限、「salt(ソルト)」とハッシュ関数を使用します。
salt とは一定長以上の文字列で、以下の要件を満たすものです。
- ユーザー毎に違うこと
- ある程度の長さがあること(20桁以上が目安)
当サイトでは、「体系的に学ぶ 安全なWebアプリケーションの作り方」に従って、salt はユーザー ID をSHA256 でハッシュ化したものを推奨します。salt は、乱数を生成してデーターベースのテーブルに保存することが一般的ですが、乱数がユーザー ID のハッシュ値より優位になるとはいいきれません。
salt は具体的には、以下のように処理します。
ハッシュ化パスワード = ハッシュ関数(salt + パスワード)
また、salt とともに「ストレッチング」を行うことも強く推奨します。
ストレッチングとは、以下の式の処理を 1,000 回繰り返してパスワードをより強力に保護する方法です。ストレッチングの回数は要件により検討が必要です。
ハッシュ値 = ハッシュ関数(計算後のハッシュ値 + salt + パスワード)
1,000 回もストレッチングを行うとサーバーの負荷が気になります。しかし、ノート PC 上の Java で 1,000 回ストレッチングを行いましたが、80ミリ秒程度の時間しかかかりませんでした。
ここで、セキュリティ企業のソフォスがストレッチングを 10,000 回以上行うことを最低条件としていることに注意を払いましょう。ソフォスは、2013 年 11 月の時点では 10,000 回以上と言っていますが、時間とともに回数を増やすことを勧めています。
背景には、2013 年 11 月の時点で 2 万ドルを下回る価格で、100,000,000,000 以上の SHA-256 ハッシュを毎秒計算できるハッシュクラッキングサーバーの存在があります。
なお、データベースに持つ項目は、以下のようにバージョン番号を持つとアルゴリズムの変更に対応できるようになります。
- ユーザーID
- バージョン番号(初期値:1)
- パスワード(処理済)
こちらの実装サンプルは、以下の記事で扱っていますので参考にしてください。
参考
Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。
コメント