saving and comparing passwords to database as binary using md5
In an ASP.NET application, I have saved a password to the database as "Binary" data using md5.
How can I now compare passwords?
I used the code in this article to encrypt the password with md5
The code is working. How can I compare the password when users enter their password at login? What's the code to check if the password is matched with encrypted password in database.
I used the following code, but it always display "Incorrect username or password" even if it's correct."the modifird code"
Byte[] hashedBytes;
string Password = txtPassword.Text;
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
UTF8Encoding encoder = new UTF8Encoding();
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password));
Byte[] pass = new Byte[16];
SqlConnection conn = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin");
SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE UserName=@UserName", conn);
cmd.Paramete开发者_开发技巧rs.AddWithValue("@UserName", txtUserName.Text);
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
pass = (Byte[])rdr["password"];
foreach (Byte b in pass)
{
Label1.Text += b.ToString() + " ";
//Response.Write(b.ToString());
string UserName = txtUserName.Text;
bool isMatch = false;
Byte[] password = new Byte[16];
SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin");
con.Open();
SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName), con);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@UserName", txtUserName.Text);
SqlDataReader dr = cmdd.ExecuteReader();
if (dr.Read())
{
password = (Byte[])dr["Password"];
}
foreach (Byte c in password)
{
Label2.Text += c.ToString() + " ";//I didnt close the pracket fo that reason data is repeted if I close it I cant type c.toString
while (dr.Read())
{
if (b.ToString() == c.ToString()) // I mean this statment
{
isMatch = true;
}
}
}
dr.Close();
con.Close();
if (isMatch)
{
Response.Write("correct");
}
else
{
Response.Write("Incorrect username or password!");
}
}
the edited code protected void Button1_Click(object sender, EventArgs e) { } public static bool ValidateUser(string userName, string password) { SqlConnection con = new SqlConnection("Data Source=shihab-PC;Initial Catalog=test;User ID=sh;password=admin"); con.Open();
using (var connection = new SqlConnection("connectionString"))
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT dbo.checkUserExists (@userName, @password)";
command.Parameters.Add("@userName", SqlDbType.NVarChar, 25).Value = userName;
command.Parameters.Add("@password", SqlDbType.NVarChar).Value = GenerateHash(password);
connection.Open();
return (bool)command.ExecuteScalar();
}
}
private static string GenerateHash(string value)
{
return Convert.ToBase64String(new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes("salt")).ComputeHash(Encoding.UTF8.GetBytes(value)));
}
}
When you compare passwords - you need to compute the MD5 on the password they are submitting.
So in your code you want to something like this:
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
//create an array of bytes we will use to store the encrypted password
Byte[] hashedBytes;
//Create a UTF8Encoding object we will use to convert our password string to a byte array
UTF8Encoding encoder = new UTF8Encoding();
//encrypt the password and store it in the hashedBytes byte array
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(txtPassword.Text));
//set the password they are using now to password for the compare:
Password = hashedBytes;
Then after that, you can run your comparison code. The point is that the password in the database is the original hashedBytes you computed when they signed up
EDIT: here it is in your original code:
SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin");
con.Open();
string UserName = txtUserName.Text;
string Password = txtPassword.Text;
//hash password
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
Byte[] hashedBytes;
UTF8Encoding encoder = new UTF8Encoding();
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password));
Password = hashedBytes.ToString();
bool isMatch = false;
SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName),con);
SqlDataReader dr = cmdd.ExecuteReader();
while (dr.Read())
{
if (dr["password"].ToString()==Password)
{
isMatch = true;
}
}
dr.Close();
con.Close();
if (isMatch)
{
Response.Write("correct");
}
else
{
Response.Write("Incorrect username or password!");
}
Updated the code for the conversion error
Try this code to see the passwords this will print out the password that is hashed and the password in the database - if they mismatch you have a problem (possibly a salt problem)
Byte[] hashedBytes;
string Password = txtPassword.Text;
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
UTF8Encoding encoder = new UTF8Encoding();
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password));
Response.Write(string.Format("Hashed Password (Given): {0}<br />", hashedBytes.ToString()));
string UserName = txtUserName.Text;
SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin");
con.Open();
SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName),con);
SqlDataReader dr = cmdd.ExecuteReader();
//should be only one row..
while (dr.Read())
{
Response.Write(string.Format("Hashed Password (DB): {0}", dr["password"].ToString()));
}
dr.Close();
con.Close();
This is the code I adjust from your code, it´s working fine(is comparing byte to byte from stored pwd in db with current pwd given by the user):
public bool AddNewUser(string userId, string pwd, string dept,string mail,string displayName)
{
//get the username
string UserName = userId;
SqlConnection conn = new SqlConnection(GetConnectionString()); //sql command to add the user and password to the database
SqlCommand cmd = new SqlCommand("INSERT INTO MAIN_USER_DATA(USERID, PWD,DEPARTMENT,MAIL,DISPLAY_NAME) VALUES (@USERID, @PWD,@DEPARTMENT,@MAIL,@DISPLAY_NAME)", conn);
cmd.CommandType = CommandType.Text; //add parameters to our sql query
cmd.Parameters.AddWithValue("@USERID", UserName);
cmd.Parameters.AddWithValue("@PWD", GenerateHash(userId ,pwd));
cmd.Parameters.AddWithValue("@DEPARTMENT", dept);
cmd.Parameters.AddWithValue("@MAIL", mail);
cmd.Parameters.AddWithValue("@DISPLAY_NAME", displayName);
using (conn) { //open the connection
conn.Open(); //send the sql query to insert the data to our Users table
try
{
cmd.ExecuteNonQuery();
return true;
}
catch
{
return false;
}
}
}
public bool ValidateUser(string userId, string password)
{
using (SqlConnection connection = new SqlConnection(GetConnectionString()))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT PWD FROM MAIN_USER_DATA WHERE USERID=@USERID";
command.Parameters.Add("@USERID", SqlDbType.NVarChar, 25).Value = userId;
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.Read())
{
byte[] storedPwd = (byte[])dr["PWD"];
byte[] currentPwd = GenerateHash(userId, password);
for (int i = 0;i< storedPwd.Length; i++)
{
if (storedPwd[i] != currentPwd[i])
{
return false;
}
}
}
else
return false;
return true;
}
}
private byte[] GenerateHash(string userId, string password)
{
//create the MD5CryptoServiceProvider object we will use to encrypt the password
HMACSHA1 hasher = new HMACSHA1(Encoding.UTF8.GetBytes(userId)); //create an array of bytes we will use to store the encrypted password
//Byte[] hashedBytes; //Create a UTF8Encoding object we will use to convert our password string to a byte array
UTF8Encoding encoder = new UTF8Encoding(); //encrypt the password and store it in the hashedBytes byte array
return hasher.ComputeHash(encoder.GetBytes(password)); //connect to our db
}
C# code:
public static bool ValidateUser(string userName, string password)
{
using (var connection = new SqlConnection("connectionString"))
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT dbo.checkUserExists (@userName, @password)";
command.Parameters.Add("@userName", SqlDbType.NVarChar, 25).Value = userName;
command.Parameters.Add("@password", SqlDbType.NVarChar).Value = GenerateHash(password);
connection.Open();
return (bool)command.ExecuteScalar();
}
}
private static string GenerateHash(string value)
{
return Convert.ToBase64String(new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes("salt")).ComputeHash(Encoding.UTF8.GetBytes(value)));
}
SQL stored proc:
IF OBJECT_ID(N'checkUserExists', N'FN') IS NOT NULL
DROP FUNCTION checkUserExists
GO
CREATE FUNCTION checkUserExists
(
@userName NVARCHAR(25),
@password NVARCHAR(255)
)
RETURNS BIT
AS
BEGIN
RETURN ISNULL((
SELECT 1
FROM users
WHERE
name = @userName
AND password = @password
), 0)
END
精彩评论