Shiro - MD5 encryption of passwords

Shiro - MD5 encryption of passwords

1. Encryption of passwords

The password stored in the data table should not be 123456, but the encrypted string of 123456, and the encryption algorithm is also required to be irreversible, that is, the encrypted string cannot be reversed to return the original password. Pushing back that this encryption is meaningless.

Well-known encryption algorithms, such as MD5, SHA1

2.MD5 encryption

1). How to encrypt a string to MD5

2). After using the MD5 encryption algorithm, how to use MD5 encryption for the string input by the foreground user, what needs to be done is to replace the current Realm's credentialsMatcher property with Md5CredentialsMatcher Since Md5CredentialsMatcher has expired, it is recommended to use HashedCredentialsMatcher and set the encryption algorithm. .

/**
 * {@code HashedCredentialsMatcher} implementation that expects the stored {@code AuthenticationInfo} credentials to be
 * MD5 hashed.
 * <p/>
 * <b>Note:</b> <a href="http://en.wikipedia.org/wiki/MD5">MD5</a> and
 * <a href="http://en.wikipedia.org/wiki/SHA_hash_functions">SHA-1</a> algorithms are now known to be vulnerable to
 * compromise and/or collisions (read the linked pages for more).  While most applications are ok with either of these
 * two, if your application mandates high security, use the SHA-256 (or higher) hashing algorithms and their
 * supporting <code>CredentialsMatcher</code> implementations.</p>
 *
 * @since 0.9
 * @deprecated since 1.1 - use the HashedCredentialsMatcher directly and set its
 *             {@link HashedCredentialsMatcher#setHashAlgorithmName(String) hashAlgorithmName} property.
 */
public class Md5CredentialsMatcher extends HashedCredentialsMatcher {

    public Md5CredentialsMatcher() {
        super();
        setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
    }
}

3. Use MD5 encryption

1). Modify the default credentialsMetcher of Realm in the configuration file to be

<bean id="jdbcRealm" class="com.java.shiro.realms.ShiroRealm">
    <property name="credentialsMatcher">
        <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <property name="hashAlgorithmName" value="MD5"></property> <!-- the name of the encryption algorithm -->
            <property name="hashIterations" value="1024"></property> <!-- Configure the number of times to encrypt -->
        </bean>
    </property>
</bean>

2). You can see through the breakpoint that the actual encryption is

3). Through new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations); we can get the string of "123456" after MD5 encryption of 1024;

public static void main(String[] args) {
        String hashAlgorithmName = "MD5";
        String credentials = "123456";
        int hashIterations = 1024;
        Object obj = new SimpleHash(hashAlgorithmName, credentials, null, hashIterations);
        System.out.println(obj);
    }

Change the plaintext 123456 in realm to fc1709d0a95a6be30bc5926fdb7f22f4

A login test is in progress.

login successful.

  1. There is still a problem with the above encryption. If the passwords of two people are the same, that is, the two encrypted strings in the data table are the same. However, we hope that even if the passwords of the two people are the same, the two encrypted strings are different. . That is, MD5 salt value encryption is required.

1). Modify Realm to use salt value encryption Complete ShiroRealm.java

public class ShiroRealm extends AuthenticatingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        System.out.println("doGetAuthenticationInfo " + token);

        // 1. Convert AuthenticationToken to UsernamePasswordToken
        UsernamePasswordToken up = (UsernamePasswordToken) token;
        // 2. Get username from UsernamePasswordToken
        String username = up.getUsername();
        // 3. Call the method of the database to query the user record corresponding to the username from the database
        System.out.println("get from database userName : " + username + " Corresponding user information.");
        // 4. If the user does not exist, an UnknownAccountException can be thrown
        if ("unknown".equals(username)) {
            throw new UnknownAccountException("User does not exist");
        }
        // 5. According to the user information, decide whether to throw other AuthencationException exceptions. Suppose the user is locked
        if ("monster".equals(username)) {
            throw new LockedAccountException("User is locked");
        }
        // 6. According to the user's situation, construct the AuthenticationInfo object and return it, usually using
        // SimpleAuthenticationInfo
        // The following information is obtained from the database.

        Object principal = username; // principal authenticated entity information.
                                        // Can be username, or the entity class object of the user corresponding to the data table
//        String credentials = "fc1709d0a95a6be30bc5926fdb7f22f4"; // credentials: password
        String credentials = null; // credentials: password
        String realmName = getName();
        AuthenticationInfo info = null;/*new SimpleAuthenticationInfo(principal, credentials, realmName);*/
        
        if("admin".equals(username)){
            credentials = "038bdaf98f2037b31f1e75b5b4c9b26e"; 
        }else if("user".equals(username)){
            credentials = "098d2c478e9c11555ce2823231e02ec1"; 
        }
        
        ByteSource credentialsSalt = ByteSource.Util.bytes(username);//The parameters here should be unique;
        
        info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);

        return info;
    }
    
}

The above password we can use the mian method to get

public static void main(String[] args) {
        String hashAlgorithmName = "MD5";
        String credentials = "123456";
        int hashIterations = 1024;
        ByteSource credentialsSalt = ByteSource.Util.bytes("user");
        Object obj = new SimpleHash(hashAlgorithmName, credentials, credentialsSalt, hashIterations);
        System.out.println(obj);
    }

After testing, the login was successful.

2). Notes

    1. Why use MD5 salt encryption:
    • It is hoped that even if the two original passwords are the same, the two strings resulting from encryption will be different.
    1. How to do it:
    • 1). When creating a SimpleAuthenticationInfo object from the return value of the doGetAuthenticationInfo method, you need to use the SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName) constructor
    • 2). Use ByteSource.Util.bytes() to calculate the salt value.
    • 3). The salt value needs to be unique: generally use a random string or user id
    • 4). Use new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations); to calculate the value of the encrypted password with the salt value.

Tags: Java Shiro

Posted by Smeep on Fri, 20 May 2022 10:27:48 +0300