密码算法简介
1.对称加密算法:加密和解密算法一样
2.非对称加密算法:公钥加密、私钥解密
3.摘要算法:不能解密,不可逆
简单介绍了解一下:
一、对称密码算法
是指加密秘钥和解密秘钥相同的密码算法. 常见的对称密码算法有: AES, DES, 3DES,RC4, RC5, RC6 等.
二、非对称密码算法是指加密秘钥和解密秘钥不同的密码算法. 该算法使⽤⼀个秘钥进行加密, 用另外一个秘钥进行解密.
加密秘钥可以公开,又称为 公钥
解密秘钥必须保密,又称为 私钥
常见的非对称密码算法有: RSA, DSA, ECDSA, ECC 等
三、摘要算法1.任意长度的输入消息数据转化为固定长度的输出数据的一种密码算法.。
2.摘要算法是不可逆的, 也就是无法解密.。
通常用来检验数据的完整性的重要技术, 即对数据进行哈希计算然后比较摘要值,,判断是否一致。
常见的摘要算法有: MD5, SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16,CRC32)
一、MD5摘要算法(非常简单的加密方式)
我们的博客系统采用摘要算法 MD5 进行操作。
其实严格来说摘要算法 主要是做校验使用。
明文 -> 摘要算法 → 另外字符串
接收到的明文 -> 摘要算法 → 另外字符串
如果两个字符串相等。救认为接收到的明文是正确的。
特点
1.不可逆
2.不同长度的字符串,经过MD5之后。得到字符串长度相同。
3.相同的字符串,经过MD5处理后。得到的字符串是相同的。(无论什么语言、什么平台实现)
有些网站会对MD5解密。(对于简单字符串)
因此我们在原始明文密码上。加上一个随机的盐值(相对复杂)。之后(明文+盐值)这个字符串就无法进行解密了。
盐值(salt)
盐值:就是相对复杂的字符串。
加密逻辑:明文 + 盐值 = 复杂的明文 再通过MD5进行加密 → 得到密文
校验逻辑:
(用户输入的明文+盐值) 通过MD5进行加密 → 得到密文
如果这两个密文相同。就认为用户输入的明文和注册时的明文密码是相同的。
数据库需要保存 :盐值和密文
验证方式:
待验证的明文+这个随机盐值,进行MD5加密。和数据库的密文进行对比。
实现步骤:
一、用户注册
1.生成随机盐值
2.用户明文密码+随机盐值,通过MD5进行加密。
3.保存 随机盐值 和密文。
二、用户登录
1.获取用户注册时的随机盐值
2.待验证的明文+第一步的随机盐值,通过MD5进行加密
3.判断第二步的密文和用户注册时数据库中存的密文是否一样。
UUID
不会重复
通常是和userId对应。但并不完全。
UUID是根据设备来的。
一个userId可能有多个UUID
System.out.println(UUID.randomUUID());
打印示例:
3c7719cd-b790-40c8-abb9-49a5545574dd
二、MD5使用示例
2.1 得到密文
数据库中存储(盐值+密文)
/*** 得到密文*/@Testpublic void encrypt(){String password = "123456";//明文String md5Str = DigestUtils.md5DigestAsHex(password.getBytes());//对字符串 password 进行 MD5 加密//并将结果转换为一个 32 位的十六进制字符串//将字符串 password 转换为字节数组。System.out.println(md5Str);String salt = UUID.randomUUID().toString().replace("-","");System.out.println(salt);//得到盐值// .toString(): 将UUID 转换为字符串。//.replace("-", ""):去掉字符串中的所有连字符(-),使生成的盐值成为一个连续的字符串。String securityPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());//得到密文String finalPassword = salt +securityPassword;System.out.println(finalPassword);//最终数据库存储的内容}
2.2解密校验
/*** 解密*/@Testpublic void verify(){String inputPassword ="123456";String sqlPassword = "587bd5b3bf7f42ca9e0bce3da50e516f9096e954d0eb8ff2bd68e8b87c49afc6";//sqlPassword 是 salt + md5(salt + md5(salt_password))if(sqlPassword == null || sqlPassword.length()!=64){System.out.println("校验失败");}String salt = sqlPassword.substring(0,32);String secretPassword = DigestUtils.md5DigestAsHex((salt + inputPassword).getBytes());String findPassword = salt +secretPassword;if(findPassword.equals(sqlPassword)){System.out.println("校验成功");}else {System.out.println("校验失败!");}}
三、将MD5加密应用到博客系统
在utils包中创建SecurityUtils类
3.1.根据明文进行加密
public static String encrypt(String password){String md5Str = DigestUtils.md5DigestAsHex(password.getBytes());String salt = UUID.randomUUID().toString().replace("-","");String securityPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());return salt+securityPassword;}
3.2密码校验
public static boolean verify(String inputPassword,String sqlPassword){if(sqlPassword == null || sqlPassword.length()!=64){log.error("数据库中密码格式错误!");return false;}String salt = sqlPassword.substring(0,32);String secretPassword = DigestUtils.md5DigestAsHex((salt + inputPassword).getBytes());return sqlPassword.equals(salt+secretPassword);}
3.3更改UserController类
@RequestMapping("/login")public Result login(String userName, String password){//1.参数校验//2.对密码进行校验//3.如果校验成功,生成tokenif(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){return Result.fail("用户名或密码不能为空!");}UserInfo userInfo = userService.queryUserByName(userName);if(userInfo == null || userInfo.getId() <= 0){return Result.fail("用户不存在");}
// if(!password.equals(userInfo.getPassword())){
// return Result.fail("密码错误!");
// }if(!SecurityUtils.verify(password,userInfo.getPassword())){return Result.fail("密码错误!");}//密码正确Map<String,Object> claim = new HashMap<>();claim.put(Constant.USER_CLAIM_Id,userInfo.getId());claim.put(Constant.USER_CLAIM_NAME,userInfo.getUserName());return Result.success(JWTUtils.gentToken(claim));}
3.4修改数据库中的密码
通过之前测试类中我们生成的findPassword。将他替换数据库中的密码。
密码都是123456。
但是在数据库中,我们是看不出来的
常见错误:
1.加密和校验的逻辑不一样。
数据库中存储的信息是(盐值+md5(salt+明文))。
注意 盐值 和 密文的 顺序。
2.数据库忘了修改密码
3.数据库中只存储了加密后的信息