ハッシュされたパスワードと同じフィールドに塩を保存するのは安全ですか?

私のアプリケーションでパスワードをハッシュ化するためにArgon2を使うことで、私はそれがこのような文字列を生成することに気づきました(例えばパスワード "rabbit"のために):

$argon2i$v=19$m=65536,t=3,p=1$YOtX2//7NoD/owm8RZ8llw==$fPn4sPgkFAuBJo3M3UzcGss3dJysxLJdPdvojRF20ZE=

私の理解するところによれば、 p = より前のものはすべてパラメータ、 p = の本文はソルト、そして最後の部分はハッシュされたパスワードです。

これをSQLデータベースの1つのフィールド(この場合は varchar(99))に格納してもいいですか。ハッシュ化されたパスワードとは別にソルトを保存し、パラメータをコードに入れておくべきですか?

61
ペッパー 、データベースの外に保存することができます。
追加された 著者 forest,
"varchar(99)"は非常にきついようです。次のバージョンのハッシュライブラリがパラメータを追加したり、ハッシュを長くしたりするとどうなりますか?データベースに "varchar(MAX)"またはそれに類似したものがありませんか?
追加された 著者 Metaathron,
追加された 著者 waqar ahmad,
PHPの password_hash 関数もハッシュ文字列とともにソルトを格納します(例: $ 2y $ 10 $ .vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3F‌ ykk1a
追加された 著者 Jack,

7 答え

あなたはそれを単一のフィールドに格納するべきです。分割しないでください。

私はこれがデータベースのバックグラウンドから来る人々にとって少し直観的でないように見えるかもしれないことを知っています。しかしセキュリティの観点からは、これは完全に理にかなっています。

どうして?個々の開発者が操作する必要がある最小の単位はそのフルストリングです。それが、提供されたパスワードが正しいかどうかを確認するためにアプリがハッシュライブラリに渡す必要があるものです。開発者の観点からは、ハッシュライブラリはブラックボックスになることがあります。そして、彼女はそれらの厄介な部分が実際に何を意味するのか自分自身を心配する必要はありません。

ほとんどの開発者は不完全な人間なので、これは良いことです(私は自分自身なので知っています)。もしあなたが彼らにその文字列を分離させてそれからもう一度それをすべて合わせようとするならば、彼らはおそらく事態を混乱させるでしょう。

コードにパラメータを格納するだけでも悪い考えです。プロセッサが高速になるにつれて、将来的にコスト要因を増やすことをお勧めします。移行段階では、パスワードが異なればコスト要因も異なります。それで、あなたはそれをハッシュするためにどのような費用が使われたかについてのパスワードレベルの情報が必要になるでしょう。

116
追加された
これには将来性がないという利点もあります。後でハッシュパラメータを変更することにした場合でも、データベース内の古いハッシュはで機能し続けます(ハッシュを直接比較するのではなく、Argon2と同じようにライブラリ関数を使用してハッシュを比較する限り)。文字列)
追加された 著者 Vincent,
多くの暗号化ライブラリは秘密と塩を別々のパラメータとして取ります。その観点だけでも、ダイジェストと塩/エントロピーを別々のフィールドに格納するのが賢明です。あなたがそれらを別々に保存するならば、あなたは塩のために均一な長さを使う必要さえありません。自分のアルゴリズムをバージョン化して、一度に複数のものをサポートすることで、パスワードを変更する必要もなく、ユーザーを新しい強力なアルゴリズムにスムーズに移行させることができます。
追加された 著者 Craig,
@Andders私はどのライブラリが実際に通常のトリプルではなく単一の文字列で動作するAPIを持っているかに興味がありました。この場合、結局のところ、追加の設定が必要です。 Spring APIは見てみるとかなりおもしろいです。
追加された 著者 Cascabel,
@Anders別々の部分を1つの文字列に格納し、タプル(アルゴリズム、ハッシュ、ソルト)と文字列を自分で変換する方法について独自の形式を定義する必要がある場合、ブラックボックスにはなりません。何らかの形でエラーが発生する可能性がある場合。全体的なアイデアは、開発者が別々の部分を扱わなくても済むようにすることだと思いましたか?
追加された 著者 Cascabel,
@Anders 1つのパスワードフィールドで保存されたパスワードのバージョン管理をサポートしているライブラリはどれですか?それを機能させる方法を見ることができ、アプローチはそれにとってかなり魅力がありますが、私は野生でそれを見たことがありません。
追加された 著者 Cascabel,
セキュリティ対策の観点からだけでは意味がありません。あなたがレイアウトする理由を考えると、それはまだ正規化の観点から理にかなっています。
追加された 著者 jpmc26,
アルゴリズムを含むすべてのパラメータを1つの文字列で透過的に格納し、より強力な設定にスムーズにアップグレードできるライブラリの例を探している人は、 PHPのpassword_ *関数password_needs_rehash
追加された 著者 IMSoP,
@Vooこのバージョン管理は開発者が起動する必要がありますが、デコードと再エンコードはライブラリによって完全に処理されます。
追加された 著者 MauganRa,
@Voo spring-security version 5はこの方向に向かっています。 docs.spring.io/spring-security/site/docs/current/reference/h‌ tml /… 私が欠けていると思う唯一の機能は、ライブラリがアプリケーションにハッシュされたパスワードフィールドをデフォルトのエンコーディングスキームに移行する機会を与えないということです(それを使わない場合)。
追加された 著者 pkm1986,
@Voo任意のライブラリあなたが必要とするすべての情報 - アルゴリズム、パラメータ、塩 - はあなたが単一の列に格納する文字列の中にあります。
追加された 著者 Anders,
@Vooはい、ポイントは文字列を変更しないことです。絶対しないでください。私はそれを示唆するつもりはなかった。私たちはお互いを誤解していると思います。
追加された 著者 Anders,
@Craig多くの古いライブラリはそうしています、しかし私は今日それが悪いデザインと考えられていると言いたいです。バージョニングアルゴリズムに関しては、1列のフルストリングでそれを行うことができます。
追加された 著者 Anders,
これが私がスタック交換を愛する理由です。毎日、私は知らなかったことを学びます。
追加された 著者 user94205,
@Voo 3つの部分すべてを単一の文字列として格納するもう1つのパスワード暗号化実装は bcrypt です多数の言語
追加された 著者 Tyler,

