日本語
  • 認証
  • パスワード
  • セキュリティ
  • ハッシング
  • bcrypt
  • argon2
  • sha1
  • sha2
  • ログイン
  • サインイン

パスワードハッシュの進化

パスワードハッシュアルゴリズムの選択についてのアドバイスを聞いたことがあるかもしれませんが、なぜそれらが推奨されているのか考えたことがありますか? この記事では、パスワードハッシュアルゴリズムの進化とその背後にある理由を探ります。

Gao
Gao
Founder

はじめに

パスワードハッシュとは、名前が示すように、パスワードからハッシュ値を計算するプロセスです。 ハッシュ値は通常、データベースに格納され、ログイン(サインイン)プロセス中に、ユーザーが入力したパスワードのハッシュ値が計算され、データベースに格納されているハッシュ値と比較されます。 一致する場合、ユーザーは認証されます。

パスワードハッシュアルゴリズムの進化に入る前に、それがなぜ必要なのかを理解することが重要です。

平文のパスワード:大きなセキュリティリスク

あなたがアカウントを登録したウェブサイトのユーザーであると想像してみてください。 ある日、ウェブサイトがハッキングされ、データベースが漏えいします。 ウェブサイトがパスワードをプレーンテキストで保存している場合、ハッカーはあなたのパスワードに直接アクセスできます。 多くの人々が複数のウェブサイトでパスワードを再利用しているため、ハッカーはこのパスワードを使用して他のアカウントに無許可でアクセスすることができます。 同じパスワード、または類似のパスワードをメールアカウントに使用している場合、状況はさらに悪化します。なぜなら、ハッカーはあなたのパスワードをリセットして関連アカウントをすべて乗っ取ることができます。

データ漏洩がなくても、大きなチームでは、データベースへのアクセスがある人は誰でもパスワードを見ることができます。 他の情報と比較して、パスワードは非常に敏感で、誰にもアクセスさせたくないものです。

パスワードをハッシュせずに保存するのは、初心者の間違いです。 残念ながら、「パスワードリークプレーンテキスト」で検索すると、Facebook, DailyQuiz, GoDaddyなどの大手企業がすべてプレーンテキストでのパスワード漏洩を経験していることがわかります。 他の多くの企業が同じエラーを犯している可能性があります。

エンコーディング v.s. 暗号化 v.s. ハッシング

これら三つの用語はしばしば混同されますが、それぞれ異なる概念です。

エンコーディング

エンコーディングは、パスワードの保存から最初に除外するべきものです。 例えば、 Base64は、バイナリデータを文字列に変換するエンコーディングアルゴリズムです:

エンコーディングアルゴリズムを知っていれば、誰でもエンコードされた文字列をデコードして元のデータを取得することができます:

ハッカーにとって、ほとんどのエンコーディングアルゴリズムはプレーンテキストと同等です。

暗号化

ハッシュが一般的になる前に、パスワードの保存には暗号化が使われていました。例えばAESなどです。暗号化は、鍵(または鍵のペア)を使ってデータを暗号化・復号化することを含んでいます。

暗号化の問題点は、「復号化」の用語に明らかに表れています。暗号化は可逆的で、ハッカーが鍵を手に入れたらパスワードを復号化し、プレーンテキストのパスワードを取り出すことができます。

ハッシング

ハッシング、エンコーディング、暗号化の主な違いは、ハッシングが不可逆であることです。パスワードが一度ハッシュ化されると、元の形に戻すことはできません。

ウェブサイトの所有者として、ユーザーが正しいパスワードでログインできる限り、パスワード自体を知る必要はありません。登録プロセスは以下のように単純化することができます:

  1. ユーザーがパスワードを入力します。
  2. サービスはハッシュアルゴリズムを使ってパスワードのハッシュ値を計算します。
  3. サービスはハッシュ値をデータベースに保存します。

ユーザーがログインするとき、プロセスは以下のとおりです:

  1. ユーザーがパスワードを入力します。
  2. サービスは同じハッシュアルゴリズムを使ってパスワードのハッシュ値を計算します。
  3. サービスはハッシュ値をデータベースに格納されているハッシュ値と比較します。
  4. ハッシュ値が一致する場合、ユーザーは認証されます。

