看了几个别人写的,不好用,还是自动总结一下,不BB直接上代码,
缺依赖自己根据 import 找
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.constraints.NotNull;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.text.DecimalFormat;
import java.util.*;
public class AESUtil {
private static final String AES = "AES";
private static final String DEFAULT_IV = "1234567890123456";
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void main(String[] args) throws Exception {
DecimalFormat nf = new DecimalFormat("16880000000");
List<Map<String, Object>> data = new ArrayList<>();
for (int i = 1; i <= 500; i++) {
Map<String, Object> curr = new LinkedHashMap<>();
curr.put("姓名", "曾特喵穷" + i);
curr.put("手机号", nf.format(i));
data.add(curr);
}
Map<String, Object> map = new HashMap<>();
map.put("data", data);
String wait = JSON.toJSONString(map);
System.out.println("wait => " + wait);
// 长度可以是 16/24/32
String key = "12345678123456781234567812345678";
for (AlgorithmEnum algorithm : AlgorithmEnum.values()) {
System.out.println(algorithm.name);
//
String encrypt = encrypt(wait, key, DEFAULT_IV, algorithm);
System.out.println("\t=> " + encrypt);
//
String decrypt = decrypt(encrypt, key, DEFAULT_IV, algorithm);
System.out.println("\t=> " + decrypt);
}
}
/**
* 先AES加密,再将进行Base64转码,输出密钥字符串
*
* @param wait 待加密字符串
* @param key 密码,16、24、32位
* @param iv 向量,必须16位
* @param algorithm 算法
* @return
* @throws Exception
*/
public static String encrypt(@NotNull String wait, @NotNull String key, String iv, @NotNull AESUtil.AlgorithmEnum algorithm) throws Exception {
return encrypt(wait, key, iv, algorithm, StandardCharsets.UTF_8);
}
/**
* 先AES加密,再将进行Base64转码,输出密钥字符串
*
* @param wait 待加密字符串
* @param key 密码,16、24、32位
* @param iv 向量,必须16位
* @param algorithm 算法
* @param charset 字符集
* @return
* @throws Exception
*/
public static String encrypt(@NotNull String wait, @NotNull String key, String iv, @NotNull AESUtil.AlgorithmEnum algorithm, @NotNull Charset charset) throws Exception {
// 按照 mode 生成实例
Cipher cipher = cipherInstance(Cipher.ENCRYPT_MODE, key, iv, algorithm, charset);
// 字节码加密
byte[] b = cipher.doFinal(wait.getBytes(charset));
// 字节码转字符串
return new Base64().encodeToString(b);
}
/**
* 先将密钥base64解码,再进行AES解密,输出解密字符串
*
* @param wait 待解密密钥
* @param key 密码,16、24、32位
* @param iv 向量,必须16位
* @param algorithm 算法
* @return
* @throws Exception
*/
public static String decrypt(@NotNull String wait, @NotNull String key, String iv, @NotNull AESUtil.AlgorithmEnum algorithm) throws Exception {
return decrypt(wait, key, iv, algorithm, StandardCharsets.UTF_8);
}
/**
* 先将密钥base64解码,再进行AES解密,输出字符串
*
* @param wait 待解密密钥
* @param key 密码,16、24、32位
* @param iv 向量,必须16位
* @param algorithm 算法
* @param charset 字符集
* @return
* @throws Exception
*/
public static String decrypt(@NotNull String wait, @NotNull String key, String iv, @NotNull AESUtil.AlgorithmEnum algorithm, @NotNull Charset charset) throws Exception {
// 按照 mode 生成实例
Cipher cipher = cipherInstance(Cipher.DECRYPT_MODE, key, iv, algorithm, charset);
// Base64 解码后解密
byte[] b = cipher.doFinal(Base64.decodeBase64(wait));
// 字节码转字符串
return new String(b, charset);
}
/**
* 按照配置生成 Cipher 实例
*
* @param mode 加密或解密
* @param key 密码,16、24、32位
* @param iv 向量,必须16位
* @param algorithm 算法
* @param charset 字符集
* @return
* @throws Exception
*/
public static Cipher cipherInstance(@NotNull int mode, @NotNull String key, String iv, @NotNull AESUtil.AlgorithmEnum algorithm, @NotNull Charset charset) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm.name);
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(charset), AES);
if (algorithm.ivFlag && null != iv) {
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(charset));
cipher.init(mode, keySpec, ivSpec);
} else {
cipher.init(mode, keySpec);
}
return cipher;
}
public enum AlgorithmEnum {
/*
算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
*/
// 算法/模式/补码方式
CBC_PKCS5("AES/CBC/PKCS5Padding", true),
CBC_PKCS7("AES/CBC/PKCS7Padding", true),
CBC_ISO10126("AES/CBC/ISO10126Padding", true),
CFB_NO("AES/CFB/NoPadding", true),
CFB_PKCS5("AES/CFB/PKCS5Padding", true),
CFB_PKCS7("AES/CFB/PKCS7Padding", true),
CFB_ISO10126("AES/CFB/ISO10126Padding", true),
ECB_PKCS5("AES/ECB/PKCS5Padding", false),
ECB_PKCS7("AES/ECB/PKCS7Padding", false),
ECB_ISO10126("AES/ECB/ISO10126Padding", false),
OFB_NO("AES/OFB/NoPadding", true),
OFB_PKCS5("AES/OFB/PKCS5Padding", true),
OFB_PKCS7("AES/OFB/PKCS7Padding", true),
OFB_ISO10126("AES/OFB/ISO10126Padding", true),
PCBC_PKCS5("AES/PCBC/PKCS5Padding", true),
PCBC_ISO10126("AES/PCBC/ISO10126Padding", true);
/**
* 算法
*/
private String name;
/**
* IV标识
*/
private boolean ivFlag;
AlgorithmEnum(String name, boolean ivFlag) {
this.name = name;
this.ivFlag = ivFlag;
}
public String getName() {
return name;
}
public boolean getIvFlag() {
return ivFlag;
}
}
}