web-dev-qa-db-ja.com

データベースにパスワードを保存するための好ましい方法

データベース(できればSQL Server 2005)にパスワードを保存するための好ましい方法/データ型は何ですか。私がいくつかのアプリケーションでこれを行ってきた方法は、最初に.NET暗号化ライブラリを使用し、次にそれらをバイナリ(16)としてデータベースに格納することです。これは推奨される方法ですか、それとも別のデータ型を使用するか、16より多くのスペースを割り当てる必要がありますか?

76
TheTXI

パスワードに相当するソルトハッシュをデータベースに保存し、パスワード自体は保存しません。次に、ハッシュを、ユーザーが渡したものの生成されたハッシュと常に比較します。

リテラルのパスワードデータをどこにでも保存するのは危険すぎます。これは回復を不可能にしますが、誰かがパスワードを忘れたり失ったりした場合、いくつかのチェックを実行して新しいパスワードを作成できます。

81

推奨される方法:パスワードをDBに保存しないでください。そのハッシュのみ。味に塩を加えます。

48
Assaf Lavie

文字列として保存されることを除いて、私はあなたが説明したのと同じことをします。 IBase64は暗号化されたバイナリ値をエンコードします。割り当てるスペースの量は、暗号化アルゴリズム/暗号の強度によって異なります。

私はあなたがそれを正しくやっていると思います(あなたが Salt を使用していると仮定して)。

15
Josh Stodola
  1. bcrypt(nounce + pwd)などのソルトパスワードのハッシュを保存します。 SHA1やMD5よりもbcryptのほうがCPUを集中的に使用するように調整できるため、ブルートフォース攻撃をより長くすることができます。
  2. いくつかのログインエラーの後に、ログインフォームにキャプチャを追加します(ブルートフォース攻撃を回避するため)
  3. アプリケーションに「パスワードを忘れた」リンクがある場合は、新しいパスワードを電子メールで送信しないようにしてください。代わりに、ユーザーが新しいパスワードを定義できるようにする(保護された)ページへのリンクを送信する必要があります(おそらく確認後のみ)たとえば、ユーザーの生年月日など、一部の個人情報の)。また、アプリケーションでユーザーが新しいパスワードを定義できる場合は、ユーザーに現在のパスワードの確認を要求するようにしてください。
  4. そして明らかに、ログインフォーム(通常はHTTPSを使用)とサーバー自体を保護します

これらの対策により、ユーザーのパスワードは次のものからかなり保護されます。

  1. =>オフライン辞書攻撃
  2. =>ライブ辞書攻撃
  3. =>サービス拒否攻撃
  4. =>あらゆる種類の攻撃!
9
MiniQuark

ハッシュ関数の結果は0から255(または-128から127、8ビットのデータ型の符号の有無による)の範囲の一連のバイトであるため、生のバイナリフィールドとして保存するのが最も理にかなっています。 、これは最もコンパクトな表現であり、追加のエンコードおよびデコード手順を必要としないためです。

一部のデータベースまたはドライバーは、バイナリデータ型を十分にサポートしていないか、開発者がそれらに精通していないために快適に感じることができません。その場合、Base-64やBase-85などのバイナリからテキストへのエンコーディングを使用し、結果のテキストを文字フィールドに格納することは許容されます。

必要なフィールドのサイズは、使用するハッシュ関数によって決まります。 MD5は常に16バイトを出力し、SHA-1は常に20バイトを出力します。ハッシュ関数を選択すると、変更すると既存のすべてのパスワードをリセットする必要があるため、通常はハッシュ関数に行き詰まります。したがって、可変サイズのフィールドを使用しても何も購入できません。


ハッシュを実行する「最良の」方法に関して、私はそのトピックに関する他のSO質問に多くの答えを提供することを試みました:

8
erickson

Varchar(40)として保存されているユーザー名のshaハッシュ、Web構成のGUID、およびパスワードを使用します。ブルートフォース/辞書を使用したい場合は、GUID用のWebサーバーもハッキングする必要があります。パスワードが見つかった場合、ユーザー名はデータベース全体にレインボーテーブルを作成するのに失敗します。ユーザーがユーザー名を変更したい場合は、同時にパスワードをリセットします。

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);
4
Shawn

パスワードの単純なハッシュ、または(salt + password)でさえ、一般的に適切ではありません。

見る:

http://www.matasano.com/log/958/enough-with-the-Rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

そして

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

どちらもbcryptアルゴリズムを推奨しています。最も人気のある言語の無料の実装はオンラインで見つけることができます。

3
finnw

データベースで複数のハッシュを使用できますが、少し余分な労力が必要です。それはそれだけの価値がありますが、将来的には追加のフォーマットをサポートする必要がある可能性が最も低いと思われる場合。私はよく次のようなパスワードエントリを使用します

{hashId} $ {salt} $ {ハッシュされたパスワード}

