![](/img/trans.png)
[英]How to validate Salted Password and Username for windows application in c#?
[英]How to validate salted and hashed password in c#
我使用以下方法对密码进行加盐和哈希处理
public string CreateSalt(int size)
{
var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
var buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
public string GenerateSHA256Hash(String input, String salt)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
System.Security.Cryptography.SHA256Managed sha256hashstring =
new System.Security.Cryptography.SHA256Managed();
byte[] hash = sha256hashstring.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public void Submit1_click(object sender, EventArgs r)
{
try
{
String salt = CreateSalt(10);
String hashedpassword = GenerateSHA256Hash(password1.Text, salt);
string MyConString = "SERVER=localhost;DATABASE=mydb;UID=root;PASSWORD=abc123;";
MySqlConnection connection = new MySqlConnection(MyConString);
string cmdText = "INSERT INTO authentication(agentlogin ,password ,question ,answer)VALUES ( @login, @pwd, @question, @answer)";
MySqlCommand cmd = new MySqlCommand(cmdText, connection);
cmd.Parameters.AddWithValue("@login", labeluname.Text);
cmd.Parameters.AddWithValue("@pwd", hashedpassword);
cmd.Parameters.AddWithValue("@question", ddlquestion.Text);
cmd.Parameters.AddWithValue("@answer", txtanswer.Text);
connection.Open();
int result = cmd.ExecuteNonQuery();
connection.Close();
lblmsg.Text = "Registered succesfully";
lblmsg.ForeColor = System.Drawing.Color.Green;
Response.Redirect("index.aspx");
}
catch (Exception)
{
Console.Write("not entered");
lblmsg.Text = "Registration failed!";
lblmsg.ForeColor = System.Drawing.Color.Red;
Response.Redirect("index.aspx");
}
}
因此,我从上面获得了完全加密的密码,但是现在我无法使用在此输入的密码登录。 登录时如何取消密码的密码? 我认为我可以使用与加密相同的方法来取消哈希处理,但是盐化不会返回相同的值。 以下是验证页面上的代码
public string GenerateSHA256Hash(String input)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
System.Security.Cryptography.SHA256Managed sha256hashstring =
new System.Security.Cryptography.SHA256Managed();
byte[] hash = sha256hashstring.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public void Login_click(object sender, EventArgs r)
{
String hashedpassword = GenerateSHA256Hash(txtpassword.Text);
string MyConString = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
MySqlConnection con = new MySqlConnection(MyConString);
MySqlCommand cmd = new MySqlCommand("select * from authentication where agentlogin=@username and password=@word", con);
cmd.Parameters.AddWithValue("@username", txtusername.Text);
cmd.Parameters.AddWithValue("@word", hashedpassword);
MySqlDataAdapter sda = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
if (dt.Rows.Count > 0)
{
Session["id"] = txtusername.Text;
Response.Redirect("calendar.aspx");
Session.RemoveAll();
}
else
{
lblmsg.Text = "Credential doesn't match!";
lblmsg.ForeColor = System.Drawing.Color.Red;
}
}
在用户表Username
和Hash
and Salt
创建一列
用户注册
1)在注册表格中输入username
或password
。
2)使用以下方法为输入的密码创建哈希和盐。
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;
}
Rfc2898DeriveBytes类用于使用RFC2898规范生成哈希,该规范使用一种称为PBKDF2(基于密码的密钥派生功能#2)的方法,并且IETF(Internet工程任务组)目前建议将其用于新应用。
3)然后将此Hash
和Salt
以及用户记录存储在数据库中。
public void Submit1_click(object sender, EventArgs r)
{
//Your code here
HashSalt hashSalt = GenerateSaltedHash(64, password1.Text);
//Your code here
cmd.Parameters.AddWithValue("@hash", hashSalt.Hash);
cmd.Parameters.AddWithValue("@salt", hashSalt.Salt);
//You code here
}
用户登录
1)在登录表单中输入username
或password
。
2)在Login_click
按用户名从数据库获取用户。
3)将存储的Hash
和Salt
传递给以下功能。
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;
}
4)然后通过验证用户密码登录。
public void Login_click(object sender, EventArgs r)
{
//You code here
User user = GetUserByUsername(txtUsername.Text);
bool isPasswordMatched = VerifyPassword(txtpassword.Text, user.Hash, user.Salt);
if (isPasswordMatched)
{
//Login Successfull
}
else
{
//Login Failed
}
//Your code here
}
参考: 有效的密码哈希
您必须先将盐存储起来,然后再将其添加到密码中并对其进行哈希处理。
因此,当有人尝试登录时,您将密码与存储的盐连接起来,然后可以对其进行哈希处理并将其与base中的现有哈希进行比较。
因此,您的用户表至少应包含以下三列:用户名,哈希密码,盐
更长的解释:哈希函数是确定性的,但不可逆,因此,当用户首次创建密码时:
所以你有:hashedpassword = hashingfunction(password + salt)
当您尝试登录时:
盐旁边的哈希密码并不会降低安全性:盐的目的是防止使用RainbowTable
如果有人闯入您的数据库,由于大多数人会在许多不同的地方重复使用相同的密码和电子邮件,因此他可能会以用户的电子邮件和密码作为目标。
现在,由于哈希函数不可逆,攻击者唯一可以做的就是尝试猜测密码并使用以下命令创建字典:
guessed_password => hash(guessed_password)
例如:
pet345 => 23FD7890F0F3FA3AE468F37CB900402A1F1977CF926F3452CA519056E16985AB
lola78 => 876B42DC10A0822CC52B894DC7517C784A542B43FB033B4A93635ADA67946B2E
lola79 => A7DCAF5195463FA367CDEA6F23688C1280EC98F4AF2B08BC3469D2496537D48D
lola80 => 8D8E1CF212F5DDC3CA1D510900382DF945625A9AE1584CE0D539B2C4D73717CB
如果hash(guessed_password)在您的数据库中,则他知道此(这些)用户的密码为guessed_password。
他可以用数十亿的guessed_password生成词典,并且由于许多用户未使用真正强大的密码,因此他很可能能够在词典中找到大量用户哈希。 因此,如果他为“ lola80”和“ lola79”生成散列,并且这些是您的2个用户的密码,那么他知道。
现在,如果您在输入的每个密码中添加一个随机盐,则由于必须这样做,他必须为每个盐生成完整的字典:
guessed_password + salt = hash(guessed_password + salt)
对于用户A带有'09ç@ p $'盐,他必须生成完整的词典,其中每个单词都以'09ç@ p $'结尾
现在,如果他想猜测与盐'Yuè45gh'关联的用户B的密码,他必须生成另一个词典,其中每个单词都以'Yuè45gh'结尾
基本上,它会根据your_number_of_users个因素减慢猜测用户密码的过程。
我认为我可以使用与加密相同的方法来取消哈希处理,但是盐化不会返回相同的值。
您的意思是您又一次通过加盐机制发送了加盐密码,并且希望得到一个未隐藏的清晰密码? 这没有任何意义。
因此,您添加了密码,并将其保存在某处。 您现在要做的是,当用户输入密码时,您对这个新密码加盐并得到了加盐的密码。 然后对照旧版本检查这个新版本; 如果它们匹配,那是正确的密码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.