2012-11-15 9 views
9

私はC#を初めて使っています。これは私の最初の質問ですので、あらかじめ偽の謝罪についてお詫び申し上げます。塩漬けされたハッシュを検証する

コンテキスト:私はCreateSaltedHash()メソッドを呼び出し、それをユーザに渡すユーザレジスタは、テキストフィールドからパスワードを入力

。このメソッドは、ユーザーテーブルの[パスワード]列にパスワードを保存する前に、パスワードをハッシュしてハッシュします。

質問:

ユーザーがログインしようとしたとき、私はパスワードを検証する必要がありますどのように?

私がCreateSaltedHash()メソッドをもう一度呼び出すと、ランダムな塩のために一致しません。

塩を別のカラムに保存する必要がありますか?塩漬けされたハッシュを生成するときにデリミタを使用する必要がありますか?塩漬けされハッシュされたパスワードに対して入力パスワードを検証する最も安全な方法は何ですか?

コード: これまで私がこれまで行ってきたことです。

public class PasswordHash 
{ 
    public const int SALT_BYTES = 32; 

    /* 
    * Method to create a salted hash 
    */ 
    public static byte[] CreateSaltedHash(string password) 
    { 
     RNGCryptoServiceProvider randromNumberGenerator = new RNGCryptoServiceProvider(); 
     byte[] salt = new byte[SALT_BYTES]; 
     randromNumberGenerator.GetBytes(salt); 
     HashAlgorithm hashAlgorithm = new SHA256Managed(); 
     byte[] passwordByteArray = Encoding.UTF8.GetBytes(password); 
     byte[] passwordAndSalt = new byte[passwordByteArray.Length + SALT_BYTES]; 
     for (int i = 0; i < passwordByteArray.Length; i++) 
     { 
      passwordAndSalt[i] = passwordByteArray[i]; 
     } 
     for (int i = 0; i < salt.Length; i++) 
     { 
      passwordAndSalt[passwordByteArray.Length + i] = salt[i]; 
     } 
     return hashAlgorithm.ComputeHash(passwordAndSalt); 
    } 

    public static bool OkPassword(string password) 
    { 
     //This is where I want to validate the password before logging in. 
    } 
} 


登録クラスのメソッドを呼び出します。

User user= new User(); 
user.password = PasswordHash.CreateSaltedHash(TextBoxUserPassword.Text); 
+0

「別の列に塩類を保存すべきか」 - はい。それを参照してください。 – TheGeekZn

+0

あなたの保有方法に重大な問題があることを理解していますか?あなたは本当にあなたの現在の選択肢が良い選択ではないパスワードを確保するためにハッシュアルゴリズムの設計を使用する必要があります。 –

+0

