1.为什么使用加盐算法
1.我们都知道明文是不安全的
2.MD5加密的密码是有规律可循的,因为所有固定的字符都会有固定的 MD5,因此如果有一个库(彩虹库{字符 | 字符的MD5 })带有所有的字符和字符的MD5,就可以破解所有的MD5加密了.
3.因此,加盐算法:使用一个不重复随机的盐值(UUID) +密码 =无规律的密码
2.实现步骤
- 生成一个盐值(UUID)
- (根据盐值(UUID)+固定密码) 进行加密 ->MD5(盐值+密码) =最终密码
- 将 [盐值] +[分隔符 ($)] +最终密码 存入数据库
代码实现:
//加盐加密 public static String encrypt(String password){ //1.生成盐值 String salt= UUID.randomUUID().toString().replace("-",""); //2.将盐值+密码 进行MD5加密 得到最终密码 String finalPassword= DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8)); //3.将盐值和最终密码进行返回 return salt+"$"+finalPassword; }
注意:
- salt+password的顺序不能反.要么是这个salt+password顺序,要么是这个password+salt
- salt 的长度是 32位. UUID是由32位字符加4个分隔符 ("-") 组成的.由于repalce去掉了分隔符,因此就剩32位了.
UUID 的格式:
123e4567-e89b-12d3-a456-556642440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxxMD5加密的得到的密码是32位的,因此finalPassword是32位的.
最终返回的密码是 32+1('$'分隔符)+32=65位.也就是说最终返回的密码一定是65位的.
3.加密验证步骤
由于MD5加密是不可逆的
1.因此我们需要将待验证的密码按照之前的加密手段进行一次同轨迹的加密.(这也就是为什么之前要将盐值跟最终密码一起添加到数据库中)
2.然后判断和数据库里的最终密码是否相同.
步骤:
- 得到盐值
- MD5(盐值+待验证密码) ->最终待验证的密码
- 对比最终验证的密码和数据中的最终密码是否相同 -> 相同密码正确
代码实现:
public static boolean decrypt(String password,String dbPassword) { //判断密码和最终密码是否为空 //判断最终密码是否为65位(最终密码一定是65位,不是就有问题) if (!StringUtils.hasLength(password) || !StringUtils.hasLength(dbPassword) ||dbPassword.length() != 65) { return false; } String[] dbPasswordArray = dbPassword.split("\\$");//需要将$转义 if (dbPasswordArray.length != 2) { return false; } //得到盐值 String salt = dbPasswordArray[0]; //得到正确密码 String dbFinalPassword = dbPasswordArray[1]; //加密待验证的密码 String finalPassword = DigestUtils.md5DigestAsHex((salt + password) .getBytes(StandardCharsets.UTF_8)); //对比 if (dbFinalPassword.equals(finalPassword)) { return true; } return false; }
4.全部代码
public class PasswordUtils {
public static String encrypt(String password){
String salt= UUID.randomUUID().toString().replace("-","");
StringfinalPassword=
DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
return salt+"$"+finalPassword;
}
public static boolean decrypt(String password,String dbPassword) {
if (!StringUtils.hasLength(password) || !StringUtils.hasLength(dbPassword) ||
dbPassword.length() != 65) {
return false;
}
String[] dbPasswordArray = dbPassword.split("\\$");
if (dbPasswordArray.length != 2) {
return false;
}
String salt = dbPasswordArray[0];
String dbFinalPassword = dbPasswordArray[1];
String finalPassword = DigestUtils.md5DigestAsHex((salt + password)
.getBytes(StandardCharsets.UTF_8));
if (dbFinalPassword.equals(finalPassword)) {
return true;
}
return false;
}
}