Validate a salted hash - c#

I am new to C# and this is my first question here so I apologize in advance for any faux pas.
Context:
When a user registers I call the CreateSaltedHash() method and pass it the user inputted password from the text field. This method salts and hashes the password before storing it in the Password column of my User table.
Question:
How should I validate the password when a user tries to log in?
If I call the CreateSaltedHash() method again it will not match because of the random salt.
Should I be storing the salts in a separate column? Should I be using a delimiter when generating the salted hash? What is the most secure way of validating the input password against the salted and hashed password?
Code:
This is what I have so far.
public class PasswordHash
{
public const int SALT_BYTES = 32;
/*
* Method to create a salted hash
*/
public static byte[] CreateSaltedHash(string password)
{
RNGCryptoServiceProvider randromNumberGenerator = new RNGCryptoServiceProvider();
byte[] salt = new byte[SALT_BYTES];
randromNumberGenerator.GetBytes(salt);
HashAlgorithm hashAlgorithm = new SHA256Managed();
byte[] passwordByteArray = Encoding.UTF8.GetBytes(password);
byte[] passwordAndSalt = new byte[passwordByteArray.Length + SALT_BYTES];
for (int i = 0; i < passwordByteArray.Length; i++)
{
passwordAndSalt[i] = passwordByteArray[i];
}
for (int i = 0; i < salt.Length; i++)
{
passwordAndSalt[passwordByteArray.Length + i] = salt[i];
}
return hashAlgorithm.ComputeHash(passwordAndSalt);
}
public static bool OkPassword(string password)
{
//This is where I want to validate the password before logging in.
}
}
Calling the method in the Register class.
User user= new User();
user.password = PasswordHash.CreateSaltedHash(TextBoxUserPassword.Text);

You could use Bcrypt.Net; it has a lot of recommendations for being really secure, plus it is very easy to use. As I understand it, when you create the password it automatically generates a unique salt for you, which is then stored in the hashed password string; so you do not store the salt separately, but in the same field as the hashed password. The point is each password has it own salt, which makes it much more difficult (time consuming) for a hacker to crack multiple passwords. The algorithm Bcrypt uses is also CPU intensive, so it requires a lot of computational power (=money) to crack.
Jeff Atwood (stackoverflow moderator) recommends Bcrypt.

When you first generate the hash, you need to store both the salt and the final hash - then re-use that same salt for future comparisons.
So you'd change your CreateSaltedHash method to take a password and a salt, and write a new CreateSalt method to generate the salt when a password is created/changed which is stored alongside the final hash.

I Suggest you to use SaltedHash of ServiceStack which you can install it from your Nuget.
Simply Enter Install-Package ServiceStack in your Nuget Console, then you'll be able to use the following imports in your code.
using ServiceStack.ServiceInterface.Auth;
And then you would generate your salt and hash so much easier and absolutely faster than before.
Just enter the following codes:
class Security
{
...
public void generate(string Password)
{
string hash, salt;
new SaltedHash().GetHashAndSaltString(Password,out hash,out salt);
//Store the hash and salt
}
...
}
And yes, You must store the hash and salt to be able to run your OkPassword Method.
public bool OkPassword(string Password)
{
var hash = //getStoredHash
var salt = //getStoredSalt
bool verify = new SaltedHash().VerifyHashString(Password, hash , salt);
return verify ;
}

You will have to store the salt along with the hash.
Refer to this article to get some background information:
http://www.h-online.com/security/features/Storing-passwords-in-uncrackable-form-1255576.html

As the other answers states; yes you should store the salt or derive it from for example the username.
You should also use Rfc2898DeriveBytes to make it more secure.
Here is a good article on that topic:
Password salt and hashing in C#

Should I be storing the salts in a separate column?
Yes.
Should I be using a delimiter when generating the salted hash?
Not necessary, but it also won't hurt as long as you include the same delimiter when validating.
What is the most secure way of validating the input password against the salted and hashed password?
SHA512, SHA-2 or -3 would be more secure than SHA256, but do you need that much more security?

You can either store the salt, or use the same salt every time. I recommend storing the salt as it is more secure than using the same salt across all users.
Most of my tables have a column with the date time of when the row was created. I use the Ticks property of the DateTime struct of this value to salt the hash, but you can use anything you like, as long as you use the same salt for the user each time. One thing to watch out for is if you use this method, and you are using the SQL type DateTime (and not DateTime2), then there is a precision issue. If you create the DateTime in code, you will need to truncate it (I believe to hundredths of a second).

