密码加密方式:MD5加密 & 盐值加密

在我们项目开发中,对于密码的存储都会进行加密处理,我们可以自定义一个加密方式进行加解密后的字符串对比,也可以使用我们的md5加密(不可逆)。

	//常用的MD5加密
     String s = DigestUtils.md5Hex("123456");
     System.out.println(s);

运行结果:

e10adc3949ba59abbe56e057f20f883e
  • MD5 经过摘要算法加密可以将任何长度的字符串转化成固定长度大小,无论加密前的字符串多大,即便是1G的数据,经过MD5摘要加密后可以得到一个固定长度字符串。举个应用的例子,当我们使用云盘的快传功能时,即使是上传10G的数据,有时也会秒传,原因就是快传时并没有真正上传数据,因为云盘后台经过MD5 的 摘要算法计算获得 了一个值,且这个值在其他上传信息中已经出现过了,所以证明资源已存在,所以直接可以把地址对应的位置进行存储即可,这就是快传的基本实现。

说了这莫多,那MD5 存储密码会不会有什么问题呢?我们来看一下这个网站:
https://www.cmd5.com/
在这里插入图片描述
我们先把123456进行MD5加密,然后把加密后的串来这里解密,居然出来了?对于常见的密码,都会有被破解的风险。那么可能你会问,不是说MD5不可逆吗,它是如何计算出来的?其实它并没有计算,只不过它经过长时间的随机计算,且一直在积累数据,存储了大量的 key->value 对应值,也就是
e10adc3949ba59abbe56e057f20f883e - > 123456 ,这个可以被称为彩虹表,正是因为这样,我们进行搜索时可以得到 value 的值 123456 。那我们该如何避免被破解呢?首先最简单的方式:密码长度长一些,且包含特殊字符,包含大小字母 的复杂密码,还有一种办法就是 盐值密码。

盐值:所谓盐值,可以理解为 我们炒菜时,随机撒了一把盐,那你能记得撒了多少克的盐吗? 额… 当然,这指是我的理解。其实实现的方式 是给 密码生成MD5时加一个随机数,如这样:

	//盐值加密
	System.out.println("默认盐:"+Md5Crypt.md5Crypt("123456".getBytes()));//随机盐值加密
	System.out.println("自定义盐:"Md5Crypt.md5Crypt("123456".getBytes(),"$1$qqqqqqqq"));//自定义盐值加密

结果:

默认盐:$1$WNQC2GY5$Yxw4ghncpwfqEN/zRz3LX0

自定义盐:$1$qqqqqqqq$AZofg3QwurbxV3KEOzwuI1

我们可以看到,默认盐是“ $1$WNQC2GY5 ” ,也就是 ‘$1$’和前八位 “WNQC2GY5” 。
自定义盐是:"$1$qqqqqqqq"。
这样可以增加破解的困难度,但是我们存储的方式也要进行改变,因为每次这只密码后,我们都要对盐值进行存储。那有没有简单的方式呢,其实spring 已经为我们准备好了,下面来看项目中的实际应用:

        //1. spring 提供的盐值加密
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //2.将传来的密码进行盐值加密,并获得加密串
        String encode = bCryptPasswordEncoder.encode("123456");
        //3.对比盐值密码,并获得布尔值
        boolean matches = bCryptPasswordEncoder.matches("123456", "$2a$10$GT0TjB5YK5Vx77Y.2N7hkuYZtYAjZjMlE6NWGE2Aar/7pk/Rmhf8S");

        System.out.println(encode+" ==> " + matches);

运行结果:

$2a$10$0FPQNmKW/KAH/2vZhQwxkeNmM.bnY7xu6RCBhds8sXV6KV6FOfCZa ==> true

Guess you like

Origin blog.csdn.net/YL3126/article/details/120373338