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.
    }
}


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

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

10 に答える 10

3

Bcrypt.Netを使用できます。本当に安全であるための多くの推奨事項があり、さらに非常に使いやすい. 私が理解しているように、パスワードを作成すると、一意のソルトが自動的に生成され、ハッシュされたパスワード文字列に保存されます。そのため、ソルトを個別に保存するのではなく、ハッシュ化されたパスワードと同じフィールドに保存します。ポイントは、各パスワードには独自のソルトが含まれているため、ハッカーが複数のパスワードを解読するのが非常に困難 (時間がかかる) ことです。Bcrypt が使用するアルゴリズムも CPU を集中的に使用するため、クラックするには多くの計算能力 (=お金) が必要です。

Jeff Atwood (stackoverflow モデレーター)は Bcrypt を推奨しています。

于 2012-11-15T13:53:43.890 に答える
2

NugetからインストールできるServiceStackのSaltedHashを使用することをお勧めします。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 ;
}
于 2012-12-18T14:11:53.630 に答える
2

最初にハッシュを生成するときは、ソルトと最終的なハッシュの両方を保存する必要があります。その後、同じソルトを将来の比較に再利用します。

したがってCreateSaltedHash、パスワードとソルトを取得するようにメソッドを変更し、パスワードが作成/変更されたときにソルトを生成する新しいCreateSaltメソッドを記述します。これは最終的なハッシュと一緒に保存されます。

于 2012-11-15T13:20:51.840 に答える
1

他の答えが述べているように; はい、ソルトを保存するか、たとえばユーザー名から取得する必要があります。

Rfc2898DeriveBytesまた、より安全にするために使用する必要があります。

そのトピックに関する良い記事があります: C#でのパスワードソルトとハッシュ

于 2012-11-15T13:37:47.453 に答える
1

ハッシュとともにソルトを保存する必要があります。

背景情報については、次の記事を参照してください: http://www.h-online.com/security/features/Storing-passwords-in-uncrackable-form-1255576.html

于 2012-11-15T13:22:25.740 に答える
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 内の別々のテーブルに保存することが提案されています。

于 2012-11-15T14:10:18.280 に答える
0

塩を別の列に保存する必要がありますか?

はい。

ソルトハッシュを生成するときに区切り文字を使用する必要がありますか?

必須ではありませんが、検証時に同じ区切り文字を含める限り問題はありません。

ソルト化およびハッシュ化されたパスワードに対して入力パスワードを検証する最も安全な方法は何ですか?

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

于 2012-11-15T13:22:05.877 に答える
0

ランダムなソルトを生成しているため、ソルトをデータベースに保存する必要があります。これに関する問題は、データベースが危険にさらされた場合、攻撃者がソルトとハッシュ化されたパスワードを取得するため、実際のパスワードをより簡単に特定できることです。理想的には、コードに静的なソルトを含める必要があります。これにより、データベースが侵害された場合でもソルトが保持されず、コードが侵害された場合でもデータベースはまだ保持されません。

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

于 2012-11-15T13:31:40.217 に答える
0

塩を保存することも、毎回同じ塩を使用することもできます。すべてのユーザーで同じソルトを使用するよりも安全であるため、ソルトを保存することをお勧めします。

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

于 2012-11-15T13:22:54.027 に答える
0

そしてより長い答えのために -

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

パスワードを (ハッシュなしで) 暗号化する方法は同じである必要があるため、毎回この方法の逆を使用するだけで十分です。
PS: (より安全な検証方法)暗号化されたパスワードを元の[Hard]に戻すか、検証パスワードをハッシュで暗号化し、暗号化されたパスワードが DB に保存されているものと一致することを確認します[Preferred]

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

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

于 2012-11-15T13:23:34.533 に答える