IntentThis pattern (actually more of a best practice) provides an easy method of adding some level of encryption for password storage. ProblemMany applications still store passwords in clear text. Because most of the code is already written to provide at least some level of encryption, there is little excuse for not providing it. To understand this pattern, you must first understand the concept of a one-way hash. A simple definition of a one-way hash is a scrambled version of a string that cannot be easily unscrambled to get the original string back. To store the password, the hash is generated for the password to be stored. We'll call the stored hash value hash 1 . When the user comes to the site and enters his or her password, the second hash is generated, which we will call hash 2 . At this point, we don't care what actual passwords are entered, just that hash 1 and hash 2 match. I stress that a one-way hash just makes it more difficult to determine the original string because a brute-force method of generating a dictionary of all possible password combinations could be generated for any known hash algorithm. Then, taking the hash and going backward, the original value would be accessible. The obvious ways of making this more difficult would be to expand the number of possible combinations by including numbers and mixed case in the passwords or to keep the one-way hash algorithm (or any keys used) secret. This single table structure can be seen in Figure 7.8. Figure 7.8. Password Storage class diagram.
ForcesUse the Password Storage pattern when:
StructureConsequencesThe Password Storage pattern has the following benefits and liabilities:
ParticipantsNone ImplementationThe Password Storage pattern exposes one main function that, in this example, wraps the MD5 compute hash function to generate the hashes. The only technical details to remember are to convert the string to an array of bytes prior to encryption and to convert the encrypted bytes back to a base-64 string because the string may have embedded nulls or other ugly items that make string handling (and storing them in databases) difficult. Listing 7.20 Hashing helper method implementation.public static string GetOneWayHash(string Value) { byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(Value); // This is one implementation of the abstract class MD5. MD5 md5 = new MD5CryptoServiceProvider(); byte[] result = md5.ComputeHash(data); return System.Convert.ToBase64String(result, 0, result.Length); } It is strongly encouraged that the readers investigate alternate implementations of this method. |