SpringBoot开发-数据加密
提示:本篇文章介绍各种加密工具以及数据脱密工具的使用
文章目录
- 前言
- 一、AES加密算法
- 二、AES加密算法工具使用
- (一)引入依赖
- (二)编写工具类
- (三)测试
- 三、MD5加密算法
- 四、MD5加密工具使用
- (一)编写工具类
- (二) 测试类
- (三)测试
- (四)MD5加随机盐
- (1)MD5+盐工具类
- (2)测试
- 五、脱密处理
- (一)正则表达式对数据做脱敏处理
- (二)测试
- 总结
前言
在开发过程中,考虑到数据安全性问题,我们经常会将一些敏感的数据进行加密,例如用户的密码,身份证,等信息进行加密,对用户手机号银行卡等信息进行脱敏处理,防止系统用户信息泄露。
一、AES加密算法
AES(英语全称:Advanced Encryption Standard,中文名称:高级加密标准)。是一种对称加密算法,广泛用于保护数据的安全性。它由美国国家标准技术局(NIST)于2001年采用,取代了以前的 DES(数据加密标准)。
对称加密算法:意味着加密和解密使用相同的密钥。
主要特点:
对称加密:加密和解密使用相同的密钥。
支持多种密钥长度:可使用 128、192 或 256 位密钥,长度越长,安全性越高。
块加密:以 128 位为块进行加密。
安全性高:目前被认为是非常安全,广泛应用于金融、政府和商业领域。
工作模式:
AES 可与多种工作模式结合使用,例如:
ECB(电子密码本):简单但不安全,容易受到攻击。
CBC(密码块链接):更安全,使用初始向量(IV)来增强安全性。
GCM(伽罗瓦计数模式):提供认证和加密,适用于网络通信。
应用场景:
数据库加密
文件加密
VPN 和 SSL/TLS 通信
AES 在线工具 https://tool.hiofd.com/aes-encrypt-online/
二、AES加密算法工具使用
(一)引入依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
(二)编写工具类
public class EncryptionUtil {
private static final String SECRET_KEY = "MD_AES256";//秘钥自己设置
public static String encrypt(String data) {
AES256TextEncryptor encryptor = new AES256TextEncryptor();
encryptor.setPassword(SECRET_KEY);
return encryptor.encrypt(data);
}
public static String decrypt(String encryptedData) {
AES256TextEncryptor encryptor = new AES256TextEncryptor();
encryptor.setPassword(SECRET_KEY);
return encryptor.decrypt(encryptedData);
}
}
(三)测试
新增用户时,对用户输入密码进行加密
@PostMapping("/add")
public boolean add(@RequestBody User user){
// 对用户密码加密
String encryptedPassword = EncryptionUtil.encrypt(user.getPassword());
user.setPassword(encryptedPassword);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
return userService.save(user);
}
查询用户时,查询密码是否解密成功(这里只是为了演示,实际开发中部展示用户密码的)
@GetMapping("/list")
public List<User> list(){
List<User> userList = userService.list();
//查看用户密码是否解密成功
userList.stream().forEach(user ->
user.setPassword(EncryptionUtil.decrypt(user.getPassword())));
return userList;
}
PostMan 添加一个用户
查看数据库中,用户密码保存后是否加密了
查询用户信息,查看解密后的密码
当我们再次加入一个用户,用户密码依然是 123456,我们查看加密效果
三、MD5加密算法
MD5(Message-Digest Algorithm 5)是一种广泛使用的加密哈希函数,它将任意长度的输入数据转换为固定长度的 128 位(16 字节)哈希值。其主要特点包括:
单向性:MD5 是单向函数,不能从哈希值逆向计算出原始输入。
固定输出:无论输入数据大小如何,MD5 始终生成相同长度的哈希值。
快速计算:MD5 可以迅速处理数据并生成哈希值。
碰撞性:理论上,两个不同的输入可以产生相同的哈希值,这种现象称为碰撞。由于 MD5 的安全性问题,已经不再推荐用于加密敏感数据。
四、MD5加密工具使用
(一)编写工具类
public class MD5Util {
public static String encrypt(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
(二) 测试类
@PostMapping("/add")
public boolean add(@RequestBody User user){
// 对用户密码加密(MD5加密)
String encryptedPassword = MD5Util.encrypt(user.getPassword());
user.setPassword(encryptedPassword);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
return userService.save(user);
}
从结果上看,如果两个相同用户输入密码一致,那么他们加密后的结果是一致
(三)测试
测试使用MD5加密的两个用户密码是否为123456
@Test
public void testUserPassword(){
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, "王二麻子"));
String password = user.getPassword();
String testPassword = MD5Util.encrypt("123456");
if(password.equals(testPassword)){
System.out.println("密码正确");
}else {
System.out.println("密码错误");
}
}
输出结果是:密码正确
(四)MD5加随机盐
从以上MD5加密我们可以看出,MD5加密如果用户输入密码相同,加密后的密文是相同,MD5可以通过穷举暴力破解,因此有了随机盐概念,将用户输入的密码+系统随机生成字符串一同加密,这样可以增加密文的安全性
(1)MD5+盐工具类
public class MD5Util {
//生成随机盐
public static byte[] generateSale(){
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[16];
secureRandom.nextBytes(salt);
return salt;
}
public static String encrypt(String password, byte[] salt) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(salt); // 加入盐
md.update(password.getBytes()); // 加入密码
byte[] hashedPassword = md.digest();
return Base64.getEncoder().encodeToString(hashedPassword); // 以 Base64 格式返回哈希值
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
(2)测试
@PostMapping("/add")
public boolean add(@RequestBody User user){
//生成随机盐
byte[] salt = MD5Util.generateSale();
user.setSalt(Base64.getEncoder().encodeToString(salt));
// 对用户密码加密(MD5+随机盐)
String encryptedPassword = MD5Util.encrypt(user.getPassword(),salt);
user.setPassword(encryptedPassword);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
return userService.save(user);
}
@PostMapping("/add")
public boolean add(@RequestBody User user){
//生成随机盐
byte[] salt = MD5Util.generateSale();
user.setSalt(Base64.getEncoder().encodeToString(salt));
// 对用户密码加密(MD5+随机盐)
String encryptedPassword = MD5Util.encrypt(user.getPassword(),salt);
user.setPassword(encryptedPassword);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
return userService.save(user);
}
之后比较用户密码很简单,将随机盐从数据库中查询出来加上用户输入的密码一起加密与数据库用户密码进行比较即可
@Test
public void testUserPassword(){
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, "虞姬"));
byte[] salt = Base64.getDecoder().decode(user.getSalt());
String password = user.getPassword();
String testPassword = MD5Util.encrypt("123456",salt);
if(password.equals(testPassword)){
System.out.println("密码正确");
}else {
System.out.println("密码错误");
}
}
五、脱密处理
除了对数据的加密外,我们还可以对数据展示做一些脱敏处理
(一)正则表达式对数据做脱敏处理
public class DesensitizationUtil {
// 对手机号进行脱敏
public static String maskPhoneNumber(String phoneNumber){
return phoneNumber.replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
}
// 对身份证进行脱敏
public static String maskIdCard(String idCard){
return idCard.replaceAll("(\\d{4})\\d{10}(\\w{4})","$1**********$2");
}
// 对银行卡号进行脱敏
public static String maskBankCard(String bankCard){
return bankCard.replaceAll("(\\d{4})\\d{10}(\\d{4})","$1**********$2");
}
}
(二)测试
@GetMapping("/list")
public List<User> list(){
List<User> userList = userService.list();
//查看用户密码是否解密成功
userList.forEach(user -> {
user.setPassword(EncryptionUtil.decrypt(user.getPassword()));
user.setPhoneNum(DesensitizationUtil.maskPhoneNumber(user.getPhoneNum()));
user.setIdCard(DesensitizationUtil.maskIdCard(user.getIdCard()));
});
return userList;
}
总结
以上就是基本加密方法使用,如果想要项目使用多种加密方式,可以导入Hutool工具包,Hutool工具包包含了以上的加密工具