There are, as you know, a plethora of Web sites on the Internet that allow for, if not require, some sort of user account. For example, on ASPMessageboard.com, in order to post a message one must create a user account, which includes information like username, email address, and password. To buy a book from Amazon.com you must create an account, which includes your name, an email address, a password, a shipping address, and so on. Note that each of these user accounts requires, among other things, a username and password pair, which are used to authenticate a user.
If you've designed a site that required allowing user accounts you likely implemented the user account by creating a database table named something like
UserAccount, with fields like
Password. This table would contain a row for each user; when a user wished to log on, they'd submit their username and password, which would be used to query the
UserAccount to see if there was a row whose
Password fields matched the user-supplied username and password.
While this approach is pretty typical one of its downsides is that each user's password is stored in an unencrypted form in the database. That means that if someone compromises your database they have access to the passwords for every user. In this article we'll look at how to use MD5 to encrypt your passwords so that not even the database administrator can determine a user's password.
|Is Your Data Safe?|
| Realize that the data in your database is not safe. Imagine that you host a database at a respectable Web hosting company that keeps the database patches up-to-date and has never had someone gain unauthorized access to the database before. While you may think that in such a situation your data is private from all others, understand that any database administrator who works at the Web hosting company will be able to view your data at will. |
Before deciding to implement a password encryption scheme, as will be described in this article, one must ask themselves not how safe is their data, but how sensitive it is. That is, assume that others will see your information. If it is vitally important that this not incur, such a password encrypting scheme is ideal. For example, a financial institution should use encrypted passwords, so that there is not a risk of someone issuing an unauthorized transaction in your name. However, you may decide it not worth the hassle to implement password encryption for, say, a messageboard site, figuring that even if someone does obtain the password for every user, you can just reset everyone's password to some random value and have each person login with their new password and change it. In the former case much irreparable harm can be done; in the latter case, it may be an annoyance to deal with, but in the end does it really matter if your messageboard Web site incurs a security breach?
There are two general classes of encryption: one-way encryption and two-way encryption. Two-way encryption is the most common form of encryption. It takes a plain-text input and encrypts it into some encrypted text. Then, at some later point in time, this encrypted text can be decrypted, which results in the plain-text that was originally encrypted. Two-way encryption is useful for private communications. For example, imagine that you wanted to send an eCommerce Web site your credit card number to make a purchase. You wouldn't want to have your credit card numbers sent over the Internet in plain-text, because someone monitoring the Internet might see your credit card information whiz by. Rather, you'd want to send your credit card information as an encrypted message. When this encrypted message was received by the Web server, it could be decrypted, resulting in the actual credit card numbers.
One-way encryption, on the other hand, only allows for a plain-text input to be encrypted. That is, there is no way to decrypt the data. At first it may seem that such an encryption scheme is not needed - after all, why would you only want to be able to encrypt data and not decrypt it? A practical example of this is storing encrypted passwords on a database server, which is what this article is all about! That is, when a user creates a new account, he or she will supply their password. Rather than storing this password to the database as plain text, this password can be encrypted using a one-way encrypting algorithm and its encrypted form can be saved to the database. That way, if someone gains access to the database they will not see any of the passwords in plain-text.
MD5 encryption is an example of a one-way encryption algorithm; specifically, MD5 encryption maps a plain-text string of an arbitrary length to a small encrypted string of a fixed length. Two important properties of the MD5 algorithm are that given an encrypted output it is impossible to revert back to the initial, plain-text input, and that any given input always maps to the same encrypted value. The former property means that even if a hacker sees the encrypted output of the MD5 algorithm, they can't "unwind it" and get back at the plain-text input; the latter property means that if you wish to encrypt a particular plain-text input that it will always result in the same encrypted output.
MD5CyptoServiceProvider class in the
System.Security.Cryptography namespace of the .NET Framework provides a class for performing one-way, MD5 encryption. It is this class that we'll use to provide encrypted passwords in our database. Before we examine how to implement encrypted passwords, let's take a minute to investigate the functionality of the
MD5CyptoServiceProvider class. The main method of this class is the
ComputeHash method, which takes as input an array of bytes (the plain-text string to encrypt) and returns an array of bytes, which is the encrypted value. Commonly we'll want to encrypt a string, meaning that we must convert our string to an array of bytes in order to use the
ComputeHash method. This conversion can be accomplished by using the
UTF8Encoding encoding class, as shown in the following example:
'The string we wish to encrypt
Keep in mind that the
ComputeHash method deals with arrays of bytes, not strings. Hence, to encrypt a plain-text string you must convert it to an array of bytes. This is accomplished by using the
UTF8Encoding encoding class's
GetBytes method (see the last line of the above code example). The return result of the
ComputeHash method is the encrypted data as an array of bytes. (For all practical purposes, the encrypted array has exactly 16 elements.)