How to Handle Server-Side Passwords

Math can be hard. This is not a bad thing, and actually security depends on this fact. The difficulty of factoring prime numbers is what makes systems like GPG actually secure. This is best for systems where you will want to be able to look at the encrypted data, for instance financial data.

Hashing uses a similar thought process, by using an arbitrary algorithm to create a string, called a hash, by manipulating another string in a repeatable process. This is best for uses such as passwords. When you create a password in many places, the “password” itself is hashed, and when you log in the string you enter is hashed using the same process and grants authorization if equal to the known. Cryptographic hashing is useful because, with some certainty, you cannot create an arbitrary string to match a given hash.

Let’s look at a demonstration, using the tool sha1pass

# Let's hash the word ThisIsMyPassword
$ sha1pass ThisIsMyPassword
# Now, let's hash the word ThisIsMypassword, changing the final word to lowercase
$ sha1pass ThisIsMypassword

What this demonstrates is that even a simple change in a string can result in a dramatically different hash result. You can also change the hash by adding an additional random string, called a salt, so that even if multiple people use the same password it will result in different hashes.

EDIT Dec 12 2013: I should have noted that if you do not supply a salt, sha1pass will use a random salt. In the above examples, they are “1/CFCl67” and “SO6FyQhU”. Thanks to Eduard Iten for pointing this out.

Below, you see how to specify a salt when generating the hash.

# Using string "Salt" for the salt
$ sha1pass ThisIsMyPassword Salt
# Using string "Salts" for the salt
$ sha1pass ThisIsMyPassword Salts

As you see, changing that also results in different output. What is problematic is that the salt has to be listed in plain text somewhere. While file or database permissions should protect this, if gathered along with the hash results, password crackers can get to work. Recent advancements in password cracking have been as a result of programmable GPUs, which allow up to 160 million password attempts per SECOND. The high-end of cracking is currently around 350 billion attempts per second instead.

Given this, people have taken to adding work to generating password hashes. Tools such as PBKDF2 allows you to run the initial string through a hashing algorithm, as before. What is different is that it runs the result of that hash through the algorithm again, an additional number of times you specify.

# Using grub-mkpasswd-pbkdf2 and the password "ThisIsMyPassword",
# test using 100000 and 1000000 iterations
$  time grub-mkpasswd-pbkdf2 -c 100000
Enter password:

Reenter password:
PBKDF2 hash of your password is grub.pbkdf2.sha512.100000.07802F2A6CD41B90ED2C2E1740F67AAFFDD8A628DE4738DF4536D48367B019657F566D9293F61292FD922B5A8EC79BC133E27FA002A363BC9EF9C5914A22284B.59DBAED532019376DE96DC35FC10C498E43D295C583A414EB0A31BF6379127C366AEE3DA064D4C0088D21BF31F5C00AAA5AE7BB7462DE6BA83B896D1A7CAFF48
grub-mkpasswd-pbkdf2 -c 100000  0.48s user 0.00s system 20% cpu 2.373 total
$ time grub-mkpasswd-pbkdf2 -c 1000000
Enter password:

Reenter password:
PBKDF2 hash of your password is grub.pbkdf2.sha512.1000000.9329135ED8527C220E9DAF039A1D63D2324DFB64FF18F7CA5420F80A2FEC1E01323B8096333D7EAD2F98DB8AAAAB7099280C2A8B097893299637F4B6F88A538E.F22A9CFD6B443266158F8218531E12C1D1889C0A259BF6805D571CFE563AE53F5BF9452C05E478587A99B12AC354949FB8D48C9AFB59DDD9DB7D3025FA86146F
grub-mkpasswd-pbkdf2 -c 1000000  4.76s user 0.01s system 68% cpu 7.010 total

Not only does the result obviously change, the time necessary to calculate the hash goes up linearly with the increased difficulty. The password cracking cluster described above drops from 350 billion attempts per second to several hundred thousand instead. Absent advances either in finding algorithm vulnerabilities or underlying mathematics that allow for generating collisions.

Finally, we can go to the new example of how not to handle passwords. The underlying password should never be the desired information by a service, it is instead the knowledge of it for authentication. Even if it is forgotten, new passwords should be sent through what is believed to be known communication channels. Therefore, there is never a reason to allow for accessing that knowledge.

That last link very casually states that encryption should not be used for passwords. While better than plain text for password storage, it requires that the underlying system have the ability to decrypt them. When that system is compromised, for instance with Adobe’s recent breach, every customer password suddenly can be found and made available. This breach even allowed all of the password hints to be accessed, which as XKCD points out creates the world’s largest crossword puzzle.

A back door into the information will be used, and never in a good way. Stick with known-good hashing methods, and add as much work as your system can support. Be sure to stay aware of advances that necessitate modifications of either the hash used or the work factor associated with it.