The hash and salt operations on passwords are not unfamiliar. The two Visual Studio Enterprise Edition examples use this method to encrypt this method. Combined with the sample code, I summarized a class that includes static methods such as encryption and comparison of passwords. Instructions for use: Use the hashandsalt method to encrypt the password and store it in the database. When a user logs on, use the comparepasswords method to compare the password entered by the user with the password stored in the database during user registration, and determine whether the password entered by the user is correct. Credentials. CS Using system; Using system. IO; Using system. text; Using system. Security. cryptography; Namespace bookstore. Common { /// <Summary> /// Summary of credentials. /// Principle: /// Hash the password /// To avoid storing passwords in plain text, a common security method is to hash the passwords. As shown in the following code, hash the password using the system. Security. cryptography namespace (which implements the 160-bit SHA-1 standard. For more information, see sha1 members. /// Perform the salt operation on the hash /// Although it is a good start to execute hash operations on passwords, to increase security against potential attacks, You can execute salt operations on Hash operations on passwords. Salt is a random number inserted in the password that has executed the hash operation. This policy helps prevent potential attackers from exploiting pre-computed dictionary attacks. Dictionary attacks are attacks that allow attackers to use all possible combinations of keys to crack passwords. When you use the salt value to further randomize the hash operation, attackers will need to create a dictionary for each salt value, which will make the attack very complex and costly. /// The salt value is stored together with the hash and is not encrypted. The stored salt value can be used for password verification later. /// </Summary> Public class Credentials { Private Static string key = "! 48% 0d-f = CJ>, S & 2 "; // key (increase password complexity, it seems redundant) Private const int saltlength = 4; // defines the length of the salt value /// <Summary> /// Hash and salt the password /// </Summary> /// <Param name = "password"> password entered by the user </param> /// <Returns> </returns> Public static byte [] hashandsalt (string password) { Return createdbpassword (hashpassword (password )); } /// <Summary> /// Add the key to the password entered by the user and then hash the sha1 /// </Summary> /// <Param name = "password"> password entered by the user </param> /// <Returns> returns the byte [] (20 bytes for 160 bits) after the 160-bit SHA-1 hash. </returns> Private Static byte [] hashpassword (string password) { // Create sha1's object instance sha1 Sha1 sha1 = sha1.create (); // Calculate the hash value of input data Return sha1.computehash (encoding. Unicode. getbytes (password + key )); }
/// <Summary> /// Compare whether the password in the database is the same as the password entered /// </Summary> /// <Param name = "storedpassword"> password in the database </param> /// <Param name = "password"> password entered by the user </param> /// <Returns> true: equal/false: unequal </returns> Public static bool comparepasswords (byte [] storedpassword, string password) { // Hash the password entered by the user Byte [] hashedpassword = hashpassword (password ); If (storedpassword = NULL | hashedpassword. length! = Storedpassword. Length-saltlength) { Return false; } // Obtain the salt value of the password in the database. The last four bytes of the password in the database are the salt value. Byte [] saltvalue = new byte [saltlength]; Int saltoffset = storedpassword. Length-saltlength; For (INT I = 0; I <saltlength; I ++ ){ Saltvalue [I] = storedpassword [saltoffset + I]; }
// Password entered by the user add the salt value to the password entered by the user for Salt Byte [] saltedpassword = createsaltedpassword (saltvalue, hashedpassword );
// Compare whether the password in the database is equal to the password entered by the user passing through the salt Return comparebytearray (storedpassword, saltedpassword ); } /// <Summary> /// Compare two bytearrays to see if they are equal /// </Summary> /// <Param name = "array1"> </param> /// <Param name = "array2"> </param> /// <Returns> true: equal/false: unequal </returns> Private Static bool comparebytearray (byte [] array1, byte [] array2) { If (array1.length! = Array2.length) { Return false; } For (INT I = 0; I <array1.length; I ++) { If (array1 [I]! = Array2 [I]) { Return false; } } Return true; } /// <Summary> /// Perform the salt operation on the password to be stored /// </Summary> /// <Param name = "unsaltedpassword"> Hash hash password that has not been used for salt Operations </param> /// <Returns> password after salt (the length of the password after salt is 20 + 4 = 24, and the field for storing the password is binary (24) </returns> Private Static byte [] createdbpassword (byte [] unsaltedpassword) { // Obtain the salt value Byte [] saltvalue = new byte [saltlength]; Rngcryptoserviceprovider RNG = new rngcryptoserviceprovider (); RNG. getbytes (saltvalue );
Return createsaltedpassword (saltvalue, unsaltedpassword ); }
/// <Summary> /// Create a password that passes through Salt /// </Summary> /// <Param name = "saltvalue"> salt value </param> /// <Param name = "unsaltedpassword"> Hash hash password that has not been used for salt Operations </param> /// <Returns> password after salt </returns> Private Static byte [] createsaltedpassword (byte [] saltvalue, byte [] unsaltedpassword) { // Add the salt value array to the hash Hash hash array and splice it into a rawsalted array. Byte [] rawsalted = new byte [unsaltedpassword. Length + saltvalue. Length]; Unsaltedpassword. copyto (rawsalted, 0 ); Saltvalue. copyto (rawsalted, unsaltedpassword. Length );
// Hash the merged rawsalted array to the saltedpassword array with a length of 20 bytes) Sha1 sha1 = sha1.create (); Byte [] saltedpassword = sha1.computehash (rawsalted ); // Add the salt value array to the saltedpassword array and splice it into a dbpassword array (24 bytes in length) Byte [] dbpassword = new byte [saltedpassword. Length + saltvalue. Length]; Saltedpassword. copyto (dbpassword, 0 ); Saltvalue. copyto (dbpassword, saltedpassword. Length ); Return dbpassword; } } }
|