I am trying to verify a hashed password in my database which has been hashed with BCrypt.
I have two web forms, a login page and registration page.
In the registration page i create the hash, verify the hash and insert it into the database. Works fine.
In the login page i select the hashed password from the database and compare it with the submitted password from the text box.
I seem to be having trouble when verifying the hash in the database against the submitted password, i don't know what is going wrong.
Here is the registration page code:
protected void registerbutton_Click(object sender, EventArgs e)
{
string myPassword = passwordtextbox.Text;
string mySalt = BCryptHelper.GenerateSalt();
string myHash = BCryptHelper.HashPassword(myPassword, mySalt);
bool doesPasswordMatch = BCryptHelper.CheckPassword(myPassword, myHash);
if (doesPasswordMatch == true)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
using (SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Users (Username, Password, FirstName, LastName) VALUES (#username, #password, #firstname, #lastname)", conn))
{
cmd.Parameters.Add("#username", SqlDbType.NVarChar).Value = usernametextbox.Text;
cmd.Parameters.Add("#password", SqlDbType.Char).Value = myHash;
cmd.Parameters.Add("#firstname", SqlDbType.NVarChar).Value = firstnametextbox.Text;
cmd.Parameters.Add("#lastname", SqlDbType.NVarChar).Value = lastnametextbox.Text;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
registerlabel3.Text = myHash;
}
}
else
{
registerlabel3.Text = "Error";
}
}
Here is the login page code:
protected void loginbutton_Click(object sender, EventArgs e)
{
const string query = "SELECT Username, Password FROM dbo.Users WHERE Username = #username";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
cmd.Parameters.Add("#username", SqlDbType.NVarChar).Value = usernametextbox.Text;
conn.Open();
//string hashedPassword = BCrypt.Net.BCrypt.HashPassword(passwordtextbox.Text);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var passwordInDb = reader.GetString(1);
Label3.Text = "submitted = " + passwordtextbox.Text;
Label4.Text = "database hash = " + passwordInDb;
if(BCryptHelper.CheckPassword(passwordtextbox.Text, reader.GetString(1)))
{
//login
loginlabel.Text = "Success";
}
else
{
loginlabel.Text = "Error";
}
}
}
}
}
Help and Feedback is appreciated.
When writing to the database, try:
protected void registerbutton_Click(object sender, EventArgs e)
{
....
cmd.Parameters.Add("#password", SqlDbType.NVarChar).Value = myHash;
....
}
Set the database field to CHAR(60)
I set my database field where the hashed password is stored to CHAR(60) and now it works.
Why it has to be specifically CHAR(60), i don't know, but it works.
Would be nice if this could be explained.
Related
I am a newbie.
I am attempting to check for duplicate database entries. My problem is:
I would like a success alert shown if the entry is successful.
A notification of duplicates shown if a duplicate exists.
My issue is: the alert for duplicates gets shown multiple times, however, the entry is never created if no duplicates exist.
This is my code:
/// <summary>
/// The following procedure creates the user account in the database The procedure first attempts to
/// perform a check for duplicates before submitting the registration info
/// </summary>
protected void BTN_CreateACNT_Click(object sender, EventArgs e)
{
string InsertQuery = "";
string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Reimburse"].ConnectionString;
InsertQuery = "Insert into TBL_Logins (FirstName, LastName, EmailAddress, Password) VALUES(#FirstName, #LastName, #EmailAddress, #Password)";
String FirstNameSTR = FN.Text.Trim();
String LastNameSTR = LN.Text.Trim();
String EMailAddressSTR = EmailAddress.Text.Trim();
byte[] PassByte = StrToByteArray(PWD.Text.Trim());
// CheckUser(EMailAddressSTR);
while (CheckUser(EMailAddressSTR) == false)
{
SqlConnection CN = new SqlConnection(ConnectionString);
SqlCommand CMD = new SqlCommand(InsertQuery, CN);
CMD.CommandType = CommandType.Text;
CMD.Parameters.AddWithValue("#Firstname", FirstNameSTR);
CMD.Parameters.AddWithValue("#LastName", LastNameSTR);
CMD.Parameters.AddWithValue("#EmailAddress", EMailAddressSTR);
CMD.Parameters.AddWithValue("#Password", PassByte);
CN.Open();
CMD.ExecuteNonQuery();
Response.Write("<script language='javascript'>alert('Account created successfully.');</script>");
CN.Close();
}
}
public bool CheckUser(String UserString)
{
String UserSelect = "Select * from TBL_Logins where EmailAddress = #EmailAddress";
int MailCount = 0;
string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Reimburse"].ConnectionString;
SqlConnection CN = new SqlConnection(ConnectionString);
UserString = EmailAddress.Text.Trim();
SqlCommand CMD = new SqlCommand(UserSelect, CN);
CMD.Parameters.AddWithValue("#EmailAddress", UserString);
CN.Open();
SqlDataReader dr = CMD.ExecuteReader();
while (dr.Read())
{
if (UserString == dr["EmailAddress"].ToString())
{
Response.Write("<script language='javascript'>alert('This EMail address is already taken. Please try again.');</script>");
// return true;
}
}
CN.Close();
return true;
}
protected void BTN_CreateACNT_Click(object sender, EventArgs e)
{
string InsertQuery = "";
string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Reimburse"].ConnectionString;
InsertQuery = "Insert into TBL_Logins (FirstName, LastName, EmailAddress, Password) VALUES(#FirstName, #LastName, #EmailAddress, #Password)";
String FirstNameSTR = FN.Text.Trim();
String LastNameSTR = LN.Text.Trim();
String EMailAddressSTR = EmailAddress.Text.Trim();
byte[] PassByte = StrToByteArray(PWD.Text.Trim());
// CheckUser(EMailAddressSTR);
while(CheckUser(EMailAddressSTR) == false)
{
SqlConnection CN = new SqlConnection(ConnectionString);
SqlCommand CMD = new SqlCommand(InsertQuery, CN);
CMD.CommandType = CommandType.Text;
CMD.Parameters.AddWithValue("#Firstname", FirstNameSTR);
CMD.Parameters.AddWithValue("#LastName", LastNameSTR);
CMD.Parameters.AddWithValue("#EmailAddress", EMailAddressSTR);
CMD.Parameters.AddWithValue("#Password", PassByte);
CN.Open();
CMD.ExecuteNonQuery();
Response.Write("<script language='javascript'>alert('Account created successfully.');</script>");
CN.Close();
}
}
public bool CheckUser(String UserString)
{
String UserSelect = "Select * from TBL_Logins where EmailAddress = #EmailAddress";
int MailCount = 0;
string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Reimburse"].ConnectionString;
SqlConnection CN = new SqlConnection(ConnectionString);
UserString = EmailAddress.Text.Trim();
SqlCommand CMD = new SqlCommand(UserSelect,CN);
CMD.Parameters.AddWithValue("#EmailAddress", UserString);
CN.Open();
SqlDataReader dr = CMD.ExecuteReader();
while (dr.Read())
{
if (UserString == dr["EmailAddress"].ToString())
{
Response.Write("<script language='javascript'>alert('This EMail address is already taken. Please try again.');</script>");
// return true;
}
}
CN.Close();
return true;
}
Looks like the CheckUser method always returns true and that's why the insertion does not work, update the method to return false by default:
while (dr.Read())
{
if (UserString == dr["EmailAddress"].ToString())
{
Response.Write("<script language='javascript'>alert('This EMail address is already taken. Please try again.');</script>");
return true; // return true if user exists
}
}
CN.Close();
return false; // return false if the user does not exist
It is also recommended to use using block to dispose the DB connection instead of manually invoking the Close() method.
I want to check if a username is already in the database. It comes along with my update statement. I have this code and I do not know where to put the select statement:
protected void btn_update_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(conn);
con.Open();
str = "update UserData set Password=#Password where UserName='" + txtUser.Text + "'";
com = new SqlCommand(str, con);
com.Parameters.Add(new SqlParameter("#Password", SqlDbType.VarChar));
com.Parameters["#Password"].Value = BusinessLayer.ShoppingCart.CreateSHAHash(txtPW.Text);
com.ExecuteNonQuery();
con.Close();
Label1.Visible = true;
Label1.Text = "Password changed Successfully!" ;
con.Close();
}
I want something like
"Select Username from Userdata Where Username = txtUser.Text"
You don't need a SELECT here. ExecuteNonQuery() returns the number of rows affected, which means that when it returns 0, there was no user with the given name in the database. If all went well, it should return 1.
Your code is vulnerable to SQL injection and leaks resources. Here's a better version:
protected void btn_update_Click(object sender, EventArgs e)
{
using(var con = new SqlConnection(conn))
{
con.Open();
var commandTest = "update UserData set Password=#Password where UserName=#Username";
using(var com = new SqlCommand(commandTest, con))
{
com.Parameters.AddWithValue("#Username", txtUser.Text);
com.Parameters.AddWithValue("#Password", BusinessLayer.ShoppingCart.CreateSHAHash(txtPW.Text));
if(com.ExecuteNonQuery() == 1)
{
Label1.Visible = true;
Label1.Text = "Password changed Successfully!" ;
}
}
}
}
i am trying to encrypt a password and be able to log in with it. here is my hash code inside my businesslayer folder under shopping cart class.
public static string CreateSHAHash(string Phrase)
{
SHA512Managed HashTool = new SHA512Managed();
Byte[] PhraseAsByte = System.Text.Encoding.UTF8.GetBytes(string.Concat(Phrase));
Byte[] EncryptedBytes = HashTool.ComputeHash(PhraseAsByte);
HashTool.Clear();
return Convert.ToBase64String(EncryptedBytes);
}
and here is my registration code where i included the hash with the password. i am successful in registering an account and having an encrypted password in my database with this:
protected void btn_Registration_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
conn.Open();
string insertQuery = "insert into UserData(Username,Firstname,Lastname,Email,Password,CustomerType,DeliveryAddress,Zip,ContactNumber)values(#Username,#Firstname,#Lastname,#Email,#Password,#CustomerType,#DeliveryAddress,#Zip,#ContactNumber)";
SqlCommand scm = new SqlCommand(insertQuery, conn);
scm.Parameters.AddWithValue("#Username", txtUser.Text);
scm.Parameters.AddWithValue("#Firstname", txtFN.Text);
scm.Parameters.AddWithValue("#Lastname", txtLN.Text);
scm.Parameters.AddWithValue("#Email", txtEmail.Text);
scm.Parameters.AddWithValue("#Password", BusinessLayer.ShoppingCart.CreateSHAHash(txtPW.Text));
scm.Parameters.AddWithValue("#CustomerType", RadioButtonList1.SelectedItem.ToString());
scm.Parameters.AddWithValue("#DeliveryAddress", txtAddress.Text);
scm.Parameters.AddWithValue("#Zip", txtZip.Text);
scm.Parameters.AddWithValue("#ContactNumber", txtContact.Text);
scm.ExecuteNonQuery();
Session["Contact"]= txtContact.Text;
Session["Email"] = txtEmail.Text;
Session["DeliveryAddress"] = txtAddress.Text;
label_register_success.Text = ("Registration Successful!");
//Response.Redirect("Home.aspx");
conn.Close();
}
catch (Exception ex)
{
Response.Write("Error:" + ex.ToString());
}
}
However, when i try to log in with the password that i have registered, its not letting me in. here is the code:
protected void btn_Login_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("Data Source = 'PAULO'; Initial Catalog=ShoppingCartDB;Integrated Security =True");
conn.Open();
string checkuser = "select count(*) from UserData where Username = '" + txtUser.Text + "'";
SqlCommand scm = new SqlCommand(checkuser, conn);
int temp = Convert.ToInt32(scm.ExecuteScalar().ToString());
conn.Close();
if (temp == 1)
{
conn.Open();
string checkPassword = "select Password from UserData where Username ='" + txtUser.Text + "'";
SqlCommand passCom = new SqlCommand(checkPassword, conn);
string password = passCom.ExecuteScalar().ToString();
if (password == BusinessLayer.ShoppingCart.CreateSHAHash(txtPassword.Text))
{
Session["New"] = txtUser.Text;
Response.Write("<script>alert('Logged In')</script>");
Response.Redirect("OrderNow.aspx");
}
else
{
lblcrederror.Text = ("Credentials dont match");
}
}
else
{
lblcrederror.Text = ("Credentials dont match");
}
}
what am i missing here? thank you
I already could make the password to become not stored as the original text in the database. But while I want to retrieve it and check between the entered password with in the database, the error appears
Value cannot be null
on this line of code:
string verifyHashedPassword = Convert.ToString(Crypto.VerifyHashedPassword(_registration.hashedPassword, this.textBox2.Text));
Here is the code that I am using for Login:
string connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=..\db1.accdb";
Registration _registration = new Registration();
private void CheckUserDatabase(object sender, EventArgs e)
{
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
string query = "SELECT [Username], [Password], [UserType], [UserStore] FROM [Member] WHERE [Username] = #Username AND [Password] = #Password";
string verifyHashedPassword = Convert.ToString(Crypto.VerifyHashedPassword(_registration.hashedPassword, this.textBox2.Text));
conn.Open();
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.Add("#Username", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#Username"].Value = this.textBox1.Text;
cmd.Parameters.Add("#Password", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#Password"].Value = verifyHashedPassword;
using (OleDbDataReader dReader = cmd.ExecuteReader())
{
if (dReader.Read())
{
UserInformation.CurrentLoggedInUser = (string)dReader["Username"];
UserInformation.CurrentLoggedInUserType = (string)dReader["UserType"];
UserInformation.CurrentLoggedInUserStore = (string)dReader["UserStore"];
}
else
{
RecursiveClearTextBoxes(this.Controls);
}
dReader.Close();
conn.Close();
}
}
}
}
Here is the code for Registration:
string connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=..\db1.accdb";
private void AddDatabase(object sender, EventArgs e)
{
string query = "INSERT INTO [Member] ([Username], [Password], [UserType], [UserStore]) VALUES (#Username, #Password, #UserType, #UserStore)";
string hashedPassword = Crypto.HashPassword(this.textBox2.Text);
OleDbConnection _conn = new OleDbConnection(connectionString);
_conn.Open();
using (OleDbCommand cmd = new OleDbCommand(query, _conn))
{
cmd.Parameters.Add("#Username", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#Username"].Value = this.textBox1.Text;
cmd.Parameters.Add("#Password", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#Password"].Value = hashedPassword;
cmd.Parameters.Add("#UserType", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#UserType"].Value = this.textBox3.Text;
cmd.Parameters.Add("#UserStore", System.Data.OleDb.OleDbType.VarChar);
cmd.Parameters["#UserStore"].Value = this.textBox4.Text;
cmd.ExecuteNonQuery();
DialogResult _dialogResult = MessageBox.Show("Added Successfully", "Success", MessageBoxButtons.OK);
if (_dialogResult == DialogResult.OK)
{
this.Hide();
this.Close();
}
}
}
}
Any help?
Your answer much appreciated!
Thank you
I have simple registration page, wherein after submitting the contents (Username and Password) of the page, I need to assign the User with a role.
I have created 2 roles (Admin and member) from WSAT GUI..
So how'd I assign him with the "member role"
This is my registration form..
protected void Button1_Click(object sender, EventArgs e)
{
string EPass = Helper.ComputeHash(TextBox2.Text, "SHA512", null);
String var = System.Configuration.ConfigurationManager.ConnectionStrings["KKSTechConnectionString"].ConnectionString;
SqlConnection conn = new SqlConnection(var);
String str = #"insert into Users (Username, Pass, EmpID, Rolename)
values(#Username, #Pass, #EmpID, #Rolename)";
SqlCommand cmd = new SqlCommand(str, conn);
cmd.CommandText = str;
cmd.CommandType = CommandType.Text;
try
{
var userName = TextBox1.Text;
conn.Open();
cmd.Parameters.AddWithValue("#Username", TextBox1.Text);
cmd.Parameters.AddWithValue("#Pass", EPass.ToString());
cmd.Parameters.AddWithValue("#EmpID", DropDownList1.SelectedValue);
cmd.Parameters.AddWithValue("#Rolename", DropDownList2.SelectedValue);
cmd.ExecuteNonQuery();
}
finally
{
conn.Close();
}
}
dbo.Users:
Username(PK) | Pass | EmpID (FK) | Rolename
As i got you right Roles.AddUserToRoles will help you.
var userName = TextBox1.Text;
Roles.AddUserToRole(userName, "member");
To get users in role you can use Roles.GetUsersInRole (Note: it will returns their names only).
PS
It better to use standart membership from the box. My previous answer can help you.