Hiring a developer or engaging a development house to build your app is frightening. It’s like buying canned food in the dark – you don’t know what the tin says. Learning to code might be too time-consuming, so you could benefit more by learning about best practices in app development, and insist that your programmer implements them.
This is especially crucial in password security, and for one important reason: users are fundamentally lazy. They use the same password for most of their services. So one weak link, say a database that is vulnerable to hackers, could compromise the user’s entire online identity. Not only is it a business necessity – users trust you less if hackers compromise your app – it’s an ethical one too.
“I’m not a security expert,” says T.J. Schuck, a developer at time-tracking service Harvest, during a talk at the Red Dot Ruby Conference in Singapore. “But I have to be a security expert strictly by virtue of the fact that I have users. If there was a breach or leak or anything, ignorance is not an excuse. You can’t say, we just didn’t know any better. That won’t absolve you from your sins.”
To cut the long story short, Schuck advocates bcrypt, which is probably the best algorithm for securing passwords right now. It’s easy to use on Ruby with a gem, and comes integrated into Devise, a user authentication solution for Ruby on Rails.
To show why bcrypt is effective, Schuck gives a rundown of how passwords are otherwise stored in a database, and how these methods suck in comparison.
The worst dish: plaintext
IT security works in layers. App-level security covers the need to protect against SQL injections, cross-site-scripting, or cross-site request forgeries. Infrastructure-level security means securing your data center to make sure people can’t walk into it. Network security involves setting up firewalls between devices to protect against data coming in from suspect, unsecured, or unknown locations.
Effective app security assumes all the other layers have failed. That’s what makes plaintext terrible: once a hacker compromises your database, it’s game over. So to safeguard against database intrusions, a developer must obfuscate password data.
Encryption is more sophisticated, but…
Encrypting passwords in databases results in better security. A simple but utterly useless encryption method is ROT13, which simply substitutes each letter with another one 13 places down in the alphabet.
Sophisticated methods like DS3 and AES exist, but they have one flaw: if intruders get the key, they can unlock the passwords. This is bad because if hackers do a database dump – storing the database into another file – they would probably already gain access to your app’s code or physical servers, which contains the data needed to decode your passwords.
Encryption also doesn’t protect against malicious in-house developers, who are probably out for revenge against some perceived slight, or bought over by a rival corporation to do damage – ridiculous as it sounds. So encryption is out.
Hashing tastes plain
While encryption is reversible, hashing, another method of obfuscation, is a one-way street. Like encryption, hashing receives a password on one end to produce a different output, but here’s the critical difference: no reverse function exists in which you can apply to the output to get the password.
Hashing is also deterministic, which means running a particular password through a hash function like MD5 or SHA-1 will always produce the same output. That’s great because it allows apps to check a keyed-in password against a stored hash in the database. But determinism is a double-edged sword.
Since the output is predictable, it’s easy to come up with a rainbow table which pairs the input and output for a certain hashing algorithm. In other words, you can look up the original word by pasting the hash in Google.
Adding some salt
Fortunately, adding ‘salt’ makes hacking more time-consuming by adding random characters to a hash so intruders can’t find them using a rainbow table. But Moore’s Law is salt’s greatest enemy.
“[Hackers] can’t look it up on an existing tables, but they can generate a new table trivially… on this Macbook Air, I can calculate 13 million SHA-1s in a second,” says Schuck.
Using an easily downloadable, off-the-shelf “advanced password recovery” software like Hashcat, paired with password dictionaries available on a Google search, Schuck generated 25 million unique password entries and ran through the list in a white-hat attack on a database. Schuck took just 87 seconds to steal 80,000 passwords.
Hackers look at opportunity costs: no security measure is completely foolproof, but it can slow an attack down until it becomes economically impractical. Salting works the same way: the more complex the salt, the longer it takes to crack the password.
But processors improve exponentially. For instance, an AX7990 graphics card by Radeon calculates 1.5 billion hashes a second. That disintegrates complex salts in no time.
The best recipe: bcrypt
Bcrypt is a “future-adaptable” function developed in 1999 that has all the essentials we talked about, like one-way hashes and password salts. But it adds one crucial feature: developers determine the length of a hash function and therefore the cost of cracking a password. So if computing power catches up, you simply increase the complexity. After implementing bcrypt, an attack that took 84 seconds to obtain thousands of passwords could take 84,000 years instead.
Critics of bcrypt argue that PBKDF2 and scrypt are more secure alternatives. They may be right. But using bcrypt puts you ahead of many vulnerable apps made by amateur programmers who don’t give two hoots about security. It’s like debating the differences between a BMW and a Mercedes Benz. You can’t go wrong with either.