Java implements password adding random salt for MD5 digest encryption (2021 / 05 / 11)

Posted by Begby on Sat, 12 Feb 2022 03:13:08 +0100

Java implements password adding random salt for MD5 digest encryption (2021 / 05 / 11)

1. General

In daily development, we often face the problem of saving the user password. We must not store the password in plaintext to the database. We can use hash digest algorithm to encrypt the password and then save it to the database.

Hash digest algorithm: only a corresponding hash value can be generated from the plaintext, and the corresponding plaintext cannot be obtained according to the hash value in turn.

2. Environmental preparation

All the methods of generating summary algorithms used in this paper are from Hutool toolkit, Hutool It is a small and comprehensive Java tool class library, which encapsulates some static methods and reduces the learning cost of relevant API s. If you want to know more, you can read it Official documents.

The author imports dependencies here through Maven:

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.5</version>
</dependency>

3. MD5 digest algorithm

MD5 is a very classic hash digest algorithm, which is widely used in data integrity verification, data digest, data encryption and so on.

Let's take a simple example, as follows:

@Test
public void MD5Test() {
    String password = "abc123456";
    String md5 = DigestUtil.md5Hex(password);
    System.out.println("md5 = " + md5);
}

Operation results:

md5 = 0659c7992e268962384eb17fafe88364

It can be seen that the password has been abstracted and encrypted, and the plaintext password cannot be obtained directly. However, if we input the summary results into the MD5 free cracking website, we can obtain the original password immediately.

Imagine if a hacker builds a super large database, calculates the MD5 hash value of all passwords with numbers and letters within 20 digits, and stores the password and their corresponding hash value in it (i.e. rainbow table). When cracking the password, you only need to check this rainbow table. Therefore, it is not safe to store the hash value of the password in MD5 alone.

4. MD5 + salt summary algorithm

Salt: in cryptography, it refers to inserting a specific string at any fixed position of the password to make the hash result inconsistent with the hash result using the original password. This process is called "salt".

After the user password + salt, hash and save it to the database, which can effectively deal with the rainbow table cracking method. However, when using salt, you need to pay attention to the following points:

  • The dead salt cannot be written in the code, and the salt needs to have a certain length (if the dead salt is too simple, the hacker may register several accounts to deduce it);
  • For example, the original password is too short, and it is easy to crack it with more than 20 bits of salt;
  • The best value is random and unique in the world, which means that there can be no ready-made rainbow table for you in the world;

Here, the author provides an idea to generate a unique UUID for each user password as its salt value, splice it behind the user password, then encrypt the MD5 summary of the user password + salt, and store the encrypted hash value and UUID in the database through a certain algorithm, so that the UUID can be inversely solved from the database when verifying the password.

The specific implementation code is as follows:

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestUtil;

/**
 * Safety tools
 *
 * @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
 * @version 1.0
 * @date 2021/04/07
 * @since 1.0
 */
public class SecureUtil {

    private static final int PASSWORD_AND_SALT_LENGTH = 64;

    /**
     * Generate a password with random salt
     *
     * @param password password
     * @return Password MD5 value with random salt
     * @author xiaoqqya
     * @date 2021/04/07
     */
    public static String generate(String password) {
        String salt = IdUtil.simpleUUID();
        password = DigestUtil.md5Hex(password + salt);
        char[] md5 = new char[PASSWORD_AND_SALT_LENGTH];
        for (int i = 0; i < PASSWORD_AND_SALT_LENGTH; i++) {
            md5[i] = password.charAt(i / 2);
            md5[++i] = salt.charAt(i / 2);
        }
        return new String(md5);
    }

    /**
     * Verify that the password is correct
     *
     * @param password password
     * @param md5      Password MD5 value with random salt
     * @return Is the password correct
     * @author xiaoqqya
     * @date 2021/04/07
     */
    public static boolean verify(String password, String md5) {
        char[] pwd = new char[32];
        char[] salt = new char[32];
        for (int i = 0; i < PASSWORD_AND_SALT_LENGTH; i++) {
            pwd[i / 2] = md5.charAt(i);
            salt[i / 2] = md5.charAt(++i);
        }
        return DigestUtil.md5Hex(password + new String(salt)).equals(new String(pwd));
    }
}

Reference link:

Related links:

Topics: Java Database Encryption cryptology