package com.dj.springtest.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
/**
* User: ldj
* Date: 2023/8/13
* Time: 16:16
* Description: AES 对称机密工具 ECB/CBC
*/
@Slf4j
public class AesUtil {
public static void main(String[] args) throws Exception {
String content = "ldj*^$#_999";
System.out.println("需加密的字符串:" + content);
String encryptStr = AesUtil.encrypt(content);
System.out.println("ECB--加密后的字符串:" + encryptStr);
String DeString = AesUtil.decrypt(encryptStr);
System.out.println("ECB--解密后的字符串:" + DeString);
System.out.println("===========================================");
//测试偏移量
String encryptContent = AesUtil.encrypt(content, "0123456789abcdef", EncryptType.CBC_MODEL);
System.out.println("CBC--加密后的字符串:" + encryptContent);
String decryptContent = AesUtil.decrypt(encryptContent, "0123456789abcdef", EncryptType.CBC_MODEL);
System.out.println("CBC--解密后的字符串:" + decryptContent);
}
/**
* 加密类型
*/
private static final String AES = "AES";
/**
* 16位加密密钥
*/
private static final String SECRET_KEY = "0123456789abcdef";
/**
* 偏移量
*/
public static final String VIPARA = "1234567890xxxyyy";
/**
* 注: 算法/加密模式/补码方式
* 1. 加密的类型(如AES,DES,RC2等)
* 2. 模式(AES中包含ECB,CBC,CFB,CTR,CTS等) 这里只关注ECB,CBC两种
* 3. 补码方式(包含nopadding/PKCS5Padding等等)
*/
static class EncryptType {
public static final String ECB_MODEL = "AES/ECB/PKCS5Padding";
public static final String CBC_MODEL = "AES/CBC/PKCS5Padding";
}
//ECB加密
public static String encrypt(String content) throws Exception {
return encrypt(content, SECRET_KEY, null);
}
//ECB解密
public static String decrypt(String encryptStr) throws Exception {
return decrypt(encryptStr, SECRET_KEY, null);
}
/**
* 加密
*
* @param content 需加密的字符串
* @param secretKey 密钥
* @param encryptType 加密类型
* @throws Exception
*/
public static String encrypt(String content, String secretKey, String encryptType) throws Exception {
if (StringUtils.isBlank(content)) {
return null;
}
if (secretKey.length() != 16) {
log.error("[AesUtil] 需要输入密钥是16位字符串");
return null;
}
if (StringUtils.isNotBlank(encryptType)) {
if (!encryptType.equals(EncryptType.CBC_MODEL) && !encryptType.equals(EncryptType.ECB_MODEL)) {
log.error("[AesUtil] 入参加密模式有错误!");
return null;
}
}
Cipher cipher = Cipher.getInstance(StringUtils.isBlank(encryptType) ? EncryptType.ECB_MODEL : encryptType);
//ECB加密类型
if (StringUtils.isBlank(encryptType)) {
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), AES));
}
//CBC加密类型
if (StringUtils.isNotBlank(encryptType) && encryptType.equals(EncryptType.CBC_MODEL)) {
IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes(StandardCharsets.UTF_8));//偏移量
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), AES), zeroIv);
}
byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
//Base64再次转码(更加隐秘)
return Base64.encodeBase64String(encrypted);
}
/**
* 解密
*
* @param encryptContent 需解密的字符串
* @param secretKey 密钥
* @param encryptType 加密类型
* @throws Exception
*/
public static String decrypt(String encryptContent, String secretKey, String encryptType) throws Exception {
if (StringUtils.isBlank(encryptContent)) {
return null;
}
if (StringUtils.isBlank(secretKey)) {
log.error("[AesUtil] 密钥是16位字符串,不能为空");
return null;
}
if (secretKey.length() != 16) {
log.error("[AesUtil] 需要输入密钥是16位字符串");
return null;
}
if (StringUtils.isNotBlank(encryptType)) {
if (!encryptType.equals(EncryptType.CBC_MODEL) && !encryptType.equals(EncryptType.ECB_MODEL)) {
log.error("[AesUtil] 入参加密模式有错误!");
return null;
}
}
Cipher cipher = Cipher.getInstance(StringUtils.isBlank(encryptType) ? EncryptType.ECB_MODEL : encryptType);
//ECB加密类型
if (StringUtils.isBlank(encryptType)) {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), AES));
}
//CBC加密类型
if (StringUtils.isNotBlank(encryptType) && encryptType.equals(EncryptType.CBC_MODEL)) {
IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), AES), zeroIv);
}
try {
//加密先用Base64转码,再用AES解密
byte[] base64DecodeContent = Base64.decodeBase64(encryptContent);
byte[] decrypted = cipher.doFinal(base64DecodeContent);
return new String(decrypted, StandardCharsets.UTF_8);
} catch (Exception e) {
log.error("[AesUtil] 解密出错!");
return null;
}
}
}
AES 加密工具类java
于 2023-08-13 19:08:30 首次发布