Currently, the MD5 password database has a huge amount of data, and most common passwords can reverse query the plaintext of the password through the MD5 Digest. To prevent internal personnel (persons who can access database or database backup files) and external intruders from checking the plaintext of passwords through MD5, better protect the security of users' passwords and personal accounts (a single user may use the same password in multiple systems, so it involves the data security of users on other websites and systems ), add other information to the MD5 Digest result, which is called salt.
There are many algorithms for adding salt. Considering the purpose of adding salt (to prevent people with permissions at the bottom of the system), it is very difficult to find out whether or not to perform reverse lookup. It requires assistance from other software or hardware, it is less practical in many scenarios. If you only want to increase the difficulty of reverse lookup, there are many methods to choose from. One convenient method is MD5 (password + username), which adds the username and password string to MD5, such an MD5 Digest cannot be reversed. However, sometimes the user name may change, and the password becomes unavailable after the change (verifying the password is actually the process of re-calculating the Digest ).
Therefore, we have made a very simple algorithm. Every time we save the password to the database, a random 16-digit number is generated. we add the 16-digit number and the password and then calculate the MD5 Digest, then, add the 16-digit numbers to the abstract to form a 48-digit string. When the password is verified, 16 digits are extracted from the 48-Bit String according to the rule, and then added to the password entered by the user and then MD5. The results produced by using this method must not be directly reversed, and the summaries generated by the same password each time they are saved are also different. As shown in the following code:
Java code
- PackageCom. zving. Framework. Security;
- ImportJava. Security. messagedigest;
- ImportJava. util. Random;
- ImportOrg. Apache. commons. codec. Binary. HEX;
- /**
- * @ Author wyuch
- * @ Email wyuch@zving.com
- * @ Date 2011-12-31
- */
- Public ClassPasswordutil {
- /**
- * Generate a password containing random salt
- */
- Public StaticString generate (string password ){
- Random r =NewRandom ();
- Stringbuilder sb =NewStringbuilder (16 );
- SB. append (R. nextint (99999999). append (R. nextint (99999999 ));
- IntLen = sb. Length ();
- If(LEN <16 ){
- For(IntI = 0; I <16-len; I ++ ){
- SB. append ("0 ");
- }
- }
- String salt = sb. tostring ();
- Password = md5hex (password + salt );
- Char[] Cs =New Char[48];
- For(IntI = 0; I <48; I + = 3 ){
- CS [I] = password. charat (I/3*2 );
- CharC = salt. charat (I/3 );
- CS [I + 1] = C;
- CS [I + 2] = password. charat (I/3*2 + 1 );
- }
- Return NewString (CS );
- }
- /**
- * Verify that the password is correct.
- */
- Public Static BooleanVerify (string password, string MD5 ){
- Char[] CS1 =New Char[32];
- Char[] CS2 =New Char[16];
- For(IntI = 0; I <48; I + = 3 ){
- CS1 [I/3*2] = md5.charat (I );
- CS1 [I/3*2 + 1] = md5.charat (I + 2 );
- CS2 [I/3] = md5.charat (I + 1 );
- }
- String salt =NewString (CS2 );
- ReturnMd5hex (password + salt). Equals (NewString (CS1 ));
- }
- /**
- * Obtain the MD5 Digest in the hexadecimal string format
- */
- Public StaticString md5hex (string SRC ){
- Try{
- Messagedigest MD5 = messagedigest. getinstance ("MD5 ");
- Byte[] BS = md5.digest (SRC. getbytes ());
- Return NewString (NewHex (). encode (BS ));
- }Catch(Exception e ){
- Return Null;
- }
- }
- Public Static VoidMain (string [] ARGs ){
- String Password = generate ("admin ");
- System. Out. println (verify ("admin", password ));
- }
- }
Package COM. zving. framework. security; import Java. security. messagedigest; import Java. util. random; import Org. apache. commons. codec. binary. hex; /*** @ author wyuch * @ email wyuch@zving.com * @ date 2011-12-31 */public class passwordutil {/*** generate password containing random salt */public static string generate (string Password) {random r = new random (); stringbuilder sb = new stringbuilder (16); sb. append (R. nextint (99999999 )). append (R. nextint (99999999); int Len = sb. length (); If (LEN <16) {for (INT I = 0; I <16-len; I ++) {sb. append ("0") ;}} string salt = sb. tostring (); Password = md5hex (password + salt); char [] cs = new char [48]; for (INT I = 0; I <48; I + = 3) {CS [I] = password. charat (I/3*2); char c = salt. charat (I/3); CS [I + 1] = C; CS [I + 2] = password. charat (I/3*2 + 1);} return new string (CS);}/*** verify that the password is correct */public static Boolean verify (string password, string MD5) {char [] CS1 = new char [32]; char [] CS2 = new char [16]; for (INT I = 0; I <48; I + = 3) {CS1 [I/3*2] = md5.charat (I); CS1 [I/3*2 + 1] = md5.charat (I + 2 ); CS2 [I/3] = md5.charat (I + 1);} string salt = new string (CS2); Return md5hex (password + salt ). equals (new string (CS1);}/*** get the MD5 Digest in the hexadecimal string form */public static string md5hex (string SRC) {try {messagedigest MD5 = messagedigest. getinstance ("MD5"); byte [] BS = md5.digest (SRC. getbytes (); return new string (New hex (). encode (BS);} catch (exception e) {return NULL;} public static void main (string [] ARGs) {string Password = generate ("admin "); system. out. println (verify ("admin", password ));}}
-------------------------- Response to questions about the number of persons downstairs ---------------------------
1. This is a very simple algorithm. Like most salt adding algorithms, it is only necessary to increase the difficulty of reverse lookup through the MD5 database (for example, using the reverse lookup database at http://www.md5.cc.
2. The author assumes that the person who can obtain the MD5 Digest of the user password in the application can also obtain the algorithm of the password digest of the application, and the external factors that the algorithm depends on (User ID, user name, salt adding rule, random data, etc. in the persistence layer ). Therefore, no matter what algorithm (such as multiple MD5 and various salt adding rules), the attacker can re-calculate the MD5 lookup library based on your algorithm and data, to obtain a dedicated MD5 lookup database for your user database, and then reverse query the plaintext of the password one by one.
3. Considering that user password verification is actually a process of re-forming the MD5 Digest, user password verification is a frequent behavior that may result in high concurrency. Therefore, password verification generally does not allow the use of very complex and performance-consuming algorithms. The CPU time consumed by one verification should be within 100 milliseconds. One reason we use MD5 or sha1 is that the tested abstract is irreversible; the other is that the performance is within the permitted range (for short strings such as passwords, A common PC can be computed tens of thousands of times per second ).
4. Because of the performance requirements mentioned at, re-constructing a dedicated MD5 lookup Database Based on your algorithm will not take a very long time (using good machines and parallel computing, the MD5 lookup database with over 10 billion records can be re-formed within a meaningful time range ).
5. Based on the above 2/3/4 points, no matter what salt algorithm is used, as long as the algorithm can be obtained, the attacker can crack the plaintext of any user's password (verify whether the password exists in the MD5 lookup library, and obtain the plaintext if it exists. Complex passwords are not recorded in the MD5 lookup database, so they cannot be cracked even if no salt is added ).
6. But multiple MD5 algorithms that disrupt the digital sequence of MD5 results are less secure, such as multiple MD5 algorithms, the attacker only needs to create an MD5 lookup Database Based on your algorithm, and then crack all your passwords at one time.
7. The algorithms in this article, as well as MD5 (username + password + salt), MD5 (userid + password + salt), and so on, introduce interference items (called salt) outside the password ), therefore, the attacker must create an MD5 lookup database for each password, which will be very costly. It is no longer feasible to crack all the passwords.
8. However, MD5 (username + password + salt) requires that username remain unchanged. MD5 (userid + password + salt) requires that the user must have a constant userid other than the user name. These additional requirements lead to the lack of good applicability of the algorithms in this article.
9. If you do not need to consider one of the above cases, this algorithm is of no use to you. Let's just let the author boast about it. This algorithm is a little better than nothing, so I am sending a post to ask everyone to make an axe and express my gratitude to the students who reply to the post.