1

ログインページからの通常のパスワードでデータベースからのハッシュパスワードを確認するのに大きな問題があります。この2つのパスワードを比較してユーザーを検証する方法。登録ページのコードは次のとおりです。

protected void Button1_Click(object sender, EventArgs e)
{

    SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider();
    byte[] plainbytes = Encoding.ASCII.GetBytes(TextBox2.Text);
    var sha = sh.ComputeHash(plainbytes);
    byte[] hashbytes = sh.Hash;
    SqlConnection con = new SqlConnection(constr);
    SqlCommand cmd = new SqlCommand("RegisterUser",con);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter param = null;
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10);
    param.Value = TextBox1.Text;
    param = cmd.Parameters.Add("@password", SqlDbType.VarChar, 20);
    param.Value = BitConverter.ToString(hashbytes);
    try
    {
        con.Open();
        cmd.ExecuteNonQuery();
        Label4.Text = "Successfully added account!!!";
    }
    catch (Exception ex)
    {
        throw new Exception("Exception adding account"+ex.Message);
    }
    finally
        {
            con.Close();
        }
}

このパスワードをログインページからのパスワードと比較する方法...みんな助けて...

SALTを使用したHASHのコード:-

 private static string CreateSalt(int size)

{

    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

    byte[] buff = new byte[size];

    rng.GetBytes(buff);

    return Convert.ToBase64String(buff);

}

private static string CreatePasswordHash(string pwd, string salt)

{

    string saltAndPwd = String.Concat(pwd, salt);

    string hashedPwd =

    FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "SHA1");

    hashedPwd = String.Concat(hashedPwd, salt);

    return hashedPwd;

}

protected void btnregister_Click(object sender, EventArgs e)

{

    int saltSize = 5;

    string salt = CreateSalt(saltSize);

    string passwordHash = CreatePasswordHash(txtPassword.Text, salt);

    try

    {

        StoreAccountDetails(txtUserName.Text, passwordHash);

    }

    catch (Exception ex)

    {

        lblMessage.Text = ex.Message;

    }

}

private void StoreAccountDetails( string userName,string passwordHash )

{

    SqlConnection conn = new SqlConnection(constr);

    SqlCommand cmd = new SqlCommand("INSERT INTO Users VALUES(@userName, @passwordHash)", conn);

    SqlParameter sqlParam = null;

    sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar,20);

    sqlParam.Value = userName;

    sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar,50);

    sqlParam.Value = passwordHash;

    try

    {

       conn.Open();

       cmd.ExecuteNonQuery();

       lblMessage.Text = "User Added Successfully!!!";

    }

    catch( Exception ex )

    {

    throw new Exception("Exception adding account. " + ex.Message);

    }

    finally

    {

       conn.Close();

    }

}

private bool VerifyPassword(string suppliedUserName,string suppliedPassword )

{

     bool passwordMatch=false;

     SqlConnection conn = new SqlConnection(constr);

     SqlCommand cmd = new SqlCommand( "SELECT PasswordHash FROM Users WHERE UserName = @userName", conn );

     SqlParameter sqlParam = cmd.Parameters.Add("@userName",SqlDbType.VarChar,20);

     sqlParam.Value = suppliedUserName;

     try

     {

        conn.Open();

        SqlDataReader reader = cmd.ExecuteReader();

        reader.Read();

        string dbPasswordHash = reader.GetString(0);

        int saltSize = 5;

        string salt = CreateSalt(saltSize);

        reader.Close();

        string hashedPasswordAndSalt =CreatePasswordHash(suppliedPassword, salt);

        passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash);

     }

     catch (Exception ex)

     {

        throw new Exception("Execption verifying password. " +ex.Message);

     }

     finally

     {

        conn.Close();

     }

    return passwordMatch;
 }


protected void btnlogon_Click(object sender, EventArgs e)

{

    bool passwordVerified=false;

    try

    {

        passwordVerified =VerifyPassword(txtUserName.Text, txtPassword.Text);

    }

    catch (Exception ex)

    {

        lblMessage.Text = ex.Message;

        return;

    }

    if (passwordVerified == true)

    {



        lblMessage.Text = "Logon successful: User is authenticated";

    }

    else

    {

        lblMessage.Text = "Invalid username or password";

    }

}
4

4 に答える 4

4

単純。ログインページから取得したパスワードをハッシュし、ハッシュコードをデータベース内のハッシュコードと比較します。


テキストは両方の時間で同じように処理される必要があるため、その部分に対して単一の関数を作成します。テキストをバイトに変換するときはUTF-8を使用します。ASCIIエンコーディングはすべての文字を処理するわけではありません。

public static string HashString(string value) {
  SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider();
  byte[] plainbytes = Encoding.UTF8.GetBytes(value);
  byte[] hash = sh.ComputeHash(plainbytes);
  return BitConverter.ToString(hashbytes);
}
于 2012-06-02T13:59:10.973 に答える
2

