Derek Slager's BCrypt Class for C# Check Password Method failed
-
Hi to all, This is with continuation of my previous question here. 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:
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(); -
Hi to all, This is with continuation of my previous question here. 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:
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();I had a very quick look at what was going on - essentially, this
if (!BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
is wrong - which I think stems from this
txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12));
The crux is you're generating a NEW salt when you use BCrypt.GenerateSalt(12) - you should use the original hashpassdb instead (I don't know how you are going to do that) The reason is, hashpassdb contains the original salt value. The clue is in BCrypt's code, function CheckPassword
public static bool CheckPassword(string plaintext, string hashed) { return StringComparer.Ordinal.Compare(hashed, HashPassword(plaintext, hashed)) == 0; }
'g'
-
I had a very quick look at what was going on - essentially, this
if (!BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
is wrong - which I think stems from this
txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12));
The crux is you're generating a NEW salt when you use BCrypt.GenerateSalt(12) - you should use the original hashpassdb instead (I don't know how you are going to do that) The reason is, hashpassdb contains the original salt value. The clue is in BCrypt's code, function CheckPassword
public static bool CheckPassword(string plaintext, string hashed) { return StringComparer.Ordinal.Compare(hashed, HashPassword(plaintext, hashed)) == 0; }
'g'
Garth J Lancaster wrote:
if (!BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
is wrong - which I think stems from this
txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12));
Thanks for your reply... But txtPass.Text.Trim().ToString() is not generated from txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12)); Infact, there is no txtHash textbox in user login form, it only has 2 textboxes, username and password. Then uses password value (txtPass.Text.Trim.ToString())with BCrypt.CheckPassword routine with hashpassdb (retrieve from database). txtHash textbox is used in the Form where new user is created with Username and password. It is actually hidden textbox, use only to save hash value of password in database.
-
Garth J Lancaster wrote:
if (!BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
is wrong - which I think stems from this
txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12));
Thanks for your reply... But txtPass.Text.Trim().ToString() is not generated from txtHash.Text = BCrypt.HashPassword(txtPass.Text.Trim().ToString(),BCrypt.GenerateSalt(12)); Infact, there is no txtHash textbox in user login form, it only has 2 textboxes, username and password. Then uses password value (txtPass.Text.Trim.ToString())with BCrypt.CheckPassword routine with hashpassdb (retrieve from database). txtHash textbox is used in the Form where new user is created with Username and password. It is actually hidden textbox, use only to save hash value of password in database.
Im sorry, I think you're missing the point - you're not getting the correct results because you're not comparing 'apples with apples' If you start with a password A And generate Hashed-Salted-Password-A (and then store Hashed-Salted-Password-A) And then want to compare that with Password B You have to compare Hashed-Salted-Password-A with HashPassword(Password B, Hashed-Salted-Password-A) 'g'
-
Im sorry, I think you're missing the point - you're not getting the correct results because you're not comparing 'apples with apples' If you start with a password A And generate Hashed-Salted-Password-A (and then store Hashed-Salted-Password-A) And then want to compare that with Password B You have to compare Hashed-Salted-Password-A with HashPassword(Password B, Hashed-Salted-Password-A) 'g'
Garth J Lancaster wrote:
Im sorry, I think you're missing the point - you're not getting the correct results because you're not comparing 'apples with apples'
Actually I am also trying to do the same, but what I don't understand is why it is not working. Let me re-phrase my problem without code: Form User Creation: 1.New User create with Username and Password, password is hashed and stored in db,using a hidden textbox (txtHash). Form User Login: 1. User enter username and password. 2. Get hashed password from db and stored it in hashpassdb string. 3. Now compare the user entered password with BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb)) I know there is something wrong in logic behind User login form, but I am unable to track it. I've used breakpoints in BCrypt.Checkpassword function to check what values are in, and they are different. But the question is why?
-
Garth J Lancaster wrote:
Im sorry, I think you're missing the point - you're not getting the correct results because you're not comparing 'apples with apples'
Actually I am also trying to do the same, but what I don't understand is why it is not working. Let me re-phrase my problem without code: Form User Creation: 1.New User create with Username and Password, password is hashed and stored in db,using a hidden textbox (txtHash). Form User Login: 1. User enter username and password. 2. Get hashed password from db and stored it in hashpassdb string. 3. Now compare the user entered password with BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb)) I know there is something wrong in logic behind User login form, but I am unable to track it. I've used breakpoints in BCrypt.Checkpassword function to check what values are in, and they are different. But the question is why?
ahmed_one wrote:
3. Now compare the user entered password with BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
yes, but, arnt you doing something funky in txtPass.Leave event ? that means the result you get from
txtPass.Text.Trim().ToString()
is effectively
HashPassword(user entered password ,BCrypt.GenerateSalt(12));
?
-
ahmed_one wrote:
3. Now compare the user entered password with BCrypt.CheckPassword(txtPass.Text.Trim().ToString(), hashpassdb))
yes, but, arnt you doing something funky in txtPass.Leave event ? that means the result you get from
txtPass.Text.Trim().ToString()
is effectively
HashPassword(user entered password ,BCrypt.GenerateSalt(12));
?
As you've quote point number 3, which is related to User login form, there is no txtPass.leave event used in User Login form. It is only used in User Creation Form, so ultimately there is no:
HashPassword(user entered password ,BCrypt.GenerateSalt(12));
Used for txtPass. It's the plaintext where user enter password. I know what you are trying to say, that when comparing password, what I am doing is to generate new hash due to the result of GenerateSalt(12). But this is not the case, I simply get hash value from db and put it in CheckPassword method alongwith plaintext password enter by user. I am sure BCrypt.GenerateSalt(12) is not call anywhere in UserLogin form. I am following this guide in my application.
-
As you've quote point number 3, which is related to User login form, there is no txtPass.leave event used in User Login form. It is only used in User Creation Form, so ultimately there is no:
HashPassword(user entered password ,BCrypt.GenerateSalt(12));
Used for txtPass. It's the plaintext where user enter password. I know what you are trying to say, that when comparing password, what I am doing is to generate new hash due to the result of GenerateSalt(12). But this is not the case, I simply get hash value from db and put it in CheckPassword method alongwith plaintext password enter by user. I am sure BCrypt.GenerateSalt(12) is not call anywhere in UserLogin form. I am following this guide in my application.
ok, which version of BCrypt are you using ?
-
ok, which version of BCrypt are you using ?
-
Derek Slagers Bcrypt class. Downloaded from http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx[^]
There appears to be a more up-to-date version here http://bcrypt.codeplex.com/[^] Nonetheless, I did a quick and dirty test with that version you used with VS2005 :-
namespace DSBcryptTest
{
class Program
{
static void Main(string[] args)
{
String Password_Text = "Lorem_ipsum_dolor_sit_amet";String Password\_Hashed = BCrypt.HashPassword(Password\_Text, BCrypt.GenerateSalt(12)); Console.WriteLine("Hashed Password {0}", Password\_Hashed); String Test\_Password\_Text = Password\_Text; if (BCrypt.CheckPassword(Test\_Password\_Text, Password\_Hashed)) { Console.WriteLine("Passwords Match"); } } }
and there was nothing wrong / I got the expected result - obviously I should be using Nunit/unit tests etc, but meh ... I copied BCrypt.cs into a new project, removed the assembly directive at the top, then used it directly as opposed to the dll version - but that wouldn't matter - it just means I can step into the code So, Im sorry, I cant think of where to go
-
There appears to be a more up-to-date version here http://bcrypt.codeplex.com/[^] Nonetheless, I did a quick and dirty test with that version you used with VS2005 :-
namespace DSBcryptTest
{
class Program
{
static void Main(string[] args)
{
String Password_Text = "Lorem_ipsum_dolor_sit_amet";String Password\_Hashed = BCrypt.HashPassword(Password\_Text, BCrypt.GenerateSalt(12)); Console.WriteLine("Hashed Password {0}", Password\_Hashed); String Test\_Password\_Text = Password\_Text; if (BCrypt.CheckPassword(Test\_Password\_Text, Password\_Hashed)) { Console.WriteLine("Passwords Match"); } } }
and there was nothing wrong / I got the expected result - obviously I should be using Nunit/unit tests etc, but meh ... I copied BCrypt.cs into a new project, removed the assembly directive at the top, then used it directly as opposed to the dll version - but that wouldn't matter - it just means I can step into the code So, Im sorry, I cant think of where to go
Thanks for reply.
Garth J Lancaster wrote:
I copied BCrypt.cs into a new project, removed the assembly directive at the top, then used it directly as opposed to the dll version - but that wouldn't matter - it just means I can step into the code
I didn't get the above part "removed the assembly directive"?? what does it mean? I am also using BCrypt.cs file not the dll.. May be assembly directive has something to do with my problem?
-
Thanks for reply.
Garth J Lancaster wrote:
I copied BCrypt.cs into a new project, removed the assembly directive at the top, then used it directly as opposed to the dll version - but that wouldn't matter - it just means I can step into the code
I didn't get the above part "removed the assembly directive"?? what does it mean? I am also using BCrypt.cs file not the dll.. May be assembly directive has something to do with my problem?
nup, not the issue - you wouldn't even be able to build it if that were the issue - I had a 'Duplicate AssemblyVersion Attribute' error with the same in AssemblyInfo.cs - so I removed [assembly: System.Reflection.AssemblyVersion("0.1")] from near the top of my copy of BCrypt.cs All I proved was there's nothing obviously wrong with that version of BCrypt.cs, but it was only one test
-
Thanks for reply.
Garth J Lancaster wrote:
I copied BCrypt.cs into a new project, removed the assembly directive at the top, then used it directly as opposed to the dll version - but that wouldn't matter - it just means I can step into the code
I didn't get the above part "removed the assembly directive"?? what does it mean? I am also using BCrypt.cs file not the dll.. May be assembly directive has something to do with my problem?
btw - what is the length of the hashed password you get back from the DB ?
-
nup, not the issue - you wouldn't even be able to build it if that were the issue - I had a 'Duplicate AssemblyVersion Attribute' error with the same in AssemblyInfo.cs - so I removed [assembly: System.Reflection.AssemblyVersion("0.1")] from near the top of my copy of BCrypt.cs All I proved was there's nothing obviously wrong with that version of BCrypt.cs, but it was only one test
-
btw - what is the length of the hashed password you get back from the DB ?
-
btw - what is the length of the hashed password you get back from the DB ?
I don't believe it...I've done hours and hours of testing and all of them is succeed...And guess what is the stupid mistake I was doing?? I've accidentally set CharacterCasing to upper when creating new user...And in Login Form it is set to default normal. Now it is working... Thanks for be patient with my stupidity. Ahmed
-
I don't believe it...I've done hours and hours of testing and all of them is succeed...And guess what is the stupid mistake I was doing?? I've accidentally set CharacterCasing to upper when creating new user...And in Login Form it is set to default normal. Now it is working... Thanks for be patient with my stupidity. Ahmed
Well done for fixing it. Don't be worried about it - we've all made mistakes like this at one time or another.
-
Well done for fixing it. Don't be worried about it - we've all made mistakes like this at one time or another.
-
I don't believe it...I've done hours and hours of testing and all of them is succeed...And guess what is the stupid mistake I was doing?? I've accidentally set CharacterCasing to upper when creating new user...And in Login Form it is set to default normal. Now it is working... Thanks for be patient with my stupidity. Ahmed
as POH said 'well done' - you got there in the end 'next time', when using someone else's code, knock up a set of unit tests and make sure its working before you start coding against it in anger - that will eliminate it from the things you have to consider when it all looks pear-shaped 'g'
-
as POH said 'well done' - you got there in the end 'next time', when using someone else's code, knock up a set of unit tests and make sure its working before you start coding against it in anger - that will eliminate it from the things you have to consider when it all looks pear-shaped 'g'