パスワードハッシュの進化
パスワードハッシュアルゴリズムの選択についてのアドバイスを聞いたことがあるかもしれませんが、なぜそれらが推奨されているのか考えたことがありますか? この記事では、パスワードハッシュアルゴリズムの進化とその背後にある理由を探ります。
パスワードハッシュアルゴリズムの選択についてのアドバイスを聞いたことがあるかもしれませんが、なぜそれらが推奨されているのか考えたことがありますか? この記事では、パスワードハッシュアルゴリズムの進化とその背後にある理由を探ります。
パスワードハッシュとは、名前が示すように、パスワードからハッシュ値を計算するプロセスです。 ハッシュ値は通常、データベースに格納され、ログイン(サインイン)プロセス中に、ユーザーが入力したパスワードのハッシュ値が計算され、データベースに格納されているハッシュ値と比較されます。 一致する場合、ユーザーは認証されます。
パスワードハッシュアルゴリズムの進化に入る前に、それがなぜ必要なのかを理解することが重要です。
あなたがアカウントを登録したウェブサイトのユーザーであると想像してみてください。 ある日、ウェブサイトがハッキングされ、データベースが漏えいします。 ウェブサイトがパスワードをプレーンテキストで保存している場合、ハッカーはあなたのパスワードに直接アクセスできます。 多くの人々が複数のウェブサイトでパスワードを再利用しているため、ハッカーはこのパスワードを使用して他のアカウントに無許可でアクセスすることができます。 同じパスワード、または類似のパスワードをメールアカウントに使用している場合、状況はさらに悪化します。なぜなら、ハッカーはあなたのパスワードをリセットして関連アカウントをすべて乗っ取ることができます。
データ漏洩がなくても、大きなチームでは、データベースへのアクセスがある人は誰でもパスワードを見ることができます。 他の情報と比較して、パスワードは非常に敏感で、誰にもアクセスさせたくないものです。
パスワードをハッシュせずに保存するのは、初心者の間違いです。 残念ながら、「パスワードリークプレーンテキスト」で検索すると、Facebook, DailyQuiz, GoDaddyなどの大手企業がすべてプレーンテキストでのパスワード漏洩を経験していることがわかります。 他の多くの企業が同じエラーを犯している可能性があります。
これら三つの用語はしばしば混同されますが、それぞれ異なる概念です。
エンコーディングは、パスワードの保存から最初に除外するべきものです。 例えば、 Base64は、バイナリデータを文字列に変換するエンコーディングアルゴリズムです:
エンコーディングアルゴリズムを知っていれば、誰でもエンコードされた文字列をデコードして元のデータを取得することができます:
ハッカーにとって、ほとんどのエンコーディングアルゴリズムはプレーンテキストと同等です。
ハッシュが一般的になる前に、パスワードの保存には暗号化が使われていました。例えばAESなどです。暗号化は、鍵(または鍵のペア)を使ってデータを暗号化・復号化することを含んでいます。
暗号化の問題点は、「復号化」の用語に明らかに表れています。暗号化は可逆的で、ハッカーが鍵を手に入れたらパスワードを復号化し、プレーンテキストのパスワードを取り出すことができます。
ハッシング、エンコーディング、暗号化の主な違いは、ハッシングが不可逆であることです。パスワードが一度ハッシュ化されると、元の形に戻すことはできません。
ウェブサイトの所有者として、ユーザーが正しいパスワードでログインできる限り、パスワード自体を知る必要はありません。登録プロセスは以下のように単純化することができます:
ユーザーがログインするとき、プロセスは以下のとおりです:
両方のプロセスはパスワードをプレーンテキストで保存することを避けており、ハッシュ化は不可逆であるため、データベースが侵害されても、ハッカーはランダムな文字列として表示されるハッシュ値しか得ることができません。
ハッシングがパスワードの保存に最適な解決策のように思えるかもしれませんが、それほど単純なものではありません。その理由を理解するために、パスワードハッシュアルゴリズムの進化を探してみましょう。
1992年、ロン・リーベストは、任意のデータから128ビットのハッシュ値を計算できるメッセージダイジェストアルゴリズムである MD5 アルゴリズムを設計しました。 MD5はパスワードハッシュを含むさまざまな分野で広く使用されていました。例えば、"123456"のMD5ハッシュ値は次のようになります:
前述のように、ハッシュ値はランダムな文字列として表示され、不可逆です。さらに、MD5は速く、実装が簡単なため、もっとも人気のあるパスワードハッシュアルゴリズムとなりました。
しかし、MD5の利点はパスワードハッシュにおいても欠点となります。その速度から、ブルートフォース攻撃に弱いです。ハッカーや攻撃者が一般的なパスワードのリストとあなたの個人情報を持っていれば、それらの組み合わせそれぞれのMD5ハッシュ値を計算し、データベースのハッシュ値と比較することができます。例えば、あなたの誕生日とあなたの名前、あるいはあなたのペットの名前を組み合わせてみることができます。
現代のコンピュータは以前よりもはるかに強力なため、MD5パスワードハッシュを総力戦で解くことは容易です。
では、より長いハッシュ値を生成する別のアルゴリズムを使ってみてはどうでしょうか? SHA ファミリーは良い選択肢に思えます。SHA-1は、160ビットのハッシュ値を生成するハッシュアルゴリズムで、SHA-2は、224ビット、256ビット、384ビット、512ビットの長さのハッシュ値を生成するハッシュアルゴリズムです。"123456"のSHA-256ハッシュ値を見てみましょう:
SHA-256のハッシュ値はMD5よりもはるかに長く、また不可逆です。しかし、別の問題があります:すでにハッシュ値を知っている場合、例えば上記のようなハッシュ値を見て、データベース中で正確に一致するハッシュ値を見つけたら、パスワードが"123456"であることがわかります。ハッカーは一般的なパスワードとそれに対応するハッシュ値のリストを作成し、それをデータベースのハッシュ値と比較することができます。このリストはレインボーテーブルと呼ばれます。
レインボーテーブル攻撃を緩和するために、Saltという概念が導入されました。Saltは、ハッシュ化する前にパスワードに追加されるランダムな文字列です。例えば、Saltが"salt"で、パスワード"123456"をSHA-256でハッシュ化する場合、以下のように行います:
ここで、結果はSaltなしのハッシュ化とはまったく異なることが確認できます。通常、各ユーザーには登録時にランダムなSaltが割り当てられ、ハッシュ値と共にデータベースに保存されます。ログインプロセス中、Saltは入力されたパスワードのハッシュ値を計算するために使用され、その後、保存されたハッシュ値と比較されます。
Saltが追加されたにも関わらず、ハードウェアがより強力になるにつれて、ハッシュ値はブルートフォース攻撃に依然として脆弱です。これをより難しくするために、反復(つまり、ハッシュアルゴリズムを何度も実行する)が導入されます。例えば、次のようにする代わりに:
次のようにすることができます:
反復回数を増やすことで、ブルートフォース攻撃がより困難になります。しかし、これはログインプロセスにも影響を与え、それが遅くなる可能性があります。したがって、セキュリティとパフォーマンスの間でバランスをとる必要があります。
休憩をとって、良いパスワードハッシュアルゴリズムの特性をまとめてみましょう:
お気づきのように、これらの要件すべてを満たすためには、Saltと反復が必要です。問題は、MD5とSHAファミリーはパスワードハッシュのために特別に設計されたものではなく、完全性チェック(または「メッセージダイジェスト」)に広く使用されていることです。その結果、各ウェブサイトは、Saltと反復の実装が異なり、標準化と移行が難しくなります。
この問題を解決するために、いくつかのハッシュアルゴリズムが特にパスワードハッシュのために設計されています。それらをいくつか見てみましょう。
bcryptは、Niels ProvosとDavid Mazièresによって設計されたパスワードハッシュアルゴリズムです。これは多くのプログラミング言語で広く使用されています。以下はbcryptハッシュ値の一例です:
もう1つのランダムな文字列のように見えますが、それは追加情報を含んでいます。それを分解してみましょう:
$2yはアルゴリズムを示し、それは2yです。$12は反復回数を示し、それは12です。これはハッシュアルゴリズムが212=4096回実行されることを意味します(反復)。wNt7lt/xf8wRJgPU7kK2juはSaltです。GrirhHK4gdb0NiCRdsSoAxqQoNbiluuはハッシュ値です。bcryptにはいくつかの制限があります:
既存のパスワードハッシュアルゴリズムの議論と制限を考えて、2015年に パスワードハッシュコンテストが開催されました。詳細は省略しますが、勝者であるArgon2に焦点を当てましょう。
Argon2は、Alex Biryukov、Daniel Dinu、Dmitry Khovratovichによって設計されたパスワードハッシュアルゴリズムです。いくつかの新しい概念を導入しました:
Argon2には、Argon2iとArgon2dの2つの主なバージョンがあります。Argon2iはサイドチャネル攻撃に対して最も安全で、Argon2dはGPUクラッキング攻撃に最高の耐性を提供します。
-- Argon2
Argon2ハッシュ値の一例を見てみましょう:
それを分解してみましょう:
$argon2iはアルゴリズムを示し、それはargon2iです。$v=19はバージョンを示しており、それは19です。$m=16,t=2,p=1はメモリコスト、時間コスト、並列度を示しており、それぞれ16、2、1です。$YTZ5ZnpXRWN5SlpjMHBDRQはSaltです。$12oUmJ6xV5bIadzZHkuLTgはハッシュ値です。Argon2では、パスワードの最大長は232-1バイト、Saltは232-1バイトに制限され、ハッシュ値は232-1バイトに制限されます。これはほとんどのシナリオで十分です。
Argon2は現在、多くのプログラミング言語で利用可能で、Node.jsのnode-argon2やPythonのargon2-cffiなどがあります。
年月を経て、パスワードハッシュアルゴリズムは大きな進化を遂げてきました。 インターネットをより安全な場所にするために、セキュリティコミュニティの長年の努力に感謝しなければなりません。 彼らの貢献のおかげで、開発者はパスワードハッシュのセキュリティを心配することなく、より良いサービスを構築することにもっと注力することができます。 システムの100%のセキュリティを達成することは不可能かもしれませんが、関連するリスクを最小限に抑えるための多様な戦略を採用することができます。
認証と認可の実装に手間をかけることなく、安全で信頼性があり、スケーラブルなソリューションを提供するLogtoを無料で試すことができます(我々はArgon2を使用しています!)。これにより、あなたは製品の構築に焦点を当てることができます。