一.BCrypt基础
在一个项目中,只要涉及用户的登陆注册,就涉及到用户密码的保护,用户的密码存在数据库是对管理员是透明的,所以为了防止管理员泄露密码,提高用户密码的安全性,我们通常会对用户密码进行加密后再存入数据库,目前MD5与Bcrypt使用比较多,都不可反向破解生成明文。但任何长度的密码使用MD5加密后长度都是相同的,固定的。而且一个密码使用MD5加密生成的密文唯一。那我就可以记下所有明文使用MD5加密后的密文,解密使用穷举就可以破解。MD5解密网站:https://www.bejson.com/enc/md5/
Bcrypt是单向Hash加密算法,首先我们来了解下Bcrypt加密过程
Bcrypt有四个变量:
- count: 正数,代表hash杂凑次数,数值越高越安全,可以使用Random随机生成次数
- password: 明文密码字符串。
- gensalt: 盐是一个随机生成的含有22个字符的字符串,并且会与密码一起合并进行最终的密文生成
并且每一次生成的盐的值都是不同的
- saltPassword: 经过明文密码password和盐gensalt进行count次数的hash得到saltPassword密文
每次明文字符串password过来,就通过count次循环加盐gensalt加密后得到saltPassword, 然后拼接BCrypt版本号+gensalt盐+saltPassword等到最终的bcrypt密码 ,存入数据库中。
因为Bcrypt加密每次每一次生成的盐的值都不同,count循环次数也不同,
所以一个密码可能生成多个不同的密文,那我想要破解难度就大了,比如MD5加密123456生成一个明文,Bcrypt加密123456生成N个明文,那我要记下来的存储成本就大多了。
bcrypt一个密码出来的时间比较长,需要0.3秒,而MD5只需要一微秒(百万分之一秒),一个40秒可以穷举得到明文的MD5,在bcrypt需要12年-----摘自
https://coolshell.cn/articles/2078.html
二.BCrypt快速入门
(1)新建测试类,main方法中编写代码,实现对密码的加密
public class TestBcrypt {
public static void main(String[] args) {
/**
* 得到盐
* 盐是一个随机生成的含有29个字符的字符串,并且会与密码一起合并进行最终的密文生成
* 并且每一次生成的盐的值都是不同的
*/
for(int i=0;i<10;i++){
String gensalt = BCrypt.gensalt();
System.out.println("salt:"+gensalt);
String saltPassword = BCrypt.hashpw("123456", gensalt);
System.out.println("本次生成的密码:"+saltPassword);
}
}
}
(2)main方法中编写代码,实现对密码的校验。BCrypt不支持反运算,只支持密码校验。
//校验密码
boolean checkpw = BCrypt.checkpw("123456", saltPassword);
System.out.println("密码校验结果:"+checkpw);