AES简介
AES(Advanced Encryption Standard)高级加密标准,是一种被广泛使用的对称加密算法,用于加密和解密数据。它曾经是美国政府的一个机密标准,但现在已成为公开的加密算法,并被广泛使用于商业、政府及军事领域。
AES算法有三种不同的密钥长度:128位、192位和256位,每种长度有不同数量的轮数,其中128位密钥需要进行10轮加密,192位密钥需要进行12轮加密,256位密钥需要进行14轮加密。其中,轮数指的是加密算法中处理数据的重复次数,每轮中会对数据进行代换、置换、线性变换等操作,以增强加密强度。
AES算法的加密和解密过程使用的是相同的密钥,因此被称为对称密钥加密算法。它通过将明文按照固定大小分块(128比特),并对每个块进行相同的加密操作,从而实现加密。解密时则对密文进行反向操作即可。
总体来说,AES算法具有安全、高效等优势,已成为目前最常用的加密算法之一。
一、示例
1.加密解密工具类
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
/**
* @author rwy
* @Title:
* @Package
* @Description:
* @date 2023-11-22 15:37
*/
@Component
public class AESEncryption {
//十六位十六进制数作为秘钥(下面有提供随机生成密钥)
private static final String SECRET_KEY = "mySecretKey123456";
//十六位十六进制数作为秘钥偏移量(可以和前端自行商量)
private static final String INIT_VECTOR = "myInitializationVector";
/**
* AES加密
* @param originalString
* @return
* @throws Exception
*/
public static String encrypt(String originalString) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encryptedBytes = cipher.doFinal(originalString.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
}
/**
* AES解密
* @param encryptedString
* @return
* @throws Exception
*/
public static String decrypt(String encryptedString) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedString));
return new String(decryptedBytes);
}
public static void main(String[] args) {
try {
String originalString = "Hello, World!";
String encryptedString = encrypt(originalString);
System.out.println("Encrypted: " + encryptedString);
String decryptedString = decrypt(encryptedString);
System.out.println("Decrypted: " + decryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.AES随机生成密钥
public static void main(String[] args) {
try {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
//要生成多少位,只需要修改这里即可128, 192或256
SecretKey sk = kg.generateKey();
byte[] b = sk.getEncoded();
String s = byteToHexString(b);
System.out.println(s);
System.out.println("十六进制密钥长度为"+s.length());
System.out.println("二进制密钥的长度为"+s.length()*4);
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println("没有此算法。");
}
}
public static String byteToHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String strHex=Integer.toHexString(bytes[i]);
if(strHex.length() > 3) {
sb.append(strHex.substring(6));
} else {
if(strHex.length() < 2) {
sb.append("0" + strHex);
} else {
sb.append(strHex);
}
}
}
return sb.toString();
}
二、登录实战完整代码
1.前端:
这里前端传过来的密码是加密过后
前端加密解密可参考:
vue MD5加密和AES加密方法_vue 加密_IDycy的博客-CSDN博客
2.后端
/**
* 账号密码登录
* @param user
* @return
* @throws Exception
*/
@PostMapping("/cs")
public Result<JSONObject> login(@RequestBody SysUser user) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsername, user.getUsername());
SysUser sysUser = sysUserService.getOne(queryWrapper);
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
return result;
}
//1. 解密前端传过来的加密的密码
String decryptAse = aesEncryption(user.getPassword());
//2. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(user.getUsername(), decryptAse, sysUser.getSalt());
String syspassword = sysUser.getPassword();
if (!syspassword.equals(userpassword)) {
result.error500("用户名或密码错误");
return result;
}
//以下代码忽略...
return result;
}