And for the longer answer -
The has should be random with every password created. This will make it unique in itself. Due to this 'randomness', you will almost never be able to programatically find the hash associated to the file.
The way you encrypted the password (without the hash) should be the same, so using a reverse of this method will be sufficient every time.
PS: (A more secure way o validating) You can either reverse the encrypted password to its original [Hard], or encrypt the validating password with the hash, and make sure that encrypted password matches that stored in the DB [Preferred].
So, you will need to store the encrypted password, as well as the hash associated to it, in the database.
This will be the way to gather all the information needed to validate the password.

Because you are generating a random salt you would need to store the salt on the database. The problem with that is that if your database becomes compromised, the attacker will have the salt and the hashed password, so they can more easily determine the real password. Ideally you should have a static salt in your code so that if your database is compromised they still don't have the salt and if your code is compromised, they don't have the database just yet.
Another solution could be to use pepper. Pepper is similar to salt but you don't store it the database with the salt and hashed password. It would be stored in the code. This way you have a random salt that is generated and a constant which is stored separate. To make the pepper more random, you could create a sub-string of a larger string that you are using for a pepper which is offset based on some variable, such as the user id. This again is an internal thing that an attack would not know of if they managed to get your data.

You should save the digest and salt. The iterations and digestLength values can be constants in your application.
byte[] getNewSalt(Int32 size)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] salt = new byte[size];
rng.GetBytes(salt);
return salt;
}
byte[] getPasswordDigest(byte[] value, byte[] salt, Int32 iterations, Int32 digestLength)
{
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(value, salt, iterations);
return deriveBytes.GetBytes(digestLength);
}
Recent articles suggest that to further secure passwords, you can split up the password into parts, hash the individual parts, then store them in separate tables in the DB.

Related

How do I decrypt text in C#?

I am using the function below to encrypt password and store it into my database. Now I need to decrypt it back and compare it with the login user. Please help me.
public static string encrypt_string_using_MD5(string s)
{
byte[] byte_array = System.Text.Encoding.Default.GetBytes(s);
System.Security.Cryptography.HashAlgorithm alg =
System.Security.Cryptography.HashAlgorithm.Create("MD5");
byte[] byte_array2 = alg.ComputeHash(byte_array);
System.Text.StringBuilder sb
= new System.Text.StringBuilder(byte_array2.Length);
foreach(byte b in byte_array2)
{
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}
You cannot Decrypt Hash. Hash is like signature of your original content.
What you can do is to store this Hash in database. Whenever user enters password. you compute the hash of value user entered and compare it with stored hash and if it matches then authentication is succesfull
You can not decrypt it, because it is not encrypted.
You create a hash of the text, and not an encrypted version.
A hash is like a fingerprint of data. This can be used for example to safely store passwords in a database. When someone wants to login again, you again calculate the hash and check the new hash against the one the in database to see if they match. If they do, then the password is the same and the user can login.
A good explanation can be found at http://www.securityinnovationeurope.com/blog/whats-the-difference-between-hashing-and-encrypting
Hence you use MD5, it's irreversible. Why are you sending passwords as plain text anyway...?
Either way, when comparing values (one plain, one hashed) hash the plain one and compare that.

Decrypt method from encryption function

I have a method that is used to encrypt the password and store it to database as below :
public static string Md5Encrypted(string password)
{
byte[] pass = Encoding.UTF8.GetBytes(password);
MD5 md5 = new MD5CryptoServiceProvider();
string strPassword = Encoding.UTF8.GetString(md5.ComputeHash(pass));
return strPassword;
}
Now I want the method that decrypt the password that I get from database which was encrypted by above method while storing it. I don't know how to make it. Anybody can help me please?
MD5 is a hash function (not an encryption) and is irreversible. That is, you can't compute the original value from a given hash.
Update: I recommend this article that describes how to store password hashes securely. There's a C# implementation as well.
http://crackstation.net/hashing-security.htm
MD5 hash function is irreversible and cannot be decrypted,If you want to check the Username and password during login then do this..
1.While registering a new user, Hash the password and store it in database.
2.During login,Hash the password entered by the user
3.Now,Compare the password entered(Hashed ) with password stored in database(Hashed)
4.If both of them are same then allow user to login else display an error
You can't decrypt this, because hashing is a one-way function - you can't take a hashed value and turn it back into the original value.
Since it looks like you're dealing with passwords and I therefore assume this is some kind of logon mechanism, this is (probably) OK. What you need to do is hash the password (as you've done), and store the hashed value when your user registers on your website. When the user returns to your site, you take the password they enter, hash it (using the same method), and compare the hashed value with the value you stored. If the two hashes match, the correct password was entered.
Salts
There's a problem with hashes, in that the same input value always produces the same hashed value (otherwise the above mechanism for logon wouldn't work). Unfortunately this means that generating hash values for, say, a dictionary of common passwords is a trivial exercise. If your database is compromised, an attacker can then compare all the hashed passwords you've got stored against his previously computed values, and if he gets a match then Bazinga! he's got into your data.
To defend against this, what you can do when you do your initial hashing is at the same time generate an extra bit of random data that gets mixed in with the password as it's being hashed. This is called a salt (or less commonly a nonce). Rather than reproducing some code to do this, at this point I'm going to direct you to blowdart's book Beginning ASP.NET Security (Amazon UK | Amazon US), which has discussion of all this stuff - hashing, salting and 'proper' encryption.

