I used the below method to salt and hash the passwords
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");
}
}
So I get the fully encrypted password from the above, but now I can't login using the passwords that was entered in there. How can I unsalt the password when logging in? I figured I can just use the same method used to encrypt to unhash it but the salting doesn't return the same values. The below is the code on validation page
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;
}
}
Create an column in your user table Username
and Hash
and Salt
User Register
1) Take input username
or password
from user in your registration form.
2) Create Hash and Salt for input password with below method.
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 class is used to generate the hash using the RFC2898 specification, which uses a method known as PBKDF2 (Password Based Key Derivation Function #2) and is currently recommend by the IETF (Internet Engineering Task Force) for new applications.
3) Then stored this Hash
and Salt
with user record in database.
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
}
User Login
1) Take input username
or password
from user in your login form.
2) In Login_click
get user by username from database.
3) Pass stored Hash
and Salt
to below function.
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) Then login your user by verifying his/her password.
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
}
Reference: Effective Password Hashing
You have to store the salt before adding it to the password and hashing it.
So when someome tries to login you concatenate the password with the stored salt and then you can hash it and compare it to the existing hash in base.
So your user table should have at least these 3 columns : username, hashedpassword, salt
longer explanation : The hashing function is deterministic but not reversable so when the user create his password for the first time :
so you have : hashedpassword = hashingfunction(password+salt)
When you try to login :
Having the salt next to the hashed password doesnt make it less secure : the goal of the salt is to prevent the use of rainbowtable
If someone breaks into your database he will probably aim for the email+password of your users due to the fact most people reuse the same password and email in a lot of different places.
Now since the hash function is not reversable, the only thing an attacker can do is trying to guess the password and creating a dictionnary with :
guessed_password => hash(guessed_password)
ex :
pet345 => 23FD7890F0F3FA3AE468F37CB900402A1F1977CF926F3452CA519056E16985AB
lola78 => 876B42DC10A0822CC52B894DC7517C784A542B43FB033B4A93635ADA67946B2E
lola79 => A7DCAF5195463FA367CDEA6F23688C1280EC98F4AF2B08BC3469D2496537D48D
lola80 => 8D8E1CF212F5DDC3CA1D510900382DF945625A9AE1584CE0D539B2C4D73717CB
if hash(guessed_password) is in your database, he knows the password for this (these) user is guessed_password.
He can generate a dictionnary with billions of guessed_passwords and since a lot of users do not use really strong password, it's very likely that he will be able to find a good number of your users hash in his dictionnary. So if he generates hashes for 'lola80' and 'lola79' and these are the passwords of 2 of your users he know knows it.
Now if you add a random salt to every password entered, for each salt he has to generate a complete dictionary since he has to do :
guessed_password + salt = hash(guessed_password + salt)
For user A with salt '09ç@p$' he has to generate a full dictionnary where every word ends by '09ç@p$'
Now if he wants to guess the password of user B associated with salt 'Yuè45gh' he has to generate another dictionnary where every word ends by 'Yuè45gh'
Basically it slows down the process of guessing your users passwords by a your_number_of_users factor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With