両方のプロセスはパスワードをプレーンテキストで保存することを避けており、ハッシュ化は不可逆であるため、データベースが侵害されても、ハッカーはランダムな文字列として表示されるハッシュ値しか得ることができません。

初心者向けハッシュアルゴリズムパック

ハッシングがパスワードの保存に最適な解決策のように思えるかもしれませんが、それほど単純なものではありません。その理由を理解するために、パスワードハッシュアルゴリズムの進化を探してみましょう。

MD5

1992年、ロン・リーベストは、任意のデータから128ビットのハッシュ値を計算できるメッセージダイジェストアルゴリズムである MD5 アルゴリズムを設計しました。 MD5はパスワードハッシュを含むさまざまな分野で広く使用されていました。例えば、"123456"のMD5ハッシュ値は次のようになります:

前述のように、ハッシュ値はランダムな文字列として表示され、不可逆です。さらに、MD5は速く、実装が簡単なため、もっとも人気のあるパスワードハッシュアルゴリズムとなりました。

しかし、MD5の利点はパスワードハッシュにおいても欠点となります。その速度から、ブルートフォース攻撃に弱いです。ハッカーや攻撃者が一般的なパスワードのリストとあなたの個人情報を持っていれば、それらの組み合わせそれぞれのMD5ハッシュ値を計算し、データベースのハッシュ値と比較することができます。例えば、あなたの誕生日とあなたの名前、あるいはあなたのペットの名前を組み合わせてみることができます。

現代のコンピュータは以前よりもはるかに強力なため、MD5パスワードハッシュを総力戦で解くことは容易です。

SHA ファミリー

では、より長いハッシュ値を生成する別のアルゴリズムを使ってみてはどうでしょうか? SHA ファミリーは良い選択肢に思えます。SHA-1は、160ビットのハッシュ値を生成するハッシュアルゴリズムで、SHA-2は、224ビット、256ビット、384ビット、512ビットの長さのハッシュ値を生成するハッシュアルゴリズムです。"123456"のSHA-256ハッシュ値を見てみましょう:

SHA-256のハッシュ値はMD5よりもはるかに長く、また不可逆です。しかし、別の問題があります:すでにハッシュ値を知っている場合、例えば上記のようなハッシュ値を見て、データベース中で正確に一致するハッシュ値を見つけたら、パスワードが"123456"であることがわかります。ハッカーは一般的なパスワードとそれに対応するハッシュ値のリストを作成し、それをデータベースのハッシュ値と比較することができます。このリストはレインボーテーブルと呼ばれます。

Salt

レインボーテーブル攻撃を緩和するために、Saltという概念が導入されました。Saltは、ハッシュ化する前にパスワードに追加されるランダムな文字列です。例えば、Saltが"salt"で、パスワード"123456"をSHA-256でハッシュ化する場合、以下のように行います:

ここで、結果はSaltなしのハッシュ化とはまったく異なることが確認できます。通常、各ユーザーには登録時にランダムなSaltが割り当てられ、ハッシュ値と共にデータベースに保存されます。ログインプロセス中、Saltは入力されたパスワードのハッシュ値を計算するために使用され、その後、保存されたハッシュ値と比較されます。

反復

Saltが追加されたにも関わらず、ハードウェアがより強力になるにつれて、ハッシュ値はブルートフォース攻撃に依然として脆弱です。これをより難しくするために、反復(つまり、ハッシュアルゴリズムを何度も実行する)が導入されます。例えば、次のようにする代わりに:

次のようにすることができます:

反復回数を増やすことで、ブルートフォース攻撃がより困難になります。しかし、これはログインプロセスにも影響を与え、それが遅くなる可能性があります。したがって、セキュリティとパフォーマンスの間でバランスをとる必要があります。

ハーフタイムブレイク

休憩をとって、良いパスワードハッシュアルゴリズムの特性をまとめてみましょう:

  • 不可逆(原像抵抗性)
  • ブルートフォース攻撃が難しい
  • レインボーテーブル攻撃に耐性がある

