ソルト (暗号)

ソルトの再利用

プログラマがパスワードをハッシュ化する際に毎回同じソルトを使用するケース。
この場合でも、既存のレインボーテーブルを無効化することはできる（ソルトの値が適切であれば）。ただし、広く使われている製品にソルトがハードコーディングされると、そこから抽出したソルトを使って新しいレインボーテーブルを生成できてしまう。
また、ソルトが固定だと、パスワードが同じユーザーはハッシュ値も同じになってしまう（ハッシュ値を作る際にユーザ名を混ぜ込んでいる場合を除く）。これにより、一つのハッシュ値で複数のユーザーを攻撃するのが容易になってしまう。

短すぎるソルト

ソルトが短すぎると、ソルトが取りうる値すべてと、よくあるパスワードすべての組み合わせに対するレインボーテーブルを、攻撃者が容易に作成できてしまう。長いソルトを使うことで、レインボーテーブルのサイズを実現不可能なほど大きくすることができる。

利点

単一のパスワードに対する攻撃と、複数のパスワードに対する攻撃との違いを示すため、ユーザ名とハッシュ化したパスワードとの組が大量に記録されているファイルを考える。
ソルトがない場合、攻撃者はまずパスワードのハッシュ値hash(attempt[0])を一つ求め、その結果と一致するハッシュ値がファイル中にないか調べる。
一致するハッシュ値がある確率、つまりこの試行でパスワードを攻略できる確率は、ファイル中にあるパスワードが多いほど高くなる。
一方でソルトがある場合、攻撃者はまずファイル中のエントリAとソルト付きのハッシュ値hash(salt[a], attempt[0])を比較し、次にファイル中のエントリBとソルト付きのハッシュ値hash(salt[b], attempt[0])を比較し……という手順で攻撃を行うことになる。
以上の例より、ソルトを使うことで、複数のパスワードを攻略しようとした際にハッシュ値の「再利用」ができなくなることがわかる。
ソルトは、ハッシュテーブルやレインボーテーブルを使ったパスワードクラッキングの防止にもなる。ここでハッシュテーブルとは、よく使われるパスワードのハッシュ値を大量に集めたリストのことを指す。ソルトなしのパスワードの場合、攻撃者は各ユーザのエントリを見て、ハッシュテーブルやレインボーテーブルにハッシュ化されたパスワードと一致するものがあるか調べる。このテーブルルックアップがハッシュ関数の処理よりも充分に高速な場合（そうである場合がよくある）、この手法によりパスワードクラッキングを高速化できる。
一方、ソルトつきのパスワードの場合、ハッシュテーブルやレインボーテーブルに「ソルト + パスワード」をハッシュ化した値がなくてはならない。ソルトが充分に長くかつランダムであれば、そのような値があるケースは考えにくい。
人間が選んだソルトなしのパスワードは、記憶できる程度に短くかつ意味のある内容でなければならないので、辞書攻撃に対して脆弱になりがちである。
小さな辞書（またはそれをハッシュ化したハッシュテーブル）であっても、もっともよく使われるパスワードにクラッキングするには充分である。
ソルトは人間が記憶しておく必要がない。そのため、長いソルトを使えば、ユーザーに負担を強いることなく、攻撃を成功させるのに必要なレインボーテーブルのサイズを実現不可能なほど大きくすることができる。
より技術的には、ソルトはパスワードをより長く、より複雑にすることで、ハッシュテーブルやレインボーテーブルによる攻撃に対抗しているものと見なせる。
レインボーテーブル上に、ソルトつきのパスワードと長さ（たとえば8バイトのパスワードと2バイトのソルトで、レインボーテーブル上では10バイトのパスワードと同じ）や複雑性（ソルトが非英数字であれば、英数字のみのパスワードより複雑性が増す）の合うパスワードがなければ、レインボーテーブルからパスワードが見つかることはない。またパスワードが見つかった場合は、パスワードからソルト部分を取り除いて使用する必要がある。
シャドウパスワードを備えた現代的なシステムでは、パスワードのハッシュ値やその他のセキュリティに関するデータは非公開のファイルに格納されるため、これらのような懸念点は軽減されていると言える。
一方で、中央集約型のパスワード管理システムを使って複数のサーバを利用しており、パスワードやパスワードハッシュが複数のシステムへ送信されるような環境では、このような課題は引き続き妥当な懸念点であると言える。
そのような環境では、個々のシステムのrootアカウントより、中央集約型のパスワード管理システムの管理者の方が信頼されているという扱いになる。そのため、パスワードをハッシュ化する際のアルゴリズムが、ソルトの値の生成方法も含めて適切か確認することにも意味がある。
ソルトには、大量のパスワードを攻撃する辞書攻撃や総当たり攻撃の速度を低下させる効果もある（パスワード1つだけを攻撃する場合にはこの効果は望めない）。
ソルトがない場合、攻撃者が一度にたくさんのパスワードを攻撃するときには、推測したパスワードを1回ハッシュ化したら、その結果をすべてのハッシュ値と比較すれば済む。
一方でソルトがある場合、各パスワードのソルトはすべて異なると考えてよい。そのため、推測したパスワードは、攻撃対象のパスワードそれぞれのソルトを使って毎回ハッシュ化する必要がある。これにより、1つのハッシュ値をすべてパスワードと比較する場合と比べ、有意に速度が低下する。
ソルトのもう一つの（ただし小さな）利点として、2人のユーザが同じパスワードを使っていた場合、あるいは同じユーザが2つのマシンで同じパスワードを使っていた場合が挙げられる。
ソルトがない場合、このようなパスワードは同じハッシュ値としてパスワードファイルに保存される。
これにより、2つのアカウントが同じパスワードを使っていることが分かってしまうため、片方のアカウントのパスワードを知っている人は、もう一つのアカウントにもアクセスできてしまう。
一方で、パスワードにランダムなソルトを付与していた場合、2つのアカウントが同じパスワードを使っていたとしても、ハッシュを見ただけでそれが知られることはない。

1970～1980年代

初期のUnixでは、パスワードファイル /etc/passwd にソルトつきのパスワードが保存されていた（パスワードの前に2文字のランダムなソルトが付いていた）。
この頃の古いバージョンのUnixでは、ソルトつきパスワードのハッシュ値といっしょに、ソルトの値も（平文で）passwdファイルに保存されていた。
またパスワードファイルはシステムのユーザは誰でも読むことができたが、これは、ユーザ権限で動くソフトウェアがユーザ名やその他の情報を読むためにこのような仕様となっていた。そのため、パスワードのセキュリティは一方向関数（暗号化、またはハッシュ化）だけで保護されている状態だった。
初期のUnixの実装では、パスワードの最大長は8文字までで、ソルトは12ビットであった。ソルトの取りうる値は4,096通りとなる。
これは1970年代における計算量とストレージのコストから見れば、妥当なバランスと言えた。

1980年代

ハッシュやソルトへのアクセスを制限するため、シャドウパスワードが導入された。ソルトは8文字、ハッシュ値は86文字となり、パスワードの最大長は無制限となった。

Webアプリケーションにおける実装

Webアプリケーションにおいては一般的に、ユーザのパスワードはハッシュ化されてデータベースに保存される。
この際にソルトがないと、SQLインジェクションが成功した場合に容易に攻略可能なパスワードができてしまう。
これは、複数のサイトでパスワードを使い回すユーザが多くいるためである。ソルトを使うことはWebアプリケーション全体のセキュリティを高めるために重要であると言える。各種プログラミング言語（PHP、.NETなど）でパスワードハッシュにソルトを使う方法については、外部リンクを参照。