Unicode password hash

I am writing a salt / hash password for my .NET application, basically following the guidance of this article: http://www.aspheute.com/english/20040105.asp

Basically, the salt hash calculation code is as follows:

public string ComputeSaltedHash(string password, byte[] salt) { // Get password ASCII text as bytes: byte[] passwordBytes = System.Text.Encoding.ASCII.GetBytes(password); // Append the two arrays byte[] toHash = new byte[passwordBytes.Length + salt.Length]; Array.Copy(passwordBytes, 0, toHash, 0, passwordBytes.Length); Array.Copy(salt, 0, toHash, passwordBytes.Length, salt.Length); byte[] computedHash = SHA1.Create().ComputeHash(toHash); // Return as an ASCII string return System.Text.Encoding.ASCII.GetString(computedHash); } 

However, I want to allow users to use Unicode characters in their password if you want. (This seems like a good idea, can anyone think of a reason?)

However, I don’t know the subtleties of how Unicode works, and I worry if I just changed both links from System.Text.Encoding.ASCII to System.Text.Encoding.Unicode , the hashing algorithm might produce some byte combinations that aren't form valid Unicode characters and a GetString call will fail.

Is this a valid problem, or will it be normal?

+6
passwords unicode hash
source share
3 answers

You should not use regular encoding to convert from arbitrary binary data back to string. This is not encoded text - it is just a sequence of bytes. Do not try to interpret it as if it were β€œnormal” text. Regardless of whether the original password contains any characters other than ASCII, this is not relevant to your current code. (I would consider a related article with a high dose of suspicion simply on this basis.)

I would suggest:

  • Use Encoding.UTF8 to get bytes from the password. This will allow the password to contain any Unicode character. Encoding.Unicode will be fine too.
  • Use Convert.ToBase64String to convert from the computed hash back to text. Base64 is specifically designed to represent opaque binary data in text in an ASCII character set.
+12
source share

This is enough to change the first link to Unicode or UTF-8 . However, you can normalize the input to account for different ways of entering accents, etc.

+2
source share

I like Jon's solution better, but another option is to just save the hexadecimal hexadecimal text as a string. Replace the last line as follows:

 return BitConverter.ToString(computedHash) 

One thing you can consider is password strength.
SHA1 is very fast, sometimes too fast. The system will be able to calculate a couple of million hashes per second. Speed ​​allows an attacker to try a standard dictionary dictionary attack (including capitalization options) and numerical extensions. SHA1 speed allows you to expand the space of dictionaries in a reasonable time, breaking most user passwords.

The method of password amplification is a hash code several times, which increases the requirements for the hash processor. Take the output of the SHA1 hash and pass it as input for the second round. Do this at least 1000 times. This slows down the calculation of the hash for both you and the attacker. For your users, this delays access after a trivial amount of time; the procedure will return in 0.01 seconds instead of 0.0001 seconds. However, to a brute force attack, you increased the execution time by 1000 times.

You can collapse your own, but the .net framework provides a class to do just that: System.Security.Cryptography.Rfc2898DeriveBytes

RFC2898 uses the SHA1 algorithm and accepts plain text, salt, and number of iterations. It can output a variable-length key.

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

0
source share

All Articles