Will you not know Shiro in 2021?-4. Use MD5 + salt + hash for password encryption

I. Introduction

The previous article introduced the use of a custom Realm to achieve data acquisition, but the data acquisition still does not come from a real database or nosql. It just wraps a method and pretends to obtain the data in the database from this method. User information, and then we returned a SimpleAccount, this object carries the user name and password, at the time we were the password returned in plain text. This is obviously unsafe. Once the data source is compromised, all user information will be leaked. So here we introduce the commonly used password encryption strategies.

2. Commonly used encryption strategies

We may have used different encryption algorithms in our daily development. So what are the advantages of these algorithms and what are their characteristics? Here is a brief introduction to several commonly used encryption algorithms.

1.MD5

  1. What is MD5
    MD5 is very different from our commonly used algorithms such as SM2. Usually the encryption algorithms we use can crack ciphertexts, such as encryption methods based on symmetric and asymmetric algorithms, but MD5 does not work. MD5 The typical feature is that it is irreversible , which means that the information we encrypted can no longer be decrypted in reverse. Then some people may say that there are many MD5 online decryption websites on the Internet. Note that these are not really decrypted MD5 encrypted secrets Instead, it uses an exhaustive method to match the ciphertext one by one to achieve cracking. This brute force cracking is actually very easy to circumvent, but this involves another feature of MD5, that is, the fixed plaintext is encrypted multiple times The results are all the same . The MD5 algorithm generated is always a hexadecimal 32-bit (256bit) string .
  2. Application scenarios of MD5
    ①Apply to encryption scenarios, such as password encryption in login.
    ②It is applied to signature to determine whether two files are the same file. The ciphertext of the same file encrypted by MD5 must be the same, which can prevent the file from being tampered with.

2.AES

  1. What is AES
    AES is a commonly used encryption algorithm. It is a symmetric encryption algorithm . What is a symmetric encryption algorithm? Both encryption and decryption require the same secret key. The commonly used AESs are AES128, AES192, and AES256 . What do these mean? These three AESs actually refer to different key lengths. The key lengths corresponding to the three AESs are 128 bits, 192 bits, and 256 bits, respectively, which are 16, 24, and 32 in bytes. For example, such a secret key: String str = "1234567812345678", then the AES that uses this secret key is naturally, AES128 is used.

  2. AES usage scenarios
    In actual projects, AES encryption is usually used for the front-end and back-end data interactions, so that the leakage of sensitive information can be avoided. However, it is worth mentioning that it is usually not just simple encryption of AES. The ciphertext will be Base64 encrypted before interaction. This ensures the security of information transmission, but there is no 100% security. As long as the ciphertext can be solved, there will be a risk of cracking, and the risks are all It is relative, and all we can do is to be relatively safe.

3. Use MD5+salt+hash to realize login

We already know that with MD5 encryption, we can still use the brute force method to achieve brute force cracking, so that users cannot use simple passwords when setting passwords. Simple passwords can easily be exhausted, but users There is no such awareness when using, so we need to add some "salt" to the user's password to make the password more salty, so that the password will not be cracked so easily. The so-called salt is actually to splice a string of randomly generated strings for the password. In addition, we can also hash the hexadecimal value generated by MD5+ salt, which will make the password more secure. Even if the database is compromised, the salt and password will be obtained, and the number of hashes will still not be discovered. Of course, this situation is rarely encountered.

1. How to use Shiro's MD5 to encrypt data

So how to use the MD5 provided by Shiro, we will understand by looking at the following code

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Md5Hash md5Hash = new Md5Hash("123");
        System.out.println(md5Hash.toHex());
        Md5Hash md5Hash1 = new Md5Hash("123","12345&8");
        System.out.println(md5Hash1.toHex());
        Md5Hash md5Hash2 = new Md5Hash("123","12345&8",1024);
        System.out.println(md5Hash2.toHex());

    }
}

The output of the above program is as follows:

202cb962ac59075b964b07152d234b70
19d11f5191d12b1c224a7d535e1cb650
cc24303e7e1827dbb9742d1f4efeb0ec

Process finished with exit code 0

According to the above example, we can see it vividly. The first example is data that only uses MD5 for encryption, the second part is MD5 encryption with "salt" added, and the third part is in the first part. The value is hashed on the basis of the two parts. In fact, according to this idea, we can encrypt the password in many ways, such as hashing the salt, MD5 encryption for the salt, or using Base64 or AES for the salt, etc. Yes, we can combine a lot of encryption, but in fact it is unnecessary and there is no absolute security, but generally we use MD5 + "salt" + hash.

2. Use MD5+salt+hash to realize login

Let's take a look at how to use this encryption method in the login scenario implemented by Shiro. As mentioned in the previous article, there is a password matcher in the password verification place. The default password matcher is equals comparison. Password, since we don’t want to use equals for direct comparison, then we need to replace this password matcher, so how do we replace this password matcher?