お気づきのように、これらの要件すべてを満たすためには、Saltと反復が必要です。問題は、MD5とSHAファミリーはパスワードハッシュのために特別に設計されたものではなく、完全性チェック(または「メッセージダイジェスト」)に広く使用されていることです。その結果、各ウェブサイトは、Saltと反復の実装が異なり、標準化と移行が難しくなります。

パスワードハッシュアルゴリズム

この問題を解決するために、いくつかのハッシュアルゴリズムが特にパスワードハッシュのために設計されています。それらをいくつか見てみましょう。

bcrypt

bcryptは、Niels ProvosとDavid Mazièresによって設計されたパスワードハッシュアルゴリズムです。これは多くのプログラミング言語で広く使用されています。以下はbcryptハッシュ値の一例です:

もう1つのランダムな文字列のように見えますが、それは追加情報を含んでいます。それを分解してみましょう:

  • 最初のセクション$2yはアルゴリズムを示し、それは2yです。
  • 2つ目のセクション$12は反復回数を示し、それは12です。これはハッシュアルゴリズムが212=4096回実行されることを意味します(反復)。
  • 3つ目のセクションwNt7lt/xf8wRJgPU7kK2juはSaltです。
  • 最後のセクションGrirhHK4gdb0NiCRdsSoAxqQoNbiluuはハッシュ値です。

bcryptにはいくつかの制限があります:

  • パスワードの最大長は72バイトです。
  • Saltは16バイトに制限されます。
  • ハッシュ値は184ビットに制限されます。

Argon2

既存のパスワードハッシュアルゴリズムの議論と制限を考えて、2015年に パスワードハッシュコンテストが開催されました。詳細は省略しますが、勝者であるArgon2に焦点を当てましょう。

Argon2は、Alex Biryukov、Daniel Dinu、Dmitry Khovratovichによって設計されたパスワードハッシュアルゴリズムです。いくつかの新しい概念を導入しました:

  • メモリハード:このアルゴリズムは、パラレル化が難しく、GPUでのブルートフォース攻撃を困難にするように設計されています。
  • タイムハード:このアルゴリズムは、最適化が難しく、ASIC(Application-specific integrated circuits)を使ったブルートフォースを困難にするように設計されています。

Argon2には、Argon2iとArgon2dの2つの主なバージョンがあります。Argon2iはサイドチャネル攻撃に対して最も安全で、Argon2dはGPUクラッキング攻撃に最高の耐性を提供します。

-- Argon2

Argon2ハッシュ値の一例を見てみましょう:

それを分解してみましょう:

  • 最初のセクション$argon2iはアルゴリズムを示し、それはargon2iです。
  • 2つ目のセクション$v=19はバージョンを示しており、それは19です。
  • 3つ目のセクション$m=16,t=2,p=1はメモリコスト、時間コスト、並列度を示しており、それぞれ1621です。
  • 4つ目のセクション$YTZ5ZnpXRWN5SlpjMHBDRQはSaltです。
  • 最後のセクション$12oUmJ6xV5bIadzZHkuLTgはハッシュ値です。

Argon2では、パスワードの最大長は232-1バイト、Saltは232-1バイトに制限され、ハッシュ値は232-1バイトに制限されます。これはほとんどのシナリオで十分です。

Argon2は現在、多くのプログラミング言語で利用可能で、Node.jsのnode-argon2やPythonのargon2-cffiなどがあります。

結論

年月を経て、パスワードハッシュアルゴリズムは大きな進化を遂げてきました。 インターネットをより安全な場所にするために、セキュリティコミュニティの長年の努力に感謝しなければなりません。 彼らの貢献のおかげで、開発者はパスワードハッシュのセキュリティを心配することなく、より良いサービスを構築することにもっと注力することができます。 システムの100%のセキュリティを達成することは不可能かもしれませんが、関連するリスクを最小限に抑えるための多様な戦略を採用することができます。

認証と認可の実装に手間をかけることなく、安全で信頼性があり、スケーラブルなソリューションを提供するLogtoを無料で試すことができます(我々はArgon2を使用しています!)。これにより、あなたは製品の構築に焦点を当てることができます。