C# 如何将用户提供的登录凭据与数据库中存储的salt和hash进行比较以允许用户登录
我在网上做了一些研究,观看了一些YouTube视频,拼凑了一段代码,对密码进行加密,然后对加密后的密码进行散列,并将加密后的密码和散列存储到数据库中。 现在,我正在研究如何将用户提供的密码与数据库中存储的salt进行比较 我不知道从这里到哪里去,我真的需要一些指导和帮助。 虽然我尝试过手动获取salt并将其与verifyPassword进行比较。但它不起作用。我相信我对代码缺乏一些理解 用户注册页面C# 如何将用户提供的登录凭据与数据库中存储的salt和hash进行比较以允许用户登录,c#,asp.net,hash,cryptography,salt,C#,Asp.net,Hash,Cryptography,Salt,我在网上做了一些研究,观看了一些YouTube视频,拼凑了一段代码,对密码进行加密,然后对加密后的密码进行散列,并将加密后的密码和散列存储到数据库中。 现在,我正在研究如何将用户提供的密码与数据库中存储的salt进行比较 我不知道从这里到哪里去,我真的需要一些指导和帮助。 虽然我尝试过手动获取salt并将其与verifyPassword进行比较。但它不起作用。我相信我对代码缺乏一些理解 用户注册页面 public class HashSalt { public strin
public class HashSalt
{
public string Hash { get; set; }
public string Salt { get; set; }
}
public static HashSalt GenerateSaltedHash(int size, string password)
{
var saltBytes = new byte[size];
var provider = new RNGCryptoServiceProvider();
provider.GetNonZeroBytes(saltBytes);
var salt = Convert.ToBase64String(saltBytes);
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltBytes, 10000);
var hashPassword = Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256));
HashSalt hashSalt = new HashSalt { Hash = hashPassword, Salt = salt };
return hashSalt;
}
protected void Button1_Click(object sender, EventArgs e)
{
HashSalt hashSalt = GenerateSaltedHash(64, txtPassConfirm.Text);
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DataBase"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("insert into Customer values (@FirstName, @LastName, @Nationality, @Email, @Tel);" +
"insert into Account values(@Email2, @Salt, @Hash);", con);
cmd.Parameters.AddWithValue("FirstName", txtFName.Text);
cmd.Parameters.AddWithValue("LastName", txtLName.Text);
cmd.Parameters.AddWithValue("Nationality", ddlNationality.SelectedItem.Text);
cmd.Parameters.AddWithValue("Email", txtMail.Text);
cmd.Parameters.AddWithValue("Tel", txtTel.Text);
cmd.Parameters.AddWithValue("Email2", txtMail.Text);
cmd.Parameters.AddWithValue("@salt", hashSalt.Salt);
cmd.Parameters.AddWithValue("@hash", hashSalt.Hash);
cmd.ExecuteNonQuery();
con.Close();
}
catch (SqlException ex)
{
if (ex.Number == 2627)
{
}
else
{
throw;
}
}
txtFName.Text = "";
txtLName.Text = "";
ddlNationality.SelectedItem.Text = "";
txtTel.Text = "";
txtMail.Text = "";
Response.Redirect("Login.aspx");
}
public static bool VerifyPassword(string enteredPassword, string storedHash, string storedSalt)
{
var saltBytes = Convert.FromBase64String(storedSalt);
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(enteredPassword, saltBytes, 10000);
return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256)) == storedHash;
}
protected void btnLogin_Click1(object sender, EventArgs e)
{
string ConnectionString = ConfigurationManager.ConnectionStrings["DataBase"].ConnectionString;
SqlConnection myConnect = new SqlConnection(ConnectionString);
string CommandText = "SELECT FirstName from Customer" + "SELECT Email, Salt, Hash from Account";
SqlCommand cmd = new SqlCommand(CommandText, myConnect);
myConnect.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
if (reader["Email"].ToString() == txtMail.Text )
{
bool isPasswordMatched = VerifyPassword(txtPass.Text,)
Session["User"] = reader["FirstName"].ToString();
}
else
{
lblResult.Text = "Incorrect Username or Password, Please Try Again!";
}
}
}
用户登录页面
public class HashSalt
{
public string Hash { get; set; }
public string Salt { get; set; }
}
public static HashSalt GenerateSaltedHash(int size, string password)
{
var saltBytes = new byte[size];
var provider = new RNGCryptoServiceProvider();
provider.GetNonZeroBytes(saltBytes);
var salt = Convert.ToBase64String(saltBytes);
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltBytes, 10000);
var hashPassword = Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256));
HashSalt hashSalt = new HashSalt { Hash = hashPassword, Salt = salt };
return hashSalt;
}
protected void Button1_Click(object sender, EventArgs e)
{
HashSalt hashSalt = GenerateSaltedHash(64, txtPassConfirm.Text);
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DataBase"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("insert into Customer values (@FirstName, @LastName, @Nationality, @Email, @Tel);" +
"insert into Account values(@Email2, @Salt, @Hash);", con);
cmd.Parameters.AddWithValue("FirstName", txtFName.Text);
cmd.Parameters.AddWithValue("LastName", txtLName.Text);
cmd.Parameters.AddWithValue("Nationality", ddlNationality.SelectedItem.Text);
cmd.Parameters.AddWithValue("Email", txtMail.Text);
cmd.Parameters.AddWithValue("Tel", txtTel.Text);
cmd.Parameters.AddWithValue("Email2", txtMail.Text);
cmd.Parameters.AddWithValue("@salt", hashSalt.Salt);
cmd.Parameters.AddWithValue("@hash", hashSalt.Hash);
cmd.ExecuteNonQuery();
con.Close();
}
catch (SqlException ex)
{
if (ex.Number == 2627)
{
}
else
{
throw;
}
}
txtFName.Text = "";
txtLName.Text = "";
ddlNationality.SelectedItem.Text = "";
txtTel.Text = "";
txtMail.Text = "";
Response.Redirect("Login.aspx");
}
public static bool VerifyPassword(string enteredPassword, string storedHash, string storedSalt)
{
var saltBytes = Convert.FromBase64String(storedSalt);
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(enteredPassword, saltBytes, 10000);
return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256)) == storedHash;
}
protected void btnLogin_Click1(object sender, EventArgs e)
{
string ConnectionString = ConfigurationManager.ConnectionStrings["DataBase"].ConnectionString;
SqlConnection myConnect = new SqlConnection(ConnectionString);
string CommandText = "SELECT FirstName from Customer" + "SELECT Email, Salt, Hash from Account";
SqlCommand cmd = new SqlCommand(CommandText, myConnect);
myConnect.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
if (reader["Email"].ToString() == txtMail.Text )
{
bool isPasswordMatched = VerifyPassword(txtPass.Text,)
Session["User"] = reader["FirstName"].ToString();
}
else
{
lblResult.Text = "Incorrect Username or Password, Please Try Again!";
}
}
}
数据库表
CREATE TABLE [dbo].[Account] (
[EMail] NVARCHAR (50) NOT NULL,
[Salt] NVARCHAR (MAX) NOT NULL,
[Hash] NVARCHAR (MAX) NOT NULL,
PRIMARY KEY CLUSTERED ([EMail] ASC)
);
如果您愿意在散列存储中使用Salt,那么应该将密码输入的Salt值保留在数据库中,附加到散列值中,或者像这样存储在另一列中 要验证密码,您的代码需要查询给定用户的salt值,并在哈希摘要方法中使用该值,方法与您在密码salt+哈希计算中使用的方法相同,然后进行比较 总结如下:
看看这个,更好地理解Salt。如果您愿意在散列存储中使用Salt,您应该将密码输入的Salt值保留在数据库中,附加到散列值后,或者像这样存储在另一列中 要验证密码,您的代码需要查询给定用户的salt值,并在哈希摘要方法中使用该值,方法与您在密码salt+哈希计算中使用的方法相同,然后进行比较 总结如下:
请看一看,以便更好地理解盐析。您可以尝试以下方法来创建和检索哈希:
public static byte[] GetHash(string inputString)
{
HashAlgorithm algorithm = SHA256.Create();
return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}
public static string GetHashString(string inputString)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in GetHash(inputString))
sb.Append(b.ToString("X2"));
return sb.ToString();
}
然后,当用户注册时,获取明文密码并生成随机salt,您只需像这样保存密码哈希:
newUser.password = GetHashString(salt + password);
别忘了还将salt保存在数据库中的某个位置(我通常将salt保存在与密码哈希相同的表中)
现在,当用户想要登录时,获取他们的输入并在数据库中搜索输入的用户名,如果返回结果(假设用户名必须是唯一的并且他们输入了有效的用户名,则应该只有一个结果),然后获取与该帐户相关联的salt并再次生成哈希:
string compareHash = GetHashString(salt + password);
现在只需将计算出的哈希值与数据库中存储的哈希值进行比较,如果两者匹配,则登录它们 您可以尝试此方法创建和检索哈希:
public static byte[] GetHash(string inputString)
{
HashAlgorithm algorithm = SHA256.Create();
return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}
public static string GetHashString(string inputString)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in GetHash(inputString))
sb.Append(b.ToString("X2"));
return sb.ToString();
}
然后,当用户注册时,获取明文密码并生成随机salt,您只需像这样保存密码哈希:
newUser.password = GetHashString(salt + password);
别忘了还将salt保存在数据库中的某个位置(我通常将salt保存在与密码哈希相同的表中)
现在,当用户想要登录时,获取他们的输入并在数据库中搜索输入的用户名,如果返回结果(假设用户名必须是唯一的并且他们输入了有效的用户名,则应该只有一个结果),然后获取与该帐户相关联的salt并再次生成哈希:
string compareHash = GetHashString(salt + password);
现在只需将计算出的哈希值与数据库中存储的哈希值进行比较,如果两者匹配,则登录它们 您似乎编写了正确的验证例程(除了不使用固定时间的相等性比较)。你真正的问题是什么/你被困在哪里?@bartonjs,我被困在调用方法上。我的引用是使用user user=getuserdetails这类代码,然后在verifypassword方法中调用它来比较salt和hash。这是我不明白的部分。此外,您能否详细说明固定时间平等比较?是否包含它是关键和重要的?您似乎已经编写了正确的验证例程(除了不使用固定时间的相等性比较)。你真正的问题是什么/你被困在哪里?@bartonjs,我被困在调用方法上。我的引用是使用user user=getuserdetails这类代码,然后在verifypassword方法中调用它来比较salt和hash。这是我不明白的部分。进一步