加密算法(MD5加密、MD5Hash加密、BCrypt加密)

1 MD5加密介绍

  1. MD5是一个加密的算法,可以对明文字符串进行加密,得到一个密文。
  2. MD5原文和密文是一对一的键值对。
  1. 例如:原文:123 密文:202cb962ac59075b964b07152d234b70

  2. 不管执行多少次,加密算法是固定的,得到的密文永远不变

  3. 相对来说就不安全,容易被破解

  1. 公司中使用MD5进行加密
  1. 例如:原文密码是123,把首尾交换,再加上用户名进行加密

  2. 例如:321meimei 进行加密e5212215b8cbf493e04f4290cf7cecc8

  3. 这样做相对来说会安全

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 加密加盐

使用Shiro框架进行加密,我们直接测试:

第一步:添加依赖

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

第二步:写测试类

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 Spring提供的高级加密

因为BCryptPasswordEncoder加密的来源就是spring security中的一部分 ,所以要引入spring security依赖

		 <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);

    }
}

猜你喜欢

转载自blog.csdn.net/qq_45850872/article/details/109126181