1. Where is the password matcher

We have already said that the verification of the password is done here, as shown in the figure below

Insert picture description here
The first line of this method is the password matcher. The password matcher is an attribute of this class, so if we want to change the password matcher, we can set the password matcher we want for this attribute to realize the replacement.

2. Where to change the matching matcher

We already know where the password matcher is, so do we want to replace it in the class to which this password matcher belongs? Of course it was not written by us. The real replacement place should be done in the custom realm we wrote To replace, we usually set the realm for the security manager. Before setting the realm, we need to change the password matcher, and we also need to tell the realm which encryption algorithm we use. Then our corresponding code should look like this

public class TestAuthenticator2 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        //定义安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //定义一个支持MD5+盐+hash散列的密码匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //告诉密码匹配器密文是哪种加密方式
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //告诉密码匹配器,密码被散列的次数,这个一般定义为1024的倍数,默认一次
        hashedCredentialsMatcher.setHashIterations(1024);
        //定义自己的realm
        SecondRealm secondRealm = new SecondRealm();
        //为realm设置密码匹配器
        secondRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        //为安全管理器设置realm
        defaultSecurityManager.setRealm(secondRealm);
        //模拟用户登录场景
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("zhaoyun","123");
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        try {
    
    
            Subject subject = SecurityUtils.getSubject();
            subject.login(usernamePasswordToken);
            System.out.println("登录成功");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

Now that we have told the security manager that my database stores the ciphertext implemented by MD5+salt+hash, then our realm is incorrectly written as before.

3. Custom realm

When we do not encrypt the password, the realm we simulated obtains the user name and password in plain text and returns it to the password matcher. Then we want to use MD5+salt+hash to implement password encryption. The previous information returns affirmative Will report an error, then how do we write it, please see the following code

public class SecondRealm extends AuthorizingRealm {
    
    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
    
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    
    
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)authenticationToken;
        String userName = usernamePasswordToken.getUsername();
        //获取数据库中的用户信息
//        SimpleAccount simpleAccount = new SimpleAccount("zhaoyun","202cb962ac59075b964b07152d234b70","df",this.getName());
        SimpleAuthenticationInfo simpleAuthenticationInfo = getSimpleInfo();
        //验证用户名与token用户名是否相同
        if(simpleAuthenticationInfo.getPrincipals().asList().contains(userName)){
    
    
            return simpleAuthenticationInfo;
        }else{
    
    
            return  null;
        }
    }

    private SimpleAuthenticationInfo getSimpleInfo(){
    
    
        Md5Hash md5Hash = new Md5Hash("123");
        Md5Hash md5Hash1 = new Md5Hash("123","12345&8");
        Md5Hash md5Hash2 = new Md5Hash("123","12345&8",1024);

        return new SimpleAuthenticationInfo("zhaoyun",md5Hash2, ByteSource.Util.bytes("12345&8"),this.getName());
    }
}

One thing to say, in the previous example, we implemented a custom realm to inherit AuthenticatingRealm. In this example, we are inheriting AuthorizingRealm. One of these two Realms is for authentication and the other is for authorization (the first authentication ), and the AuthorizingRealm used for authorization is a subclass of AhthenticatingRealm, so it is correct that we can directly inherit AuthorizingRealm. Just like the code above, inheriting this class requires us to rewrite the two pieces of code for authentication and authorization. This part of authorization has not been involved yet, let's not talk about it for now, and we will continue to look at the part of authentication.
According to this method SimpleAuthenticationInfo(), we can see that there are three Md5Hash objects written in it. The first one uses only Md5, the second uses a random salt, and the random salt is even a set of random strings, the third The ciphertext produced by MD5+salt+hashing 1024 times is used.
Careful students may find that when we set up the password matcher for realm, we did not tell the ream what the random salt is, only the ciphertext of the password matcher. What kind of encryption method and how many times need to be hashed.

4. How does the password matcher know what the random salt is?

It's actually very simple. When we complete the user name verification, we will return an account information, which is an object of the SimpleAuthenticatingInfo class. This object contains the password, which has been salted. When it reaches the password matcher, it will come and go according to whether the salt is passed. The value of the salt is dynamically obtained without the need for us to directly carry the salt when the user logs in. Moreover, it is extremely insecure that the user logs in with the salt, so we do not need to set the salt for the password matcher.

5. Use MD5+salt+hash to successfully log in

Running the above code we can get the results as follows:

登录成功

Process finished with exit code 0

Interested big guys can try more, here is not a list of other password usage scenarios.

Four. Summary

This article mainly introduces the application scenarios of MD5 when logging in with Shiro. We use MD5+salt+hash to ensure the security of the password to a large extent. In the daily development, in fact, the password is also added to you. This kind of, like the project I was doing a while ago, the front-end interaction uses AES+Base64 for double encryption when encrypting the parameters.

Guess you like

Origin blog.csdn.net/m0_46897923/article/details/114906453