Development Environment used:
1.Microsoft Visual Studio 2010
2. Programming Language: C#
3. Database MySql
I am trying to use BCrypt class by Derek Slager for creating and authenticating username and password. A form is use to create new user to save Username and Password to database, but this Password is not the plaintext one, it is hashed using BCrypt.HashPassword method. I am using binding source for the form, so I am using a dummy textbox which will hold the hashed value of plaintext user entered in password textbox. Then I bind the controls using following:
public void BindControls()
{
txtUser.Text = null;
txtPass.Text = null;
txtHash.Text = null;
txtID.DataBindings.Clear();
txtUser.DataBindings.Clear();
txtHash.DataBindings.Clear();
txtID.DataBindings.Add(new Binding("Text", bs, "userID"));
txtUser.DataBindings.Add(new Binding("Text", bs, "userName"));
txtHash.DataBindings.Add(new Binding("Text", bs, "userPass"));
}
As plaintext password is not required to save in Database, there is no need to bind it. txtHash will get hashed password after user enter plaintext password in txtPass textbox on LeaveEvent as follows:
private void txtPass_Leave(object sender, EventArgs e)
{
txtHash.Text = null;
txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12));
}
Then called the save method of User class when user click Save Button:
private void btnSave_Click(object sender, EventArgs e)
{
this.Validate();
bs.EndEdit();
if (!ds.HasChanges())
{
MessageBox.Show("No changes to save.", "Saving Records");
return;
}
try
{
fUser.SaveUser(ds);
MessageBox.Show("Records saved.", "Saving Records");
}
catch (Exception exceptionObj)
{
MessageBox.Show(exceptionObj.Message.ToString());
}
}
User class save method is follows:
public void SaveUser(DataSet oDs)
{
oCn = da.GetConnection();
oTrn = oCn.BeginTransaction();
sqlDataMaster = new MySqlDataAdapter();
try
{
if (oCn == null)
{
oCn.Open();
}
sInsProcName = "prInsert_User";
insertcommand = new MySqlCommand(sInsProcName, oCn, oTrn);
insertcommand.CommandType = CommandType.StoredProcedure;
insertcommand.Parameters.Add(new MySqlParameter("nNewID", MySqlDbType.Int32, 0, "userID"));
insertcommand.Parameters["nNewID"].Direction = ParameterDirection.Output;
insertcommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
insertcommand.Parameters.Add("mUserName", MySqlDbType.VarChar, 50, "userName");
insertcommand.Parameters.Add("mUserPass", MySqlDbType.VarChar, 60, "userPass");
sqlDataMaster.InsertCommand = insertcommand;
sUpdProcName = "prUpdate_User";
updatecommand = new MySqlCommand(sUpdProcName, oCn, oTrn);
updatecommand.CommandType = CommandType.StoredProcedure;
updatecommand.Parameters.Add("nNewID", MySqlDbType.Int32, 0, "userID");
updatecommand.Parameters.Add("mUserName", MySqlDbType.VarChar, 50, "userName");
updatecommand.Parameters.Add("mUserPass", MySqlDbType.VarChar, 60, "userPass");
sqlDataMaster.UpdateCommand = updatecommand;
sqlDataMaster.Update(oDs.Tables[0]);
oTrn.Commit();
}
catch (MySqlException e)
{
oTrn.Rollback();
MessageBox.Show(e.ToString());
}
Data is saved successfully, no problem is there. In the password field of Table it is shows the hashed value. But problem arises when I need to validate the password via Login form. User enter username and password and click login, which fires following code:
private void btnCheck_Click(object sender, EventArgs e)
{
string hashpassdb = dm.GetData("Select userPass from userMaster where userName = " + "'" + txtUser.Text.ToString() + "'" ).Rows[0]["userPass"].ToString();
if (!BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
{
MessageBox.Show(hashpassdb);
MessageBox.Show("Invalid Username or Password.");
MessageBox.Show(BCrypt.HashPassword(txtPass.Text.Trim().ToString(), hashpassdb));
}
else
{
MessageBox.Show("Login Successfull");
((frmMain)this.MdiParent).EnableMenu();
this.Close();
}
}
private bool DoesPasswordMatch(string userEnteredPassword, string hashedPwdFromDatabase)
{
return BCrypt.CheckPassword(userEnteredPassword, hashedPwdFromDatabase);
}
dm is the instance of DAL class which contains GetData method, accepts Sql command as parameter and returns DataTable. The problem is hashed values never matched with the one using in validation, as notice in code I've use MessageBox.Show method just to ensure what value is return from Database hashed password and the one return by BCrypt.Hashpassword. They both are different. Also, I am using VarChar(60) datatype for holding hash value in Mysql.
I need some guidance about what I am doing wrong here? any help is much appreciated.
Thanks
Ahmed