Derek Slager?s BCrypt Class for C# Check Password Method failed

ahmed_one

Member
Joined
Nov 29, 2012
Messages
23
Programming Experience
Beginner
Dear All,

I am using Microsoft Visual Studio 2010 Ultimate, C# Winforms & MySql Database.

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:

C#:
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:

C#:
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:

C#:
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:

C#:
 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:

C#:
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
 
ok losing all the database stuff and going back to basics, i did a simple app using your method with a try/catch on a validation button

C#:
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;




namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_Load(object sender, EventArgs e)
        {


        }


        private void validatepassword_Click(object sender, EventArgs e)
        {
            string alreadysaltedpassword = saltedpassword.Text;
            try
            {
                if (!BCrypt.CheckPassword(verifypassword.Text.Trim().ToString(), alreadysaltedpassword))
                {
                    MessageBox.Show("Error");
                    validated.BackColor = Color.Red;
                }
                else
                {
                    MessageBox.Show("Validated");
                    validated.BackColor = Color.Green;
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        private void generate_Click(object sender, EventArgs e)
        {
            saltedpassword.Text = BCrypt.HashPassword(plainpassword.Text.Trim().ToString(), BCrypt.GenerateSalt(12));
        }


        private void plainpassword_Leave(object sender, EventArgs e)
        {
            string saltpassword = BCrypt.HashPassword(plainpassword.Text.Trim().ToString(), BCrypt.GenerateSalt(12));
            saltedpassword.Text = saltpassword;
        }


    }
}

now on the catch im getting a "index was outside the bounds of the array"

but if i switch to generating the hash using a button as opposed to the _leave method it works fine

i think the issue you are having here is when you use the _leave its not actually hashing anything

ive made that small bit of demo code available for you

you can download it here

https://philscloud.uk/index.php/s/UtMAzZ2nI8tM7YF

password for link is csharp
 
Last edited:
Back
Top Bottom