欠けているのは、ハッシュが元のデータから元の文字列を除いたものに対して機能することです。ハッシュに対して文字列を検証したい場合は、提供された文字列と元のハッシュデータ(cost、saltなど)を取り、新しいハッシュを生成します。新しいハッシュが古いハッシュと一致する場合は、文字列が検証されます(つまり、文字列は復号化されない再ハッシュされます)。

塩を持っていることはあなたが力ずくになるのを助けません。タンブラーがロックの一部であるのと同じように、ソルトはハッシュの必須部分です。あなたがどちらかを取り出すならば、だれもそれを使うことができません。

分離ストレージは無意味です。ほとんどの場合、完成したハッシュを検証するために組み立て直す必要があります。そのため、デフォルトではすべてのコンポーネントが1つの便利な文字列に格納されています。

47
追加された
あなたは私よりずっとエレガントに、より少ない言葉でそれを説明しました。 +1
追加された 著者 Anders,
はい、分離するのは無意味です - 一方を他方なしで使用することはできず、もう一方なしで更新することはできません。また、同じセキュリティ要件があるため、salt +パスワードを単一の不可分なストレージ単位として扱います。
追加された 著者 brandonmack,

はい、あなたはそれを単一のフィールドに格納することができ、多くのデータベース/アプリケーションは単一のフィールド/ファイルなどにsalt + hashを格納します。

最も有名なのはLinuxです(これはDBではありません)。ハッシュは/ etc/shadowファイルに次の形式で格納されます。