How to validate a user in asp.net web site using the existing encrypted password stored in the SQL Database?

Hi i am using the MD5 encyrption in my asp.net website where it stores the passwords to the database using the MD5 encryption.so when i want to login using the credentials entered during the registration of the user i am having trouble comparing the existing password from the database to the current one which i entered to login.As the stored password is in the ecrypted form i am confused how to compare the encrypted format to the text format ?
I am using the Sqlserver as my database.
In addition to what #Jason said... I like salting the password.
public static string CreateSalt(int byteSize)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[byteSize];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
public static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1");
return hashedPwd;
}
when the user is intially created, here is the process
Create the salt => CreateSalt(16)
Create the hash with the password and salt => CreatePasswordHash(passwordEntered, salt)
Store the hashed password and salt
next time the user logs in, validate the stored credentials against what they have entered into the login form
=> string enteredPasswordHash = CreatePasswordHash(enteredPassword, saltFromDatabase)
the compare against what is in the database
=> if(passwordHashInDatabase != enteredPasswordHash) => wrong login credentials
Hope this helps someone...
MD5 is a one way hash, so the password in the database cannot be converted back to plain text. Instead you have to convert the plain text password (the one entered in the login form) to cypher text using the MD5 hash algorithm.
To compare the MD5 hashes you would need to query the database based on the User Name enter in the login and return the known MD5 hash and the salt (if there is one). Then hash the given password with the known salt. You can then compare the two hashes for a match.
If you are definitely storing the password in an encrypted state, then you only need to encrypt their plaintext password (using the same key) and compare it to the database value. Apples to apples. When encrypted using the same key and algorithm, it will always encrypt and decrypt to the same value.
If this doesn't appear to be working correctly, I would guess that you are not using the same key that you used when you first stored the value in the database. Double-check and make sure that the key you encrypt with is exactly the same as the key you decrypt with. Typically, many of us will use a machine or user-level certificate as a key, to ensure that the value isn't tampered with or changed.
If (instead) you are using MD5 to hash the password, then it's not actually encrypted. Hashing totally munges the plaintext value and you will never get it back. It's the safest and smartest way to store passwords. You merely hash the plaintext into an encoded value and save it to the database -- then, you compare against that hashed value any time the user logs in.
I'm hoping you are hashing and not encrypting. It's definitely a best practice when it comes to password storage. It's very easy to implement and will save you headaches if you're ever audited.
Good luck!

How can I encrypt userid and password from user?

