暗号化において、ソルトとは、データ、パスワード、またはパスフレーズをハッシュ化する一方向関数に追加入力として与えられるランダムなデータのことです。[ 1 ]ソルト処理は、攻撃を成功させるために必要なテーブルのサイズを大幅に増やすことで、事前に計算されたテーブル(レインボーテーブルなど)を使用する攻撃に対する防御に役立ちます。 [ 2 ] [ 3 ] [ 4 ]また、パスワードの各インスタンスに新しいソルトが使用されるため、データベース内で複数回出現するパスワードの保護にも役立ちます。[ 5 ]さらに、ソルト処理はユーザーに負担をかけません。
通常、各パスワードに対して一意のソルトがランダムに生成されます。ソルトとパスワード(またはキーストレッチ後のパスワード)を連結して暗号学的ハッシュ関数に入力し、出力されたハッシュ値をソルトとともにデータベースに保存します。ソルトは暗号化する必要はありません。ソルトを知っていても攻撃者にとって何の役にも立たないからです。[ 5 ]
ソルト処理は、 Unixシステムの認証情報からインターネットセキュリティまで、サイバーセキュリティの分野で幅広く利用されています。
ソルトは暗号学的ノンスに関連しています。
ソルトがない場合、同じパスワードは同じハッシュ値に対応するため、ハッカーがハッシュ値からパスワードを推測しやすくなる可能性があります。
その代わりに、ソルトが生成されて各パスワードに追加されるため、同じ元のパスワードでも結果として得られるハッシュ値は異なる値になります。
生成されたソルトとハッシュはデータベースに保存されます。ユーザーが入力したパスワードが正しいかどうかを後でテストするには、同じ処理(パスワードにユーザーのソルトを追加してハッシュを計算する)を実行できます。結果が保存されているハッシュと一致しない場合、入力されたパスワードは正しいものではなかったことになります。
実際には、ソルトは通常、暗号学的に安全な擬似乱数発生器(CSPRNG)を使用して生成されます。CSPRNGは、英数字を含む予測不可能な乱数を生成するように設計されています。セキュリティ上のリスクが高いため一般的には推奨されませんが、タイムスタンプや単純なカウンターをソルトの生成元として使用するシステムもあります。また、異なるシステムや期間にわたって一意性を確保するために、タイムスタンプやユーザー固有のデータなどの追加情報と乱数値を組み合わせてソルトを生成する場合もあります。
すべてのパスワードに同じソルトを使用することは危険です。なぜなら、ソルトのみを考慮した事前計算済みのテーブルがあると、ソルトが無効になってしまうからです。ただし、Pepper を参照してください。
パスワードごとに固有のソルトを持つデータベース用の事前計算済みテーブルを生成することは、計算コストが高すぎるため現実的ではありません。しかし、すべてのエントリに共通のソルトが使用されている場合、そのようなテーブル(ソルトを考慮したもの)を作成することは、実行可能で成功する可能性のある攻撃となります。[ 6 ]
ソルトの再利用によって、同じパスワードを使用しているユーザーが同じハッシュ値を持つ可能性があるため、単一のハッシュ値を解読すると、他のパスワードも漏洩する恐れがある。
ソルトが短すぎると、攻撃者は考えられるすべてのパスワードに付加されるすべての可能なソルトのテーブルを事前に計算する可能性があります。長いソルトを使用すると、そのようなテーブルが非常に大きくなることが保証されます。[ 7 ] [ 8 ] 16 バイト (128 ビット) 以上であれば、一般的に十分な大きさの可能な値空間が提供され、衝突 (つまり、2 つの異なるパスワードが同じソルトになる) のリスクが最小限に抑えられます。
単一のパスワードを解読する場合と、複数のパスワードを解読する場合の違いを理解するために、ユーザーとそのハッシュ化されたパスワードを含むファイルについて考えてみましょう。このファイルにソルトが使用されていないとします。この場合、攻撃者は文字列を選択し、それを と呼びattempt[0]、 を計算することができますhash(attempt[0])。ファイルに保存されているハッシュが であるユーザーは、hash(attempt[0])パスワード を持っている場合もあれば、持っていない場合もありますattempt[0]。しかし、attempt[0]がユーザーの実際のパスワードでなくても、システムは入力されたパスワードのハッシュを計算し、ファイルに保存されているハッシュと比較することによってのみパスワードをチェックできるため、 は実際のパスワードであるかのように受け入れられます。したがって、一致するたびにユーザーのパスワードが解読され、一致する確率はファイル内のパスワードの数とともに高くなります。対照的に、ソルトが使用されている場合、攻撃者は を計算しhash(attempt[0] || salt[a])、エントリ A と比較し、次に をhash(attempt[0] || salt[b])計算し、エントリ B と比較するなど、繰り返して計算する必要があります。これにより、ソルトの再利用が回避されれば、1回の試行で複数のパスワードを解読することはできなくなります。[ 9 ]
ソルトは、パスワードを解読するための事前計算済みテーブルの使用にも対抗します。[ 10 ]このようなテーブルは、一般的なパスワードをそのハッシュに単純にマッピングする場合もあれば、事前計算済みハッシュチェーンのセットの開始点と終了点を保存するなど、より複雑な処理を行う場合もあります。いずれの場合も、ソルトはハッシュを長くし、より大きな文字セットからハッシュを抽出させることで、事前計算済みテーブルの使用を防ぐことができます。これにより、テーブルが結果として得られるハッシュをカバーする可能性が低くなります。特に、事前計算済みテーブルは[salt + hash]単にではなく、文字列をカバーする必要があります[hash]。
パスワードハッシュやその他のセキュリティデータを非公開ファイルに保存する最新のシャドウパスワードシステムは、こうした懸念をある程度軽減します。しかし、集中型パスワード管理システムを使用して複数のシステムにパスワードやパスワードハッシュを配信するマルチサーバー環境では、これらの懸念は依然として重要です。このような環境では、各システムのrootアカウントは集中型パスワードシステムの管理者よりも信頼性が低いとみなされる可能性があるため、固有のソルト値の生成を含むパスワードハッシュアルゴリズムのセキュリティが十分であることを確認することが重要です。
ソルトのもう 1 つの (あまり重要ではない) 利点は次のとおりです。2 人のユーザーが同じ文字列をパスワードとして選択したとします。ソルトがない場合、このパスワードはパスワードファイルに同じハッシュ文字列として保存されます。これにより、2 つのアカウントが同じパスワードを使用していることが明らかになり、いずれかのアカウントのパスワードを知っている人は、もう 1 つのアカウントにアクセスできるようになります。2 つのランダムな文字でパスワードをソルトすると、2 つのアカウントが同じパスワードを使用していても、ハッシュを読み取るだけでは誰もそれを発見できません。ソルトを使用すると、ある人物が複数のシステムで同じパスワードを使用しているかどうかを判断することも非常に困難になります。[ 11 ]
初期のバージョンのUnixでは、パスワード ファイル を使用して/etc/passwd、ソルト付きパスワード (2 文字のランダムなソルトがプレフィックスとして付加されたパスワード) のハッシュを保存していました。これらの古いバージョンの Unix では、ソルトも、ソルト付きパスワードのハッシュとともに passwd ファイル (平文) に保存されていました。パスワード ファイルは、システムのすべてのユーザーが公開で読み取ることができました。これは、ユーザー権限を持つソフトウェア ツールがユーザー名やその他の情報を見つけるために必要でした。したがって、パスワードのセキュリティは、その目的で使用される一方向関数 (暗号化またはハッシュ化) によってのみ保護されていました。初期の Unix 実装では、パスワードを 8 文字に制限し、12 ビットのソルトを使用しており、4,096 通りのソルト値が可能でした。[ 12 ] これは、1970 年代の計算コストとストレージ コストに見合った適切なバランスでした。[ 13 ]
シャドウパスワードシステムは、ハッシュとソルトへのアクセスを制限するために使用されます。ソルトは8文字、ハッシュは86文字で、スタックオーバーフローエラーが発生しない限り、パスワードの長さは実質的に無制限です。
ウェブアプリケーションでは、ユーザーのパスワードのハッシュ値をデータベースに保存するのが一般的です。ソルトがない場合、SQLインジェクション攻撃が成功すると、簡単に解読できるパスワードが手に入る可能性があります。多くのユーザーが複数のサイトでパスワードを使い回しているため、ソルトの使用はウェブアプリケーション全体のセキュリティの重要な要素です。[ 14 ]特定の言語やライブラリ(PHP、.NETライブラリなど)でパスワードハッシュを保護するためにソルトを使用する方法に関する追加の参考資料は、以下の外部リンクセクションにあります。