ここで、「hashId」は、それを認識するために内部的に使用するいくつかの数値です。たとえば、特定のハッシュパターンでSHA1を使用しています。 「塩」は、base64でエンコードされたランダムな塩です。 「ハッシュされたパスワード」は、base64でエンコードされたハッシュです。ハッシュを移行する必要がある場合は、古いパスワード形式のユーザーを傍受して、次回ログインしたときにパスワードを変更させることができます。

他の人が言っているように、本当に安全ではない何かをするのは簡単なので、ハッシュには注意したいです。たとえば、H(salt、password)はH(password、salt)よりはるかに弱いですが、同時にこれに費やされた努力とサイトコンテンツの価値とのバランスを取ります。私はよくH(H(password、salt)、password)を使います。

最後に、テキストデータを期待するさまざまなツールを使用できる利点と比較すると、base64でエンコードされたパスワードを使用するコストはわずかです。ええ、もっと柔軟なはずですが、レコードごとに数バイトを節約したいので、上司にお気に入りのサードパーティツールを使用できないことを伝える準備はできていますか? :-)

もう1つのコメントを追加するために編集しました。各パスワードを1/10秒でもハッシュするアルゴリズムを意図的に使用することを提案した場合、上司のオフィスから笑われるだけで幸運です。 (それほど幸運ではありませんか?彼は次の年次レビューで話し合うために何か書き留めておきます。)何十人、または何百人ものユーザーがいる場合、その時間の書き込みは問題ではありません。 10万人のユーザーをプッシュしている場合、通常は複数のユーザーが同時にログインします。遅くて強いものではなく、速くて強いものが必要です。 「でも、クレジットカード情報はどうですか?」保存されたクレジットカード情報は通常のデータベースの近くにあるべきではなく、個々のユーザーではなくアプリケーションによって暗号化されるため、はせいぜい不誠実です。

3
bgiles

ASP.Netを使用している場合は、組み込みのメンバーシップAPIを使用できます。

これには、多くのタイプのストレージオプションが含まれます。一方向ハッシュ、双方向暗号化、md5 +ソルト。 http://www.asp.net/learn/security 詳細については。

あまり凝ったものを必要としない場合、これはWebサイトに最適です。

ASP.Netを使用していない場合は、4guysとcodeprojectのいくつかの記事への良いリンクがここにあります

http://aspnet.4guysfromrolla.com/articles/081705-1.aspxhttp://aspnet.4guysfromrolla.com/articles/103002-1.aspx - http://www.codeproject.com/KB/security/SimpleEncryption.aspx

2
Sruly

あなたの質問は保管方法とサイズについてですので、私はそれに対処します。

ストレージタイプは、バイナリ表現またはテキスト表現のいずれかです(base64が最も一般的です)。バイナリは小さいですが、テキストの操作は簡単です。ユーザーごとにソルティングを行う場合(パスワードごとに異なるソルト)、salt + hashを単一の結合文字列として格納する方が簡単です。

サイズはハッシュアルゴリズムに依存します。 MD5の出力は常に16バイト、SHA1は常に20バイトです。 SHA-256とSHA-512はそれぞれ32バイトと64バイトです。テキストエンコーディングを使用している場合は、エンコーディング方法によっては少し多くのストレージが必要になります。ストレージが比較的安いので、私はBase64を使用する傾向があります。 Base64では、約33%大きいフィールドが必要になります。

ユーザーごとにソルトを使用している場合は、ハッシュ用のスペースも必要になります。すべてを64ビットのソルト+ SHA1ハッシュ(160ビット)のbase64でエンコードすると、40文字かかるため、char(40)として保存します。

最後に、正しく実行したい場合は、単一のハッシュではなく、RBKDF2のようなキー導出関数を使用する必要があります。 SHA1およびMD5ハッシュはめちゃくちゃ速いです。シングルスレッドのアプリケーションでも、1秒あたり約30K〜50Kのパスワードをハッシュできます。これは、クアッドコアマシンでは1秒あたり最大200Kのパスワードです。 GPUは、1秒あたり100倍から1000倍のパスワードをハッシュできます。そのような速度では、ブルートフォース攻撃が許容できる侵入方法になります。 RBKDF2を使用すると、反復回数を指定して、ハッシュの「低速」を微調整できます。重要なのは、システムをひざまずかせることではなく、ハッシュスループットの上限(たとえば、1秒あたり500ハッシュ)を制限するように反復回数を選択することです。今後の証明方法は、パスワードフィールドに反復回数を含めることです(反復+ソルト+ハッシュ)。これにより、将来的に反復を増やして、より強力なプロセッサに対応できるようになります。さらに柔軟にするには、varcharを使用して、将来、より大きな/代替のハッシュを使用できるようにします。

.Netの実装はRFC2892DeriveBytes http://msdn.Microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

2
Gerald Davis