In this day and age of websites being hacked, personal information being stolen, and companies large and small being targeted by hackers around the world, you would think most developers would go through their systems to make sure they are following best practices when it comes to security.

I understand “security” is big and scary and has many layers. Let’s start with something easy: passwords.

Facepalm for bad password securityLast week, I signed up for a service. I’m not going to put them on blast, but after I signed up, I received an email with my new account information, including my password.

My heart skipped a beat.

That’s very bad.

If you get an email from a website, large or small, and it contains your password, be very wary. In the vast majority of situations, they are not storing that password in a secure way.

When I pressed them, they said it wasn’t a huge deal because they weren’t storing credit card details in there.

The reality is this: it doesn’t matter what you are or aren’t storing in your database or application. If you have weak security in one place, you have weak security everywhere. I would hazard a guess that the password strength and security for the other servers on that network aren’t great either.

So why do companies launch web applications with terrible password security? Some of it may be lack of knowledge, but that excuse is harder and harder to believe in today’s world.

For some companies, that’s the way its always been done. For others, they store passwords in plain text to make life easier for customers who have lost theirs. They think it’s easier to give them their password as opposed to reset it.

Finally, there’s cost. If have to retrofit your web application to store passwords securely, there is time and effort and resources needed to do that. Company executives may not see the return on investment, which is unfortunate.

One of the most popular posts on this blog was on I did in 2008 about passwords. Specifically, you should never store a user’s password in your database as plain text. This means not saving in  your database or text file exactly what the user typed in.

When developers store passwords this way, and an unauthorized person gains access, that attacker needs to do no work to get all user data. This comes from MediaTemple, who was hacked in 2009 and it was discovered they were storing passwords in plain text.

“Clear Text” is a method of storing passwords in a database so that they are human readable. This preference was made to provide customers a convenient way of managing access to their services, e.g. connecting a PHP app to MySQL. The “clear text” method can be less-secure than methods involving “encryption”, where passwords are not human-readable. This is less convenient for customers, but adds a layer of security. Properly secured databases can store passwords using either method, with the information kept private. However, if a database gets compromised, the encryption method is the only way to keep the information secure.

If you want to securely store your passwords, use a decent hashing algorithm, use a salt, or use a strong password library such as Bcrypt. Don’t store them as plain text. It isn’t hard, and it will help secure the information your users have trusted you with.

I think it’s fair for users to think that sites they give their personal information to will keep that information secure.

It seems like every week there’s a report of another security intrusion, in higher ed or not, with user details being stolen. In many of these cases, user’s passwords were not stored correctly, and in some cases, they were being stored in plaintext, which means there was no encryption or hashing being used.

Before we go any further, if you are storing passwords for your web app in plaintext, shut it off immediately and fix it. Seriously.

Even LinkedIn, a network built by very smart people, was only using SHA1 for their passwords, and no salt. All it takes is a rainbow table, a powerful computer and passwords are easily cracked.

From Poul-Henning Kamp, writing at the Association for Computing Machinery:

This is the first place LinkedIn failed utterly: Calculating the SHA1 function is very, very fast. A regular computer can crunch from 10 million to 100 million of them per second using the GPU, making it a trivial task to check even very large lists of potential passwords.

I’ve written in the past about some ways to use salts to protect passwords, but even some of those recommendations are now out of date.

Recently, for anything I’ve written that needs a login, I’ve used Bcrypt. There are ports for just about any type of programming language out there. If you’re writing in PHP, I’d recommend PHPass, a portable public domain password hashing framework. Takes out a bunch of work and is computationally slow, which is what you want when hashing a password.

If you’re looking for a refresher on password security, or you’re new to building apps and want a quick primer on how to do it right, you’ll enjoy this video from Les Hazelwood, CTO of Stormpath. In it, he walks you through various levels of password security and how to store them, from just plain wrong to crazy and complicated. If you’ve got a few minutes, it’s really worth checking out.