あなたのタイトルを編集しました。 「[質問には「タイトル内に「タグ」を含める必要がありますか」(http://meta.stackexchange.com/questions/19190/)」を参照してください。コンセンサスは「いいえ、そうすべきではありません」です。 –

答えて

1

ハッシュを最初に生成するときは、塩と最終ハッシュの両方を保存する必要があります。その後、同じ塩を後で比較するために再利用してください。

CreateSaltedHashメソッドを変更してパスワードと塩を取り、最後のハッシュと一緒に保存されたパスワードを作成/変更するときに塩を生成する新しいCreateSaltメソッドを作成します。

0

塩類は別のカラムに保存する必要がありますか?

はい。

塩漬けされたハッシュを生成するときに区切り記号を使用する必要がありますか?

有効ではありませんが、検証時に同じ区切り文字を含めても問題ありません。

パスワードとハッシュパスワードの入力パスワードを検証する最も安全な方法は何ですか?

SHA512、SHA-2または-3はSHA256よりも安全ですが、セキュリティははるかに必要ですか?

0

あなたは塩を保存する、または同じ塩を毎回使用することができ、次のいずれか

は、いくつかの背景情報を取得するには、この記事を参照してください。すべてのユーザーに同じ塩を使用するよりも安全なので、塩を保管することをお勧めします。

ほとんどのテーブルには、行が作成された日時の列があります。この値のDateTime構造体のTicksプロパティを使用してハッシュをソルトしますが、毎回同じソルトを使用する限り、好きなものを使用できます。注意すべき点は、このメソッドを使用し、SQL型DateTime(DateTime2ではなく)を使用している場合、精度の問題です。コード内にDateTimeを作成する場合、それを切り捨てる必要があります(私は1/100秒と考えています)。

0

そして、より長い答え -

作成されたすべてのパスワードでランダムである必要があります。これにより、それ自体がユニークになります。この 'ランダム性'のため、ファイルに関連付けられたハッシュをプログラムで見つけることはほとんどできません。

パスワードを暗号化する方法(ハッシュなし)は同じである必要があります。そのため、この方法の逆の方法で十分です。
PS:暗号化されたパスワードを元の[ハード]に戻すか、ハッシュで検証するパスワードを暗号化して、暗号化されたパスワードがDB [好ましい]

したがって、暗号化されたパスワードとそれに関連付けられたハッシュをデータベースに格納する必要があります。

これは、パスワードの検証に必要なすべての情報を収集する方法です。

0

ランダムな塩を生成しているので、塩をデータベースに保存する必要があります。その問題は、データベースが侵害された場合、攻撃者は塩とハッシュパスワードを持ち、実際のパスワードをより簡単に特定できることです。理想的には、データベースに侵入してもまだ塩がなく、コードが侵害された場合でもデータベースがまだ存在しないように、コードに静的な塩を入れるのが理想的です。

もう1つの解決策は、コショウを使用することです。ペッパーは塩に似ていますが、あなたは塩とハッシュパスワードでデータベースを保管しません。それはコードに格納されます。このようにして、ランダムな塩が生成され、定数が別々に保存されます。ペッパーをランダムにするには、ユーザーIDなどの変数に基づいてオフセットされた、より大きな文字列のサブストリングを作成することができます。これは、攻撃があなたのデータを取得できたかどうかを知ることができない内部的なものです。

+1

パスワードごとに異なる固有の塩がある場合、ハッカーが複数のパスワードを解読することははるかに難しくなります。 – Polyfun

+0

はい、しかし、あなたはどこかにユニークな塩を保管する必要があります。データベース上に存在し、ハッカーがそれを持っているならば、それらが異なるという事実は無関係です。 –

+3

塩がユニークであれば、特にbcryptのようなものを使って、複数のパスワードを解読するほうがはるかに高価になるので、http://www.codinghorror.com/blog/2012/04/speed-hashing.htmlを参照してください。 。 – Polyfun

1

他の回答として、はい、あなたは塩を保存するか、例えばユーザー名からそれを派生させるべきです。

さらに安全性を高めるには、Rfc2898DeriveBytesも使用する必要があります。ここで

は、そのトピックに関する良い記事です: Password salt and hashing in C#

3

あなたはBcrypt.Netを使用することができます。それは本当に安全であるための多くの推奨事項を持っていますが、それは非常に使いやすいです。私が理解しているように、パスワードを作成すると、自動的に独自の塩が生成され、ハッシュされたパスワード文字列に格納されます。したがって、塩を別々に保管するのではなく、ハッシュされたパスワードと同じフィールドに保管します。要は、それぞれのパスワードには独自のソルトがあるため、ハッカーが複数のパスワードを解読するのがずっと困難(時間がかかる)になります。 BcryptのアルゴリズムはCPUを大量に使用するため、クラックするには多くの計算能力(=資金)が必要です。

Jeff Atwood(stackoverflow moderator)recommends Bcrypt

0

ダイジェストと塩を保存してください。 iterationsとdigestLengthの値は、アプリケーション内の定数にすることができます。

byte[] getNewSalt(Int32 size) 
{ 
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
    byte[] salt = new byte[size]; 
    rng.GetBytes(salt); 
    return salt; 
} 


byte[] getPasswordDigest(byte[] value, byte[] salt, Int32 iterations, Int32 digestLength) 
{ 
    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(value, salt, iterations); 
    return deriveBytes.GetBytes(digestLength); 
} 

最近の記事では、さらに安全なパスワードに、あなたは、部品にパスワードを分割個々の部品をハッシュし、DB内の別々のテーブルに保存することができますことを示唆しています。

1

私はServiceStackのSaltedHashを使用することをお勧めします。これはあなたのNugetからインストールできます。 あなたのNugetコンソールにInstall-Package ServiceStackと入力するだけで、コード内で次のインポートを使用することができます。

using ServiceStack.ServiceInterface.Auth; 

そして、あなたはあなたの塩と簡単にと以前よりも絶対に速くそんなにハッシュを生成します。 はただ、次のコードを入力します。

class Security 
{ 
    ... 
    public void generate(string Password) 
    { 
    string hash, salt; 
    new SaltedHash().GetHashAndSaltString(Password,out hash,out salt); 
    //Store the hash and salt 
    } 
    ... 
} 

そしてはいは、あなたはハッシュと塩があなたのOkPasswordメソッドを実行できるようにする必要があります。

public bool OkPassword(string Password) 
{ 
    var hash = //getStoredHash 
    var salt = //getStoredSalt 
    bool verify = new SaltedHash().VerifyHashString(Password, hash , salt); 
    return verify ; 
} 
関連する問題