"$ id $ salt $ hashed"、生成された印刷可能なパスワードハッシュの形式   crypt(C)では、 "$ id"は使用されているアルゴリズムです。 (GNU/Linuxでは、 "$ 1 $"   MD5の略で、 "$ 2a $"はBlowfish、 "$ 2y $"はBlowfishです(正しい   8ビット文字の処理)、 "$ 5 $"はSHA-256、 "$ 6 $"はSHA-512、[4]   NetBSDのように、他のUnixでは異なる値があるかもしれません。

     

(情報源: https://en.wikipedia.org/wiki/Passwd

塩は秘密にすることを意味していません(または少なくともハッシュより秘密ではありません)。攻撃者は個々のユーザーごとに異なるソルトを使用する必要があるため、ブルートフォース攻撃をさらに困難にすることが主な目的です。

しかし、あなたの質問はもっと微妙です - なぜならあなたは塩についてだけではなくパラメータについても尋ねているからです。ハッシュアルゴリズム、反復回数、およびsaltのようなもの。いずれにせよ、これをコードに格納しないでください。それらはまだDBに属しています。

たくさんのユーザーがいて、ハッシュアルゴリズムとしてSHA1を使用したと想像してください。そのため、データベースフィールドは SHA1:SALT:HASH のようになります。

データベースをBCRYPTにアップグレードしたい場合、どうしますか。

通常は、ユーザーがログオンしたときにパスワードを確認し、有効な場合は新しいアルゴリズムでパスワードを再ハッシュするようにコードを配置します。これで、ユーザーのフィールドは BCRYPT:SALT:HASH のようになりました。

しかし、その場合、SHA1にいるユーザーもいればBCRYPTにいるユーザーもいるでしょう。これはユーザーレベルなので、どのユーザーをデータベースに含めるかをコードに伝えるパラメーターが必要です。

一言で言えば、単一のフィールドにパラメータとハッシュを格納することは問題ありませんが、何らかの理由(効率、簡単なコードなど)でそれらを分割することも問題ありません。 OKではないのは、これをあなたのコードに保存することです:)

TL:DR

Troy Huntは最近、上記の方法でBCRYPTに移行するのではなく、現在DBにあるすべてのSHA1ハッシュを単純に取得し、BCRYPTを使用してそれらをハッシュすることを提案するポッドキャストを公開しました。

Effectively BCRYPT(SHA1(clear_password))

ユーザーがログオンしたとき

BCRYPT(SHA1(clear_password)) == 

この方法では、プラットフォーム上のすべての人が一度にアップグレードされ、パスワード用の複数のハッシュ形式を持つデータベースがなくなります。とても清潔でとても素敵。

私はこの考えは完全に理にかなっていると思いますが、全員が一度に移行しても、それは瞬間的なものではありません。あなたが(あなたがすべてのパスワードを再ハッシュしている間に)あなたがあなたのアプリでいくつかのダウンタイムを受け入れても構わないと思っているのでなければハッシュアルゴリズムのパラメータ、そしてあなたのコードはそれに基づいて実行されます。

8
追加された
@MartinBonnerは正しいです。直感的に理解できますが間違っています。 SHA1が壊れていると仮定します。すべての入力に対して1を返すようにしてこれをシミュレートします。このシナリオでは、BYCRYPT(SHA1(x))はBCRYPT(x)より明らかに安全性が劣ります。同様にSHA1(BCRYPT(x))を検討してください。 SHA1がどのように壊れて連鎖しているかによってハッシュ は有効なままになります。しかし、それは2つのうちのより安全なものを使用するよりも決して安全ではないでしょう。それらは理想的にはセキュリティ方程式の同じパラメータに影響を与えているからです。 相互作用の連鎖が最小限であれば便利かもしれませんが、それは非常に多くの数学です。だからAndrewMorton 実績 @
追加された 著者 gibbo,
@keithRozario "BCRYPT(SHA1(x))が少なくともBCRYPT(x)と同じくらい安全であることは直感的に明白です"と "セキュリティ証明があることと同じではありません..."。暗号の第一の規則:あなたの名前がdjbかそれに似たものでない限り、決してあなたの直感を信頼しないでください。
追加された 著者 jpcgt,
新しいスレッドはこちらです。 183358 /…
追加された 著者 Daniel Oberlin,
まあ、私は文章を「私は思う」と警告しました。私の理解するところでは、BCRYPTがブルートフォースをより高価にすることによって機能するならば、それがSHA1であろうと平文であろうと入力が何であるかに関係なくそれは攻撃者にとってブルートフォースよりももっと高価である。 BCRYPT(SHA1())は、マイグレーションの観点からは意味があります。
追加された 著者 Daniel Oberlin,
また、私はこのトピックをここで見つけました、それはあなたにそれをBCRYPTする前にパスワードをSHAするためのいくつかの他のユースケースを提案します。スレッドに関する一般的なコンセンサスは、実行するのはOKであるということでしたが、それでも同意しない場合は別の質問を始める必要があります。
追加された 著者 Daniel Oberlin,
@AndrewMorton良い議論、しかし私は確信していません。すべての入力に対して1を返すようにして壊れたSHA1をシミュレートする例は正しくありません。つまり、ユーザーが自分のパスワードに1を選択した場合、BCRYPTは壊れているというようなものです。私はこれが面白いと思うのでしかし私は別のスレッドを始めています。
追加された 著者 Daniel Oberlin,
あなたはどうして私たちは自分たちでロールバックしないのですかことを知っていますか BCRYPT(SHA1())はその問題がないことが実証済みですか? (私が簡単に調査できるようにリンクを張ったのではなく、「完全に理にかなっている」と「それが本当であること」は同じではありません。)
追加された 著者 Aaron,
@keithRozarioそれを書いたのは黒人でした。
追加された 著者 Aaron,

セキュリティの観点からは、簡単にするために1つのフィールドに寄りかかっていますが、saltとハッシュされたパスワードが1つのフィールドに格納されていても別々のフィールドに格納されていても構いません。それらを分離する唯一の理由は、アプリケーションコードがsaltとパスワードを別々に検証機能に渡す必要がある場合です。アプリケーションコードが単一の結合された文字列しか必要としない場合は、そのようにして格納することもできます。

たとえば、古いASP.NETメンバーシップではパスワードのハッシュとsaltを2つのDBフィールドに分割し、新しいASP.NET IDではハッシュとsaltを1つのDBフィールドに格納しています。入力および出力としての単一の文字列

4
追加された

これをSQLデータベースの1つのフィールドに格納することは可能ですか(この場合はvarchar(99))。

いいえ。データのサイズはいつか変わる可能性があります。仕様上、サイズが常に正確に99になり、その からの変動がないことを指定しない限り、varchar(MAX)フィールドを使用する必要があります。データベースにストレージ要件を引き受けさせます。

3
追加された

ある程度安全かどうかを知るためには、塩の目的を理解しなければなりません。

塩は(私が考えることができる)いくつかの目的にかなう

  1. 辞書攻撃を防ぐ

辞書攻撃は、論理的な単語がパスワードの一部として使用される場所です。原型は password または P @ ssW0rd という単語です。人は不完全であり、言葉を覚えてからランダムな文字列と数字を覚えるのが簡単です。辞書攻撃はこれを当てにしてブルートフォース攻撃の道を短くします。無作為に大量のものを追加すると、この種の攻撃は不可能または無意味になり、全体を強引に強制されます。

攻撃者が使用されているソルトを知っている場合、パスワードごとにすべての辞書ファイルを編集する必要があります。これは、ソルトが元のパスワードに追加された方法を知っていることを前提としています。辞書リストの大きな利点の1つは、1000個のパスワードと100万個の辞書の単語を使用することです。それからあなたはより弱いパスワードでいくつかの一致を得ることを試みるそれらを通って循環します。したがって、100万語を1000回編集しなければならないのは、実際には現実的ではありません。

  1. ハッシュまたはレインボーテーブル攻撃を防止します。

Rainbowテーブルは、ハッシュが事前に計算されてある種のデータベースに格納される場所です。たとえば、MD5を使用してランダムなものをハッシュして保存するだけです。パスワードを解読したいときは、レインボーテーブルを見上げるだけです。

攻撃者が塩を持っている場合、彼らは使用された塩ごとにレインボーテーブルを再コンパイルする必要があります。この攻撃の利点は、そのデータを事前にコンパイルして何度も再利用することです。これにより、パスワードのブルートフォース強制に戻ります。すべてのパスワードを別々に塩漬けして塩漬けすることは、基本的にはそれぞれの塩ごとにレインボーテーブルを再計算する必要があることを意味します。そのため、パスワードごとに異なるソルトを使用することが重要です。

要約

これらの理由のどれも本当に秘密である塩に頼りません。攻撃者がその塩を知っている場合、明らかにそれらはすべてそれほど強力ではありません。しかし、彼らが手に入れた追加の情報は常に彼らを助けます。だから私はそれを宣伝するつもりはないと思いますが、あいまいさに基づいてセキュリティについての言葉があります....

Disclaimer I am by no means a cryptological expert, but these are a few of the top reasons that come to my mind when I think about salts.

それが役立つことを願っています。

1
追加された
あなたは理由3について間違っています。ソルトは公開されているので、攻撃者は1文字のパスワードすべて、2文字のパスワードすべてなどを操作できます。ソルトが行うことができるのは、攻撃者が1人のユーザーで作業する必要があるということです。時間、
追加された 著者 jpcgt,
@MartinBonner - 罰金私はそれを削除しました...
追加された 著者 Stephen Quan,

ソルトはレインボーテーブル攻撃を防ぐために使われています。 したがって、saltが/ etc/shadowに格納されている最新のGNU/Linuxシステムで行われているように、saltはハッシュされたパスワードで格納されている可能性があります。

0
追加された
あなたの答えが異なるデータベース列にどのように当てはまるかわかりませんか?
追加された 著者 Anders,