アップデート

コードを更新したので、まだいくつかの問題があります。Saltを使用する必要がありますが、最初に実際に機能するコードが必要です。塩の追加は簡単です。

「mypassword」の単純なSHAハッシュは、20文字よりはるかに大きい文字列になります。base64でハッシュ化されたパスワードを20文字のフィールドに収める方法はありません。より大きなハッシュをサポートするように、列のサイズとコードを変更します。

アップデート2

これがハッシュにSaltを含むコードです。ユーザー名とハッシュ化されたパスワードとともにsaltを保存するには、RegisterUserストアドプロシージャを更新する必要があります。ユーザーごとに新しいSaltが必要です。ソルト自体をハッシュまたは暗号化する必要はありません。

また、LogInUserストアドプロシージャからソルトを返す必要があります。

以下のコメントを読んでください:

private byte[] Combine(byte[] a, byte[] b)
{
   byte[] c = new byte[a.Length + b.Length]; 
   System.Buffer.BlockCopy(a, 0, c, 0, a.Length); 
   System.Buffer.BlockCopy(b, 0, c, a.Length, b.Length); 
   return c; 
}

protected void Button1_Click(object sender, EventArgs e)
{    
    byte[] salt = new byte[16];
    RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
    random.GetNonZeroBytes(salt);

    SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider();
    byte[] plainbytes = Encoding.ASCII.GetBytes(TextBox2.Text);

    var saltedBytes = Combine (salt, plainbytes);
    var sha = sh.ComputeHash(saltedBytes);

    SqlConnection con = new SqlConnection(constr);
    SqlCommand cmd = new SqlCommand("RegisterUser",con);
    cmd.CommandType = CommandType.StoredProcedure;

    SqlParameter param = null;
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10);
    param.Value = TextBox1.Text;

    param = cmd.Parameters.Add("@password", SqlDbType.VarChar, 128);
    param.Value = Convert.ToBase64String(sha);

    // Store salt to use when comparing.
    param = cmd.Parameters.Add("@salt", SqlDbType.VarChar, 128);
    param.Value = Convert.ToBase64String(salt);

    try
    {
        con.Open();
        cmd.ExecuteNonQuery();
        Label4.Text = "Successfully added account!!!";
    }
    catch (Exception ex)
    {
        throw new Exception("Exception adding account"+ex.Message);
    }
    finally
    {
        con.Close();
    }
}

public bool searchtable() 
{           
    SqlConnection con = new SqlConnection(constr);
    SqlCommand cmd = new SqlCommand("LogInUser",con);
    cmd.CommandType = CommandType.StoredProcedure;

    SqlParameter param = null;
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10);
    param.Value = TextBox1.Text;

    try
    {
        con.Open();
        SqlDataReader reader = cmd.ExecuteReader();
        reader.Read();

        // Get the salt hashed password
        string dbpassmatch = reader.GetString(0);

        // Get the salt
        byte[] salt = Convert.FromBase64String(reader.GetString(1));

        // Recreate the salted hashed password
        byte[] plainbyte = Encoding.ASCII.GetBytes(TextBox2.Text);
        SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider();
        var saltedBytes = Combine (salt, plainbytes);
        var sha = sh.ComputeHash(saltedBytes);            

        // Now it matches what you did in insert.
        String dbpassword = Convert.ToBase64String(sha);

        reader.Close();

        return dbpassword.Equals(dbpassmatch);
    }
    catch (Exception ex)
    {
        throw new Exception("Exception adding account" + ex.Message);
    }
    finally
    {
        con.Close();
    }
}
于 2012-06-02T14:47:12.437 に答える
2

あなたのコードはセキュリティの観点からかなり悪いです:

  1. 塩を使用してください。通常、データベースにハッシュと一緒に格納されるランダムな値(64ビット以上)。

  2. .netにはすでに実装が含まれているため、PBKDF2、bcrypt、scryptなどの低速のKDFを使用するのが最も簡単です。Rfc2898DeriveBytesClass
  3. 使用しないでくださいEncoding.ASCII、しかしEncoding.UTF8。それ以外の場合、ASCII以外の文字を含むパスワードは非常に弱くなります。

次に、入力されたパスワードを確認するために、データベースからハッシュとソルトを読み取ります。候補パスワードをデータベースから読み取ったソルトでハッシュし、ハッシュを比較します。


ASP.netには、というライブラリも含まれていますMembershipが、私はあまり詳しくありません。

于 2012-06-02T14:49:23.663 に答える
0

アプリケーション側ではなく、db側でハッシュを行うことができます。これが最も簡単です。パスワードをプレーンテキストとしてレジスタに保存されたプロシージャに送信し、ハッシュし(sha1など)、ユーザーがログインを実行したときにパスワードを再度送信します。保存されたプロシージャは、送信したユーザー名は、パスワードをハッシュし、登録時に保存したパスワードと比較します。

于 2012-06-02T14:00:38.357 に答える