Flow of validating a user with hashed password? - c#

I was reading this article about hashing passwords when I came to this part:
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same
hash function.
Compare the hash of the given password with the hash from the
database. If they match, the password is correct. Otherwise, the
password is incorrect.
But I am a little confused with the flow this would follow, for example lets assume I have a database with a user table with id,name,password and email and in order to login to some app I need to input my email and password.
Following the the steps above, I first need to get the salt+hashed password of said user stored in the database.
Question:
Assuming I am using a simple stored procedure would the only way be to do it like this...
CREATE PROCEDURE [dbo].[sp_validate_user]
#us_email VARCHAR (MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT us_id,
us_name,
us_pass,
us_email
FROM Users
WHERE us_email = #us_email
END
Then following step two and three:
public static bool ValidatePassword(string inputPassword, string storedPassword)
{
// Extract the parameters from the hash
char[] delimiter = { ':' };
string[] split = storedPassword.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(inputPassword, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
My concern comes from the fact that if I am creating objects with the data pulled from the table, doesn't that make the information within vulnerable somehow?
Also does that mean that the only way to use this validation is pulling all the user's information based only on a username/email just to check in runtime if the input password and the hashed one match and then letting said user access the information?
I'm sorry if this sounds confusing but any insight would be great.

It looks like you may be thinking of it backwards. The salt is added to the cleartext password before passing to the hash function. Store the end result in the database.
Commonly, the salt is the username. Something unique to each user to thwart dictionary attacks. (A dictionary attack relies on the economy of scale by cracking one password and then looking for other instances of the same crypto-text. It used to work especially well on very large user databases like well known sites that have millions of users, but hopefully those sites use proper salting and key derivation nowadays).
So for username u, password p, assume SHA2 is hash function. Concatenate u + p to get a salted value, then hash it.
hashtext = SHA2(u + p) // in this case, + is concatenate
hashtext is what you store in the database.
For the login, user enters his username u2 and password p2:
tryhash = SHA2(u2 + p2)
Query database for a user record matching u2, with password hashtext of tryhash
Lets say you have an MVC action receiving loginViewModel which is populated with cleartext email or username as well as cleartext password, entered from the page:
var loginUser = new User(loginViewModel);
CalcHash(loginUser);
var realUser = users.Find(loginUser.username);
if(realUser.HashPassword == loginUser.HashPassword)
// success
While it is also possible to add the hashed password as a second argument to your Data Access method, ie. users.Find(username, hashPass), it is usually not done this way, because you need to access the user record even if the password fails, in order to increment password failure count and lockout the account.

The article covers ASP.NET (C#) Password Hashing Code but you seem to want to use a database?
You have three things to worry about; the unique key for the user (username), your chosen hashing algorithm and adding a salt to the password attempt (prevents rainbow table attacks).
To validate a password you should create a sql stored procedure that accepts the username and password attempt as parameters. This data is in plain text and has been entered into the web form, passed to the web server and will be passed into the database server via the stored procedure.
The stored procedure will do the following;
Lookup the data row for user based on matching the username parameter with the username field and
select the stored salt field
Append the salt from (1) to the password parameter and hash the result
Lookup the data row for the user based on matching the username parameter with the username field
and the hash result from (2) with the hashed password field.
If there is no row found the password hashes don't match and are wrong so return a suitable error code
If there is a row found return the useful user data i.e. First Name, Address
If the stored procedure handles all this then the web server never needs to know what the salt is or the hashing algorithm. At no point does the hash result or the salt get transmitted out of the database server.

I think you understood it correctly, this is the usual workflow:
Get the password-hash by username SELECT password_hash FROM user WHERE email=?.
Extract the salt from the password_hash, or get the salt from a separate field.
Calculate the hash of the entered password with the extracted salt and compare the hashes.
Validating the password cannot be done in a single query, because you first have to extract the salt. Appropriate hash functions like PBKDF2, BCrypt or SCrypt are often not supported by the database system, so you have to do the validation in your code. Additionally to the salt you also have to store other parameters like the cost factor and the algorithm (to be future-proof), so it is a good idea to store all these parameters in the same database field.
The salt should be a random string of at least 20 characters, so it is not safe to use the username as salt, or to derrive the salt from other information.

Related

How to get Decrypted password from Password Hash and Salt without Password passing to decrypt c#

I have list of user's password (password Salt and password Hash ) saved in DB table. The password is not saved anywhere.
var hmac = new HMACSHA512();
var newUser = new Users
{
UserName = userName.ToLower(),
CreatedDate = DateTime.UtcNow,
CreatedBy = User.Identity.Name,
PasswordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(pwd)),
PasswordSalt = hmac.Key
};
_dbContext.Users.Add(newUser);
_dbContext.SaveChanges();
I need to display the password for each of the user only when needed. Say when we click on particular user with show password button by passing user ID.
As #Daevin said in the comment on your post, this is not possible with your current setup. Hashing is not something you can undo (if the hash is a proper cryptographic hash that is unbroken).
https://www.techopedia.com/definition/14316/hashing-cybersecurity explains it well:
A good hash function for security purposes must be a unidirectional
process that uses a one-way hashing algorithm. Otherwise, hackers
could easily reverse engineer the hash to convert it back to the
original data, defeating the purpose of the encryption in the first
place.
So no, you can't display the user's password unless you store it unhashed somewhere.

Hashing user password - Identity Server

I'm currently working with Identity Server 4, at present when the user logs in I need to hash their provided password and then compare with the password stored in the database (also hashed)
After some searching, I was linked to the PasswordHasher within Identity Server to handle this:
var _hasher = new PasswordHasher<User>();
var hashpassword = _hasher.HashPassword(user, context.Password);
User is my custom class that inherits from IdentityUser, however, when checking the hashed password against the one in the database the hash is completely different, I have double checked the password and I can confirm it's correct.
Can anyone suggest why I maybe seeing a different hash compared to the one in the database?
Each time you hash a password with PasswordHasher<T>.HashPassword you will get a total different result because of the salt.
To verify such hashed salted passwords use the given method IPasswordHasher<T>.VerifyPassword.

How to convert hash password in text string in SQL Server 2008

How to convert a hashed password in text string in SQL Server 2008?
I want to know the password of user which is stored in SQL Server as hash password. How to convert hashed password to normal text?
thats generally not how it works. Password checks are done on the following principal
Password -> encryption -> saved
then when user enters a password you reencrypt it, and compare the new encrypted to the old, if its the same then you got the right password you can enter. This stops people "finding out" other peoples passwords and keeps systems secure. Which is why often brute force password cracking is needed to get into things.
If you can unencrypt it - then there was no point storing it encrypted in the first place.
you cant send a string and decrypt it, because DecryptByPassPhrase function expects a varbinary parameter.
here is a small example
declare #encrypt varbinary(200)
select #encrypt = EncryptByPassPhrase('key', 'abc' )
select #encrypt
select convert(varchar(100),DecryptByPassPhrase('key', #encrypt ))

Password salting and hashing asp.net?

I have spent the past hour reading up on salting and still don't understand how it is achieved. Forgive me if im wrong, but the way I am thinking of salting is, storing an ArrayList of random strings for example 100 strings. Now when a user registers, a method gets a random string from the array list and retrieves the index of the string within the array to insert into my DB, it then applies this random string to the password the user entered and then hashes the whole string and stores into the DB.
Now when the user logs in it will retrieve the index for the ArrayList of random strings, then applies it to the entered password to then hash the whole string and compare the 2 passwords.
Is this a good way of salting? Is this classed as salting?
It's better to have unique salts for each user/password hash instead of reusing a limited set of 100 salts.
The reason is because of the way hackers attempt to compromise a database full of passwords once they get a hold of it, in particular using rainbow tables to find known values shared between multiple users.
For example (pseudo-code):
This is bad because once a hacker cracks the first password hash, both users are compromised.
//BAD WAY
var nonUniqueSalt = "some salt value";
var userPass1 = "P#ssword!";
var userPass2 = "P#ssword!";
//Bad! This will be true!
var isSame = (DoHash(userPass1 + nonUniqueSalt) == DoHash(userPass2 + nonUniqueSalt));
This way is better, because the salts are different even if the passwords are the same, so the hacker can't use rainbow tables and is forced to compromise each user's password individually.
//BETTER WAY
var uniqueSalt1 = "unique salt 1";
var userPass1 = "P#ssword!";
var uniqueSalt2 = "unique salt 2";
var userPass2 = "P#ssword!";
//Better! This will be false.
var isSame = (DoHash(userPass1 + uniqueSalt1) == DoHash(userPass2 + uniqueSalt2));
As far as the salting "algorithm" some users mentioned in comments, you don't REALLY need to worry about it too much aside from trying to make the salt unique to each user (because of the reasons described above).
In practice, whatever salt you use will need to be stored in the DB alongside the password hash, so once a hacker has the database, he'll have the value you used for a salt no matter how you go about deriving it.
As such, using a salt based on something like Guid.NewGuid().ToString() is sufficient for simply having unique values for each login.

How to store salted hashed password in the database

I'm trying to figure out a way to store a salted hashed password to my database. It's my first time doing so, so I'm kind of unsure of how the process should go about.
My ASP.NET C# Web Application first requires a user to register for an account. I have a data layer, business layer to call the method in the data layer, and a presentation layer to display the form controls. At the moment I'm using plain text to store the password in the database. Let's call that method createAccount() in the data layer. Username, password and other attributes are passed into the createAccount() method to invoke the SQL Query to create an Account record. Username and password is specified by the user in the registration page. I found a web site that provided me a method to generate my password with hash as follow:
public static string GenerateHashWithSalt(string password, string salt)
{
// merge password and salt together
string sHashWithSalt = password + salt;
// convert this merged value to a byte array
byte[] saltedHashBytes = Encoding.UTF8.GetBytes(sHashWithSalt);
// use hash algorithm to compute the hash
System.Security.Cryptography.HashAlgorithm algorithm = new System.Security.Cryptography.SHA256Managed();
// convert merged bytes to a hash as byte array
byte[] hash = algorithm.ComputeHash(saltedHashBytes);
// return the has as a base 64 encoded string
return Convert.ToBase64String(hash);
}
Where should I put this, in the registration page, in the code-behind (.cs) page, or in the data layer? And then, how would you all suggest I placed this hashed password in my database along with my other attributes? Should I directly store it as hashed, or store it in plaintext first, then update it to the hashed value. Thanks!
I would recommend using an existing implementation, instead of rolling your own here.
The asp.net membership database is perfect for this, and uses salting and hashing out of the box.

Categories

Resources