在使用AES加密时要注意指定字符编码,要使用String.getBypes(String charsetName)而不能使用String.getBytes(),后者源码中有一句:
String csn = Charset.defaultCharset().name();
Charset.defaultCharset()返回此Java虚拟机的默认字符集。
默认字符集在虚拟机启动期间确定,通常取决于基础操作系统的区域设置和字符集。
如果在加密和解密过程中环境发生变化,就可能导致中文字符解密后出现乱码
import lombok.SneakyThrows;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.SecureRandom;
public class AesUtil {
/**
* 加密算法名称
*/
private static final String CIPHER_ALGORITHM = "AES";
/**
* 密钥
*/
private static final String KEY = "123456";
/**
*获取密钥Key
*/
public static Key getKey(String strKey) {
try {
if (strKey == null) {
strKey = "";
}
KeyGenerator generator = KeyGenerator.getInstance(CIPHER_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(strKey.getBytes());
generator.init(128, secureRandom);
return generator.generateKey();
} catch (Exception e) {
throw new RuntimeException(" 密钥出现异常 ");
}
}
/**
* AES加密
* @param data 原文
* @return 密文
*/
@SneakyThrows
public static String encrypt(String data){
if(StringUtils.isEmpty(data)){
return data;
}
SecureRandom secureRandom = new SecureRandom();
Key secureKey = getKey(KEY);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secureKey, secureRandom);
//这里需要指定编码,否则可能因环境问题出现解密乱码
byte[] bytes = data.getBytes("utf-8");
byte[] bt = cipher.doFinal(bytes);
//加密后以base64编码后存储,这里使用的是Spring的Base64Utils
String string = Base64Utils.encodeToString(bt);
return string;
}
/**
* AES解密
* @param message 密文
* @return 原文
*/
@SneakyThrows
public static String decrypt(String message){
if(StringUtils.isEmpty(message)){
return message;
}
SecureRandom secureRandom = new SecureRandom();
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
Key secureKey = getKey(KEY);
cipher.init(Cipher.DECRYPT_MODE, secureKey, secureRandom);
//先base64解码,这里使用的是Spring的Base64Utils
byte[] bytes = Base64Utils.decodeFromString(message);
byte[] res = cipher.doFinal(bytes);
//这里需要指定编码,否则可能因环境问题出现解密乱码
String data = new String(res,"utf-8");
return data;
}
/**
*测试
*/
public static void main(String[] args) {
String message = "北京是中华人民共和国首都";
System.out.println("原文信息:"+message);
System.out.println("原文长度:"+message.length());
//加密
String encryptMsg = encrypt(message);
System.out.println("加密信息:"+encryptMsg);
System.out.println("密文长度:"+encryptMsg.length());
//解密
String decryptedMsg = decrypt(encryptMsg);
System.out.println("解密信息:"+decryptedMsg);
//验证解密信息和原文是否相等
System.out.println(message.equals(decryptedMsg));
}
}