使用 md5 将密码保存和比较到数据库作为二进制文件
Posted
技术标签:
【中文标题】使用 md5 将密码保存和比较到数据库作为二进制文件【英文标题】:saving and comparing passwords to database as binary using md5 【发布时间】:2010-11-11 18:19:40 【问题描述】:在一个 ASP.NET 应用程序中,我使用 md5 将密码保存为数据库的“二进制”数据。
我现在如何比较密码?
我用code in this article to encrypt the password with md5
代码正在运行。用户在登录时输入密码时如何比较密码?检查密码是否与数据库中的加密密码匹配的代码是什么。
我使用了下面的代码,但它总是显示“不正确的用户名或密码”,即使它是正确的。“修改代码”
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.Parameters.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!");
编辑后的代码 protected void Button1_Click(对象发送者,EventArgs e) 公共静态布尔验证用户(字符串用户名,字符串密码) SqlConnection con = new SqlConnection("数据源=shihab-PC;初始目录=test;用户ID=sh;密码=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)));
【问题讨论】:
MD5 不加密;没有办法解密,没有暴力破解或者MD5的弱点。 MD5 是一个哈希;许多不同的输入可以产生相同的哈希输出。 还有几点:1)MD5坏了;使用 SHA-1 或(更好的)SHA-2。 2) 每行使用不同的盐。 我不想解密我只想比较用户输入的密码和存储在数据库中的密码 你应该使用好的密钥推导函数如PBKDF2,不要玩md5/sha-1/sha-2。 en.wikipedia.org/wiki/Key_derivation_function .net 中 PBKDF2 的实现:msdn.microsoft.com/en-us/library/… 【参考方案1】:当您比较密码时 - 您需要计算他们提交的密码的 MD5。
所以在你的代码中你想要这样的东西:
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;
然后,您可以运行比较代码。关键是数据库中的密码是他们注册时计算的原始 hashedBytes
编辑:它在您的原始代码中:
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!");
更新了转换错误的代码
尝试此代码查看密码这将打印出经过哈希处理的密码和数据库中的密码 - 如果它们不匹配,您就有问题(可能是盐问题)
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();
【讨论】:
你能详细解释一下我不知道在哪里添加你的代码。 第 88 行错误:密码 = hashedBytes; //编译器错误消息:CS0029:无法将类型'byte[]'隐式转换为'string' IM 的问题是这个主题(使用 md5 加密)对我来说是一个新主题,我也不知道如何将字符串转换为字节,反之亦然。我尝试了更新的代码,但仍然存在同样的问题 我也有一个疑问,为什么我们需要将其转换为 string 。我们不能将字节与字节进行比较 dr["password"] 返回一个字符串,因此您必须将一个转换为另一个。【参考方案2】:这是我根据您的代码调整的代码,它工作正常(正在将 db 中存储的 pwd 中的字节与用户给出的当前 pwd 进行比较):
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
【讨论】:
【参考方案3】:C#代码:
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 存储过程:
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
【讨论】:
另见***.com/questions/1300890/… “编译器错误消息:CS1012:字符文字中的字符太多”而且浅蓝色线条是黑色的,我应该在开头添加任何语句 @shihab:你有像char x = 'ab'
这样的代码吗?您不能添加超过 1 个字符来输入 char
!
我没有得到你的问题。我粘贴了您的代码并运行它,结果是“字符文字中的字符太多”“
第 95 行:IF OBJECT_ID(N'checkUserExists', N'FN') IS NOT NULL以上是关于使用 md5 将密码保存和比较到数据库作为二进制文件的主要内容,如果未能解决你的问题,请参考以下文章
loadrunner 里面 怎样将网站的登录密码进行MD5解密之后 做参数化?