I want to save userid and password in a MySql database for my WinForms project. One of my friends told me that this is not secure; I should encrypt and save that. I don't know about encryption.
How can I do this?
Usually passwords are not stored in database at all. Instead hash of the password is stored. You can take a look at SHA156 class for example.
There are plenty articles in the web on how to hash passwords.
For example Storing Passwords - done right!
Note that your friend is telling you to encrypt it, which is different from storing a hash (computed using a cryptographic hash function) in the table.
If you encrypt and store it, you will be able to retrieve the password if you have the key.
If you store a secure hash of a password, you can tell if a string is the same as the password or not by hashing the string and comparing the hash in the table.
I did a search and found this answer from another SO question which explains in greater detail why you should be using a hash (of a secure variety) as opposed to encrypting the password.
Last but not least, whether encrypting or secure hashing, be sure to use a publicly tested libraries and not to "roll your own".
When using encypion one needs to choose an algorithum (method of encryption) for the data. When storing user credentials one generally creates and stores a hash of the information rather than encrypting it. The advantage of using a hash over encryption is that a hash is non-reversible, so the original data can not be recovered.
The process for creating a hash is:
Create a salt value (explained below)
Append the salt value to the password
Hash this string
Store the salt value and the hash value in the database
Then when you want to validate the credentials later:
Take the password value entered by the user and append the salt to it
Hash the string from step 1
Compare it with the password stored in the database. If the stored hash and the hash from step 2 match, the user has entered the correct password, otherwise the password is incorrect
Hashes and Salts
A salt value is a value unique to each user that gets appended to sensitive values such as user names and passwords before they are stored. The reason salts are used with hashes is to make it more difficult to generate lists of hashed values used in brute force attacks against the database.
Code Samples
Generating a Salt & Hash
private void EncryptPassword(string userPassword)
{
//Performs hashing using SHA256 algorithum
SHA256Managed hash = new SHA256Managed();
RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
byte[] saltBytes = new byte[32]; // 32 bytes = 256-bit salt.
//Fill saltBytes with cryptographically strong random values.
random.GetBytes(saltBytes);
//Get a byte representation of the password because the hash function
//works with byte arrays.
byte[] passwordBytes = Encoding.UTF8.GetBytes(userPassword);
byte[] hashInput = new byte[passwordBytes.Length + saltBytes.Length];
//Append the contents of the passwordBytes and hashBytes arrays to create
//the input to the hash function (value to be hashed)
passwordBytes.CopyTo(hashInput, 0);
saltBytes.CopyTo(hashInput, passwordBytes.Length);
//Compute (generate) a hashed representation of the input value.
byte[] hashValue = hash.ComputeHash(hashInput);
//Hashes are often stored as strings in databases.
//Hashes should be stored using Base64 encoding.
string hashString = Convert.ToBase64String(hashValue);
string saltString = Convert.ToBase64String(saltBytes);
//store hashString and saltString in database.
}
Authenticating a User
private bool AuthenticateUser(string userName, string password)
{
SHA256 hash = new SHA256Managed();
//Convert hash and salts from Base64/
byte[] storedHash = Convert.FromBase64String("Hash Value from the database");
byte[] storedSalt = Convert.FromBase64String("Salt from Database");
//Append salt to user password and hash the result
byte[] attemptedPasswordBytes = Encoding.UTF8.GetBytes(password);
byte[] hashInput = new byte[attemptedPasswordBytes.Length + storedSalt.Length];
attemptedPasswordBytes.CopyTo(hashInput, 0);
storedSalt.CopyTo(hashInput, attemptedPasswordBytes.Length);
byte[] attemptedHash = hash.ComputeHash(hashInput);
//Check whether the password entered by the user matches the stored hash.
return attemptedHash == storedHash;
}
well a very simple solution is to use varbinary datatype which will store password in binary format and unreadable for other ..
If you want more security then you need to use encrytion provided my sql server itself like 128bit encryption for that u need to create asyymetric key then encrypt it with that
You could encrypt the username and password using fronthand that is C# and store that value in the database. On retrieval you have to decrypt it for matching. Have a look at this link.

How to salt and hash a password value using c#?

Hai guys,
I came to know that storing hash value of a password is a safe one from Preferred Method of Storing Passwords In Database...
How to salt and hash a password value using c#?
How to compare both the values stored in DB and the one given by the user?
The most popular way to do this is using a hashing algorithm. There's an excellent blog post here about how to use the MD5 algorithm to hash a string, but there are many other examples in the System.Cryptography namespace.
As for #2, the general step-by-step guide to how this would work would be the following:
On registration:
Hash a user's password using your specified algorithm and store it in the database
Salt this hash (optional, but preferred)
On login / user & password check:
Look up in the database for the username
If it exists, retrieve the hashed password
Hash and salt the entered password and compare it to the retrieved password
It's all relatively long-winded, but it's very secure.
There's another extremely in-depth guide on hashing and salting here.
Simple hash:
public string GetSHA256Hash(string s)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("An empty string value cannot be hashed.");
}
Byte[] data = System.Text.Encoding.UTF8.GetBytes(s);
Byte[] hash = new SHA256CryptoServiceProvider().ComputeHash(data);
return Convert.ToBase64String(hash);
}
Strictly speaking, you should salt the password then hash it, to avoid a dictionary attack. You can use any of the implementations of the HashAlgorithm abstract class in the System.Cryptography namespace to calculate the hash - current best choice would probably be one of the SHA-2 algorithms.
You store the hash not the password, and compare the hash values to authenticate the user.
Like the others have said, there are many options.
Here is some sample code (using MD5 instead of SHA) from Microsoft that might help get you get started
using System;
using System.Security.Cryptography;
using System.Text;
string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";
//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
//Compute hash based on source data.
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
For hashing you have several supported algorithms in System.Security.Cryptography, for your usecase you probably want to choose an SHA based hash or something similar.
Regarding the comparison: You don't compare the DB value and the one the user gave to you. You use the same encryption/hashing function that you used to store the password in the DB in the first place, this time with the user input. If the result is equal to the hash in the DB the password was (probably) correct.
The intention is that no one that has access to the DB can retrieve the passwords in clear text and not even your program needs to know about it (only the part that accepts the user input will have it for a short time).
Links (maybe even duplicates):
Secure Password Hashing
https://stackoverflow.com/questions/1841595/secure-password-hashing
System.Security.Cryptography.MD5

Categories