Encryption algorithm (MD5 encryption, MD5Hash encryption, BCrypt encryption)

1 Introduction to MD5 encryption

  1. MD5 is an encryption algorithm that can encrypt a plain text string to obtain a cipher text.
  2. MD5 original text and cipher text are one-to-one key-value pairs.
  1. For example: original text: 123 cipher text: 202cb962ac59075b964b07152d234b70

  2. No matter how many times it is executed, the encryption algorithm is fixed, and the ciphertext obtained will never change

  3. Relatively insecure, easy to crack

  1. Use MD5 for encryption in the company
  1. For example: the original password is 123, exchange the beginning and end, plus the user name for encryption

  2. For example: 321meimei for encryption e5212215b8cbf493e04f4290cf7cecc8

  3. This is relatively safe

package com.itheima.travel.util;

import java.security.MessageDigest;

/**
 * 写一个MD5算法,运行结果与MySQL的md5()函数相同
 * 将明文密码转成MD5密码
 * 123456->e10adc3949ba59abbe56e057f20f883e
 */
public final class Md5Util {
    
    
	private Md5Util(){
    
    }
	/**
	 * 将明文密码转成MD5密码 
	 */
	public static String encodeByMd5(String password) throws Exception{
    
    
		//Java中MessageDigest类封装了MD5和SHA算法,今天我们只要MD5算法
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		//调用MD5算法,即返回16个byte类型的值
		byte[] byteArray = md5.digest(password.getBytes());
		//注意:MessageDigest只能将String转成byte[],接下来的事情,由我们程序员来完成
		return byteArrayToHexString(byteArray);
	}
	/**
	 * 将byte[]转在16进制字符串 
	 */
	private static String byteArrayToHexString(byte[] byteArray) {
    
    
		StringBuffer sb = new StringBuffer();
		//遍历
		for(byte b : byteArray){
    
    //16次
			//取出每一个byte类型,进行转换
			String hex = byteToHexString(b);
			//将转换后的值放入StringBuffer中
			sb.append(hex);
		}
		return sb.toString();
	}
	/**
	 * 将byte转在16进制字符串 
	 */
	private static String byteToHexString(byte b) {
    
    //-31转成e1,10转成0a,。。。
		//将byte类型赋给int类型
		int n = b;
		//如果n是负数
		if(n < 0){
    
    
			//转正数
			//-31的16进制数,等价于求225的16进制数 
			n = 256 + n;
		}
		//商(14),数组的下标
		int d1 = n / 16;
		//余(1),数组的下标
		int d2 = n % 16;
		//通过下标取值
		return hex[d1] + hex[d2];
	}
	private static String[] hex = {
    
    "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
	/**
	 * 测试
	 */
	public static void main(String[] args) throws Exception{
    
    
		String password = "123456";
		String passwordMD5 = Md5Util.encodeByMd5(password);
		System.out.println(password);
		System.out.println(passwordMD5);
	}
}

2 Md5Hash encryption and salt

Using Shiro framework for encryption, we directly test:

The first step: add dependencies

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.3.2</version>
        </dependency>

Step 2: Write the test class

package com.itheima;

import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;

public class App {
    
    

    // (1) md5 加密,生成32位加密字符串
    @Test
    public void md5_1(){
    
    
        Md5Hash md5Hash = new Md5Hash("1234");
        System.out.println("加密:" + md5Hash.toString());
    }

    // (2) 加密加盐
    @Test
    public void md5_2(){
    
    
        String salt = "AAA";
        Md5Hash md5Hash = new Md5Hash("1234",salt);
        System.out.println(md5Hash);
    }

    // (3) 加密 加盐 随机盐
    @Test
    public void md5_3(){
    
    
        // 随机盐
        SecureRandomNumberGenerator srn = new SecureRandomNumberGenerator();
        String salt = srn.nextBytes().toHex();

        Md5Hash md5Hash = new Md5Hash("1234",salt);
        System.out.println(md5Hash.toString());
    }

    // (4) 加密 加盐 随机盐 迭代次数
    @Test
    public void md5_4(){
    
    
        // 随机盐
        SecureRandomNumberGenerator srn = new SecureRandomNumberGenerator();
        String salt = srn.nextBytes().toHex();

        Md5Hash md5Hash = new Md5Hash("1234",salt,3);// 迭代3次
        System.out.println(md5Hash.toString());
    }
}


3 Advanced encryption provided by Spring

Because the source of BCryptPasswordEncoder encryption is part of spring security, spring security dependencies must be introduced

		 <dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
		</dependency>
 
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
		</dependency>
package com.itheima;

import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
 * spring security中的BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥对密码进行加密。
 * SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(这个与编码/解码一样),
 * 但是采用Hash处理,其过程是不可逆的。
 *
 * (1)加密(encode):注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,
 *     得到密码的hash值,然后将其存入数据库中。
 *
 * (2)密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),
 *     而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,
 *     然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。
 */
public class App {
    
    
    @Test
    public void test(){
    
    
        // 加密器
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String str = encoder.encode("123");
        System.out.println(str);
        // 加密的结果每次不一样
        //r1 = $2a$10$I4XP9//KH5GsPt059YmikuZJl0FUR6HQYSRa/J4UrOwKWmnlEh97G
        //r1 = $2a$10$l3ki2psVSi91CWPpYXQRm.J3156djwwCyGI.7YGnjscOcxeAwQS6C
        //r1 = $2a$10$gpTfkWpAtmSQywBepw3XU.aPX.zWzeauUoU7s8FVg9xPIXPLJIQCi

        // 对比:加密前的123,与加密后的r1分别对比,返回的结果都是true.说明是一样的
        boolean flag =
                encoder.matches("123","$2a$10$gpTfkWpAtmSQywBepw3XU.aPX.zWzeauUoU7s8FVg9xPIXPLJIQCi");
        System.out.println(flag);

    }
}

Guess you like

Origin blog.csdn.net/qq_45850872/article/details/109126181