Closed AbeidDEV closed 1 year ago
password= '" +BCryptNet.Verify( textBoxPASSWORD.Text)+ "'"
You're using verify; which returns a bool; in a sql statement and without the hash to compare it against.
The entire things not valid.
I'd advise against handling sql like that.
You might find it easier to use something like entity framework which will provide some guard-rails as well as allowing you to skip writing sql and use the linq provider to query data. Also https://jonathancrozier.com/blog/preventing-sql-injection-in-c-sharp-applications
You would need to query the password from sql; then call Verify like BCrypt.Verify("my password from txtbox", passwordHashFromSql);
and use the bool response to fail or allow the login.
Tried which returns a bool but failed to connect to db, VS2022
I'm guessing you're new to this and its related to the repo in your account. I'll try to break the bits down.
Version control You should really just put the files in rather than a zip; gits great at letting you see the history of your changes but sadly in a zip which is basically an opaque binary to git it wont do a whole lot.
Winforms & SQL Firtly if you're interested in desktop apps I'd look at the newer stuff https://learn.microsoft.com/en-us/dotnet/maui/what-is-maui?view=net-maui-7.0 I'll openly admit to still cracking out winforms on occasion but it's pretty much on the way out in the grand scheme of things.
If your aim is to store data locally for a user and the querying isn't particularly complex you may wish to consider using something like SQLLite instead of a full blown SQL engine like MySql
Of course if you're talking to a remote sql server that's a whole different thing.
Your repo
Assuming I'm right about the winforms app; I've pulled your zip; modified the code to use bcrypt so you have an example
There's a docker-compose file in there (docker-compose up -d
) which will start mysql locally with the passwords configured etc.
The sql class is setup to bootstrap the table.
...
public MySqlDb()
{
SqlConnection = new MySqlConnection($"Server={Server};Database={Database};User ID={Uid};Password={Password}");
SqlConnection.Open();
if (BootStrapSql) return;
using var tblCheck = SqlConnection.CreateCommand();
tblCheck.CommandText = @$"
CALL sys.table_exists({Database}, users, @table_type);
SELECT @table_type;
";
var reader = tblCheck.ExecuteReader();
if (!reader.Read())
{
using var tblCommand = SqlConnection.CreateCommand();
tblCommand.CommandText = @"CREATE TABLE IF NOT EXISTS users
(
Id int(10) NOT NULL,
userName varchar(20) NOT NULL,
Password varbinary(256) NOT NULL,
Registered varchar(20) DEFAULT NULL
);
ALTER TABLE users
ADD PRIMARY KEY (Id),
ADD UNIQUE KEY userName (userName);
ALTER TABLE users
MODIFY Id int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=24;
COMMIT;
";
tblCommand.ExecuteNonQuery();
}
BootStrapSql = true;
}
It's not how I'd do this in production but for the sake of example it does the job.
The user creation changes to
...
try
{
using MySqlDb db = new MySqlDb();
using var cmd = db.SqlConnection.CreateCommand();
cmd.CommandText = "INSERT INTO users (Username, Password, Registered) values (@name, @password, now())";
cmd.Parameters.AddWithValue("@name", userName);
cmd.Parameters.AddWithValue("@password", BCrypt.Net.BCrypt.HashPassword(password));
cmd.ExecuteNonQuery();
System.Windows.Forms.MessageBox.Show("Account created", "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
return $"{userName}{password}";
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
return null;
}
...
So we take the input password from the user and we hash it as its stored.
To validate it we'd call ValidateLogin
...
try
{
using MySqlDb db = new MySqlDb();
using var cmd = db.SqlConnection.CreateCommand();
cmd.CommandText = ("Select Top 1 Username, Password from users where userName = @name;");
cmd.Parameters.AddWithValue("@name", userName);
var reader = cmd.ExecuteReader();
if (!reader.Read())
{
System.Windows.Forms.MessageBox.Show("Error", "Information",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else
{
while (reader.Read())
{
var sqlPassword = reader.GetString(1);
if (BCrypt.Net.BCrypt.Verify(password, sqlPassword))
{
System.Windows.Forms.MessageBox.Show("Hi :D", "Information",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
}
else
{
System.Windows.Forms.MessageBox.Show("Error", "Information",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
}
}
return $"{userName}{password}";
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
return null;
}
}
Thank you, for support
On Fri, 17 Feb 2023, 13:34 Chris McKee, @.***> wrote:
I'm guessing you're new to this and its related to the repo in your account. I'll try to break the bits down.
Version control You should really just put the files in rather than a zip; gits great at letting you see the history of your changes but sadly in a zip which is basically an opaque binary to git it wont do a whole lot.
Winforms & SQL Firtly if you're interested in desktop apps I'd look at the newer stuff https://learn.microsoft.com/en-us/dotnet/maui/what-is-maui?view=net-maui-7.0 I'll openly admit to still cracking out winforms on occasion but it's pretty much on the way out in the grand scheme of things.
If your aim is to store data locally for a user and the querying isn't particularly complex you may wish to consider using something like SQLLite instead of a full blown SQL engine like MySql
- https://www.codeguru.com/dotnet/using-sqlite-in-a-c-application/
https://learn.microsoft.com/en-us/xamarin/android/data-cloud/data-access/using-sqlite-orm
Of course if you're talking to a remote sql server that's a whole different thing.
Your repo
Assuming I'm right about the winforms app; I've pulled your zip; modified the code to use bcrypt so you have an example
C#_Login_Encrypt.zip https://github.com/BcryptNet/bcrypt.net/files/10765728/C._Login_Encrypt.zip
There's a docker-compose file in there (docker-compose up -d) which will start mysql locally with the passwords configured etc. The sql class is setup to bootstrap the table.
... public MySqlDb() { SqlConnection = new MySqlConnection($"Server={Server};Database={Database};User ID={Uid};Password={Password}"); SqlConnection.Open();
if (BootStrapSql) return; using var tblCheck = SqlConnection.CreateCommand(); tblCheck.CommandText = @$"CALL sys.table_exists({Database}, users, @table_type); SELECT @table_type;"; var reader = tblCheck.ExecuteReader(); if (!reader.Read()) { using var tblCommand = SqlConnection.CreateCommand(); tblCommand.CommandText = @"CREATE TABLE IF NOT EXISTS users ( Id int(10) NOT NULL, userName varchar(20) NOT NULL, Password varbinary(256) NOT NULL, Registered varchar(20) DEFAULT NULL ); ALTER TABLE users ADD PRIMARY KEY (Id), ADD UNIQUE KEY userName (userName); ALTER TABLE users MODIFY Id int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=24; COMMIT; "; tblCommand.ExecuteNonQuery(); } BootStrapSql = true; }
It's not how I'd do this in production but for the sake of example it does the job.
The user creation changes to
... try { using MySqlDb db = new MySqlDb();
using var cmd = db.SqlConnection.CreateCommand(); cmd.CommandText = "INSERT INTO users (Username, Password, Registered) values ***@***.***, @password, now())"; ***@***.***", userName); ***@***.***", BCrypt.Net.BCrypt.HashPassword(password)); cmd.ExecuteNonQuery(); System.Windows.Forms.MessageBox.Show("Account created", "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); return $"{userName}{password}"; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); return null; }
...
So we take the input password from the user and we hash it as its stored.
To validate it we'd call ValidateLogin
- Which selects the first match on username
- extracts the password hash from the results
- Passes the hash to bcrypt with the user entered password.
- BCrypt then uses the SALT portion of the hash to hash the user-entered password in exactly the same way as when it was generated
- If the two strings match (if you look at the bcrypt code you'll see we do this in a de-optimized fashion to try and ensure timing attacks dont work)
- Return pass or fail depending on the verify response
... try { using MySqlDb db = new MySqlDb();
using var cmd = db.SqlConnection.CreateCommand(); cmd.CommandText = ("Select Top 1 Username, Password from users where userName = @name;"); ***@***.***", userName); var reader = cmd.ExecuteReader(); if (!reader.Read()) { System.Windows.Forms.MessageBox.Show("Error", "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } else { while (reader.Read()) { var sqlPassword = reader.GetString(1); if (BCrypt.Net.BCrypt.Verify(password, sqlPassword)) { System.Windows.Forms.MessageBox.Show("Hi :D", "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } else { System.Windows.Forms.MessageBox.Show("Error", "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } } } return $"{userName}{password}"; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "Information", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); return null; } }
— Reply to this email directly, view it on GitHub https://github.com/BcryptNet/bcrypt.net/issues/130#issuecomment-1434446970, or unsubscribe https://github.com/notifications/unsubscribe-auth/A5NZW4QDHNBAGIRZS7FXWG3WX5H4BANCNFSM6AAAAAAU56J4XI . You are receiving this because you authored the thread.Message ID: @.***>
No problem
Great, thanks!
On Fri, 17 Feb 2023, 15:14 Chris McKee, @.***> wrote:
No problem
— Reply to this email directly, view it on GitHub https://github.com/BcryptNet/bcrypt.net/issues/130#issuecomment-1434557454, or unsubscribe https://github.com/notifications/unsubscribe-auth/A5NZW4WSAAWURLP5CDVJUHTWX5TRDANCNFSM6AAAAAAU56J4XI . You are receiving this because you authored the thread.Message ID: @.***>
} } catch (Exception ex) { MessageBox.Show("No network"); }