安全でない(古い)暗号化ハッシュ関数を使用して、ユーザーアカウントのパスワードをデータベースに保存しています。
パスワードハッシュ関数を変更するための最良/通常のアプローチは何ですか?私の頭に浮かぶのは2つのアイデアだけです。
すべてのユーザーに次回のログイン時にパスワードを変更するように求め、パスワードを変更する場合は新しい機能でパスワードをハッシュします。これは、多くの問題(非アクティブなユーザー、長い移行期間、複雑な実装など)のため、適切なオプションではありません。
新しいハッシュ関数で古いハッシュ値をハッシュし、データベースに対してパスワードをチェックするメソッドを書き直します:newHash(salt + oldHash(salt + password))
このダブルハッシュは、エレガントで簡単に実装できる優れたアイデアのようです。
ここで気づいていない警告があるかどうか知りたいのですが。これは通常行われる方法ですか、それとも別の方法がありますか?弱いハッシュ関数の出力を強いハッシュ関数の入力として使用する際に、既知の暗号化の脆弱性はありますか?.
それが良い考えであるなら、塩はどうですか?両方のハッシュ関数に同じソルトを使用しても大丈夫でしょうか?
個人的には、新しいユーザーが強力な最新のハッシュ(bcryptまたは他のキー強化された暗号化ハッシュ)を取得する古いユーザーと、弱いユーザーがbcryptをラップしている古いユーザーの両方を実装するでしょう。人々が実装の複雑さに不満を言う前に、代わりに、常に新しいユーザーに強力なハッシュアルゴリズムにラップされた弱いハッシュアルゴリズムを使用するように強制することです。つまり、元のスキームがなくなることはありません。
私はcryptで$1$
、$2a$
、$5$
、または$6$
に類似したタイプハッシュスキームの文書化されたインジケーターを持っています(cryptのマニュアルページからの引用)。
If salt is a character string starting with the characters "$id$" fol‐
lowed by a string terminated by "$":
$id$salt$encrypted
... id identifies the encryption
method used and this then determines how the rest of the password
string is interpreted. The following values of id are supported:
ID | Method
─────────────────────────────────────────────────────────
1 | MD5
2a | Blowfish (not in mainline glibc; added in some
| Linux distributions)
5 | SHA-256 (since glibc 2.7)
6 | SHA-512 (since glibc 2.7)
この場合、3種類のパスワードハッシュが必要です。
1日目、カテゴリ1からすべてを取り出してカテゴリ2に移動します。新しいパスワードはカテゴリ3に入れられます。さらに、ログインすると、正常に認証されたすべてのハッシュをカテゴリ2からカテゴリ3に移行しながら、プレーンテキストパスワードはメモリにあります。ある時点で、弱いハッシュスキームの証拠/レガシーメンテナンスを完全に排除することもできます。 (たとえば、変更後2年以上ログインしていないアカウントを持つユーザーにパスワードのリセットを強制する)。
あなたの提案2(古いハッシュ値を新しいハッシュの「パスワード」として使用する)は適切ですif以下の条件がすべて当てはまります。
MD5は衝突に関しては完全に壊れていますが、プリイメージに関してはまだかなり強いように見えます。
移行をスムーズに処理できるように、データベースに「ハッシュのタイプ」フィールドを含めることは、それでも最善の方法です。たとえば、ハッシュオブハッシュを適用し、新しいハッシュのみを使用するパスワードハッシュスキームへの移行を計画できます。パスワードは、作成または変更されるたびに新しいスキームに更新されます。段階的な移行。後で(たとえば1年後に)、古い形式を使用しているパスワードの強制更新(ユーザーは次回ログイン時にパスワードを再入力する必要があります)をセットアップできます。
移行が気に入らなくても(誰が?)、その時の状況によって移行が強制される場合(例:壊滅的な暗号解読)、将来の移行の可能性に備えて準備するのが賢明なようです。
新しいハッシュとして bcrypt を使用します。それ以外の場合、bcryptに適切なソルトを使用すれば、古いハッシュを「ラップ」するソリューションは安全になります。システムがパスワードをハッシュする方法をアップグレードしたいときに、このソリューションが数回うまくいくことを確認しました。
古いハッシュ関数を使用したくないが、全員にパスワードの変更を強制したくない場合は、エレガントな解決策が1つあります。
すべてのユーザープロファイルに列/値を追加します。 HashVersionなら呼び出しましょう
移行後、ユーザーが初めてログインすると、システムは古いハッシュ関数を使用してそれを検出できます。したがって、ユーザーが指定したパスワードがハッシュと一致する場合は、プレーンテキストのパスワードを取得して、新しいアルゴリズムでハッシュし、ソルトなどをリセットします。次に、HashVersionを上げて、新しいハッシュ関数が使用されていることを確認します。
これは、私の意見では、特に以前のハッシュ関数が本当に安全でなかった場合、最良の解決策です。
古いハッシュが適切である限り(MD5またはDES-Cryptは問題ありませんが、CRC32は問題ありません)、このアプローチは安全です。同じソルトを使用しても問題は発生しません。ソルトが十分に優れている、つまり(ほぼ)グローバルに一意であると想定します。
外部ハッシュ関数については、scrypt、bcrypt、またはPBKDF2のいずれかを使用することをお勧めします。
この問題を解決した数十のオープンソースアプリケーションが見つかります。 Wordpressがすぐに思い浮かびますが、他にもあります。MicrosoftWindowsでもこれと同じ手法を使用しています。一般的な解決策は次のとおりです。
sha1:salt:_hash_output____
)または、データベースに新しいフィールドを追加して、ハッシュタイプを識別します。