I am following the MSDN article located here: http://msdn.microsoft.com/en-us/library/aa302398.aspx
My confusion is over the function:
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "SHA1");
hashedPwd = String.Concat(hashedPwd, salt);
return hashedPwd;
}
My understanding is that:
1. concat the salt and the plain text pwd
2. created a hashed pass using sha1
3. Concat the salt once again with the hashed pwd which originally had the salt in it???
What is the reasoning behind step 3?
I found a function identical to the MSDN one else where and it omits the last concat.
I just do not understand why the MSDN version has the last concat operation in there.
It's storing the salt with the hashed password so that you can simply extract the whole thing from the configuration file (or wherever you store it), grab the salt off the end, hash the incoming password with it, and compare the results to the hashed password from the configuration. If you don't store the salt with the hashed password in the configuration, you'd have to store it somewhere else and extract it from there to hash incoming passwords when you perform the test. Since SHA1 is a fixed 160 bits (20bytes), it's easy to grab the salt by simply skipping the first 20 characters in the hashed password in the configuration.
Related
I'm trying to use PBKDF2 in C# to create a password, then I'm trying to retrieve that password.
var masterPwd = "masterPassword";
var service = "www.google.com";
byte[] salt = CreateSalt(16);
var encodedPwd = CreateMasterPassword(masterPwd, salt);
var decoded = CreateMasterPassword(encodedPwd, salt);
With the following functions defined:
public static byte[] CreateSalt(int size)
{
var salt = new byte[size];
using (var random = new RNGCryptoServiceProvider())
{
random.GetNonZeroBytes(salt);
}
return salt;
}
public static string CreateMasterPassword(string password, byte[] salt)
{
string PassHash = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return PassHash;
}
In this case, shouldn't decoded be the same as masterPwd?
I think you have a bit of a misunderstanding about what PBKDF2 does. It is not an encryption function where you can ever recover the plaintext data (let's put brute force aside as it is not an 'intended use'). Rather, it is a "slow" hashing mechanism, often described as "one way".
PBKDF2 is a key derivation function, but is also used for storing passwords. Here's a typical flow for PBKDF2 when used for password storage.
A user creates an account with a website with a password. The site generates a random salt, then applies PBKD2 to the password with the salt, and stores the result and the salt. The salt is stored in plain text.
When the user needs to log in again, the site asks for the username and password. It looks up the salt for that user, then it re-applied PBKDF2 to the password the user entered.
It compares the stored hash with the hash of what the user entered. If the hashes are equal, the site knows they typed the password correctly.
This approach means the site does not store the password in a way that it can possibly know. This allows the site to disavow knowledge of the password.
If that is what you want to do, then that is how you should use it.
If you do need a way to have a "two way" algorithm, then this goes from hashing to encryption. A symmetric algorithm would be used in this place, with all of the troublesome issues of key and IV management. You would most likely want to take a look at a high abstraction that is built on top of symmetric ciphers like libsodium.
libsodium is a nice abstraction built on top of primitives that takes the guess work out of how to use them. If offers simple APIs such as "encrypt this thing with this password" and it correctly derives an encryption key from the password, performs some form of authentication on the encryption, and is regarded well by information security experts.
I have a software which stores passwords using an unknown hashing method. for example if the 123456789 set as the password, it would be stored in the database by two fields which are 'salt' (seems that the salt is generated randomly) and 'hashed'. And I need to know how the software reaches to that hashed string.
as an example for the origial string: 123456789
the salt is: ifWIg1IB
hashed is: QkKtpxSqd+kIH2EuMkNdWV44B2g=
I need to know it because of making an integrated login system via this hashed password. I think it is very important to avoid make lots of username and password for each person in an office.
with the best respects
Your 'hashed' output is a base-64 encoded string. Decoding the string results in a 20-byte digest. SHA-1 produces 20-byte hashes so it looks like the generation process is:
base64(sha1(combine(salt, password)))
there are two obvious approaches to combining the salt and password plaintext - append or prepend the salt to the password. If you prepend the salt you end up with the following algorithm to generate the encoded digest:
public static string GenPasswordString(string password, string salt)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(salt + password);
using (var alg = new System.Security.Cryptography.SHA1Managed())
{
byte[] hashBytes = alg.ComputeHash(bytes);
return Convert.ToBase64String(hashBytes);
}
}
and
GenPasswordString("123456789", "ifWIg1IB") == "QkKtpxSqd+kIH2EuMkNdWV44B2g="
I have code to generate SHA512 from string.
public static string GetCrypt(string text)
{
string hash = "";
SHA512 alg = SHA512.Create();
byte[] result = alg.ComputeHash(Encoding.UTF8.GetBytes(text));
hash = Encoding.UTF8.GetString(result);
return hash;
}
Now I must convert hash back to string. Any ideas how can it be done? Thank you.
Hashes are 1-way. You can't get it back (easily). you might want actual encryption.
Yes. Hashes are one-way. Please use symmetric encryption classes like RijndaelManaged.
Here is a RijndaelSimple class that I am using:
http://www.obviex.com/samples/encryption.asp
The cached version of the same link is here:
http://webcache.googleusercontent.com/search?q=cache:WyVau-XgIzkJ:www.obviex.com/samples/encryption.asp&hl=en&prmd=imvns&strip=1
You cant convert a hash back to string from which you computed the hash.
If you want it then you would have to compare the hash with each of the target strings hash.
If one of them matches with the hash,then that hash comes from the target string.
Its use: If you want to store passwords in database,you can store its hashes instead of passwords.So even if a hacker gets access to your database,he cant get the password cuz it is hashed.The only way to know the string through which we created the hash is to match it with the desired string!
I want to store login and password in sqlite database. This database in encrypted using SQLCipher library. But password to encrypt database is separate issue. This password is stored in code of application. Login and password are provided by user to login to application. In C# there is the SHA256 class. If I use this class if it is enough ? Or rather I should use hash and salt or other methods ?
Thanks
To store a user password in a database for login matters, you should use a hash function with a salt.
SHA 256 is one of them, but there are better ones existing. I recommend you using the PBKDF2 derivative function. You can implement your own PBKDF2 hashing method using the Rfc2898DeriveBytes class provided in the .NET framework.
Here is a quick how-to-do-it:
int saltSize = 256; // Number of bytes of the salt
int iterations = 1000; // Number of times we iterate the function
// The more we iterate, the more it is gonna take time.
// The advantage of a great iterations number is to
// make brutforce attack more painful.
int hashSize = 20; // Number of bytes of the hash (the output)
var deriveBytes = new Rfc2898DeriveBytes("mypassword", saltSize, iterations);
byte[] salt = deriveBytes.Salt;
byte[] hash = deriveBytes.GetBytes(hashSize);
You just have now to store the salt and the hash in your database. Use Convert.FromBase64String and Convert.ToBase64String to get a string from a byte[] and vice-versa.
Another alternative is to use bcrypt. See this interesting article.
wondering if anyone has some quick links to code snippets to generate a random salt (that's not easy too easy to guess) and then hashing some plain text password with the generated hash.
Suggestions or links, please?
.NET code, please.
The salt can be know. Why would you want the salt "not easy to guess"? It just has to be unique so that if two people share the same password the salt applied to the password ensures that they don't end up with the same hash value and to reduce the effectiveness of Rainbow attacks (where a reverse Hash dictionary is used to see the possible plain text value(s) that can produce a particular hash value)
From a code snippet on MSDN:
private static string CreateSalt(int size)
{
// Generate a cryptographic random number using the cryptographic
// service provider
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number
return Convert.ToBase64String(buff);
}
You can then append or prepend this on to the plain text password, then hash it.