Let’s say you’re building a big new web app at your institution. One of the parts of this application will be storing usernames and passwords. There are a ton of ways to do this, but today I want to share with you one way that I do things, in the hopes of making my logins as secure as possible. For our examples today, we’ll be using PHP.

Before I get going too far, I should mention that when I say storing passwords, what we’re really doing is storing a hash of the user’s password. When we authenticate a user, we run the password they supply through whatever algorithm we’re using to encrypt and hash their input and we compare the result to what we’re storing in our database.

That being said, when storing passwords for your app, you have a many options. You could skip all security and store your users’ passwords in plain text in MySQL. Bad idea. You could use MySQL’s default password functionality. This is okay, but you could do things better.

For the rest of this post, let’s create a password variable, $pass. For all the examples, let’s set the value of $pass as “highedwebtech1”.

Let’s look at what’s generated when we pass the $pass variable through MD5.

echo md5($pass);

That gives us the following hash:


That’s not a terrible way to store a password, but there’s been research for the last couple of years that its possible to create MD5 collisions – where you generate lists and lists of MD5 hashes and look for matches. For example, this site will look up your MD5 hashes and check for collisions.

Well, we could use SHA1 to encode the password. Let’s run our $pass variable through SHA1:

echo sha1($pass);

That gives this:


Getting better. But – SHA1’s been broken as well. The chances of your user accounts being brute-forced by someone running SHA1 collisions is very minute, but let’s keep searching for something better.

Let’s do some crazy hashing and mashing. Let’s look at PHP’s crypt function.

crypt() will return an encrypted string using the standard Unix DES-based encryption algorithm or alternative algorithms that may be available on the system.

If we run the following code:

echo crypt($pass);

We get the following:


crypt() also allows you to add a salt. Wikipedia describes a salt thusly: “a salt comprises random bits that are used as one of the inputs to a key derivation function.” This basically means we can specify some characters that will become part of our encryption scheme.

Let’s create a $salt variable. We’ll give $salt a value of, for now, “yummysalt”.

Let’s run crypt() again but this time we’ll specify a specific salt. The system I’m running this on in these examples is using standard DES as its encryption.

echo crypt($pass,$salt);

This returns:


Standard DES puts the first 2 characters of the salt at the beginning of the hash of the password. If we use “yummysalt” as our salt (footnote – DES only uses the first 2 characters, we could have just made our salt “yu”), every time we run our password through crypt we will get the same value. The number of characters in your salt can depend on your system settings, including values in PHP and your server software.

Specifying a salt isn’t a bad thing to do, but you’ve got to now store that salt somewhere in your code. If your system is compromised, and with your salt, cracking passwords may be a little easier for your user passwords to be cracked.

If you’re sensing a theme here, you’d be right. DES is also susceptible to cracking, even when using a salt.

So, what’s a way to do it thats secure and has little chance of getting cracked? There are a lot of different ways to answer that question, but here’s some ideas I had, along with some help from a friend, who’s a security professional at a major research institution.

He recommends using something like the following, which is based on the username and password responses we receive from the user.

$username = "user1";
$password = "highedwebtech1";

echo sha1($username.$password);

In the code above, we’re creating a hash from a concatenation of the username and the password they enter. But, Mike, you say, a few paragraphs earlier you said SHA1 wasn’t the best choice. In this case though, we’re not hashing just the password. We’re hashing an entirely new value, in this case, user1highedwebtech1. That would be much more difficult to crack, especially using a brute-force attack. Here’s the hash value we get back from this function:


It’s long, and difficult to crack. When it comes time for a user to log in, checking against what they enter is easy. Just put the two values together, run it through SHA1 and then compare that to the value we originally stored in the database.

It should also go without saying that you should never email a user’s password to them. Either send them a replacement, temporary password or make them reset it altogether by emailing them a link with a hashed value they need to reproduce. But that’s a whole other post.

Want to learn more about doing this stuff in PHP? I’d recommend reading about about the mcrypt module. It offers a great deal of additional functionality.

Happy hashing!

What tips or tricks do you use when it comes to handling passwords? I’d like to learn how you deal with this issue.