【JAVA】AES加密DEMO
<h2>数据加密DEMO</h2>
<h3>1. 通过时间戳(毫秒)生成16位随机字符串 -> ASE-KEY</h3>
<ol>
<li><code>timestamp</code>:(毫秒)</li>
<li><code>ase-key</code>: timestamp 通过 SHA-256 加密取 4-20 位的获得随机字符</li>
</ol>
<h3>2 根据获取的 ASE-KEY 为密钥,对所有参数进行 ASE 加密</h3>
<ol>
<li>指定 AES 加密算法,ECB 模式,PKCS5Padding 填充方式</li>
<li><code>AES/ECB/PKCS5Padding</code></li>
<li><code>sign</code> & <code>timestamp</code> & <code>merchantNo</code> 不参与加密、签名</li>
</ol>
<h3>AES工具类 DEMO</h3>
<pre><code class="language-java">import com.alibaba.fastjson2.JSONObject;
import lombok.extern.log4j.Log4j2;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.List;
@Log4j2
public class AESUtils {
//忽略 加密、签名 字段
public final static List&lt;String&gt; neglectParams = List.of(&quot;sign&quot;,&quot;timestamp&quot;,&quot;merchantNo&quot;);
/**
* 参数字段值 加密
* @param param 参数json
* @param key AES加密 kEY
*/
public static void encrypt(JSONObject param, String key) {
param.forEach((k, v)-&gt; {
if(neglectParams.contains(k)){
//忽略字段,跳过
param.put(k,v);
return;
}
param.put(k, encrypt(String.valueOf(v), key));
});
}
/**
* 参数字段值 解密
* @param param 参数json
* @param key AES加密 kEY
*/
public static void decrypt(JSONObject param, String key) {
param.forEach((k, v)-&gt; {
if(neglectParams.contains(k)){
//忽略字段,跳过
param.put(k,v);
return;
}
param.put(k, decrypt(String.valueOf(v), key));
});
}
/**
* AES-ECB-PKCS5Padding 加密
* @param data 需加密值
* @param key AES加密 kEY
* @return 加密后字符串
*/
public static String encrypt(String data, String key){
try{
// 创建一个 AES 密钥
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), &quot;AES&quot;);
// 创建一个 Cipher 对象,指定 AES 加密算法,ECB 模式,PKCS5Padding 填充方式
Cipher cipher = Cipher.getInstance(&quot;AES/ECB/PKCS5Padding&quot;);
// 初始化为加密模式
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 执行加密操作
byte[] encryptedData = cipher.doFinal(data.getBytes());
// 将加密后的字节数组转为 Base64 编码的字符串返回
return Base64.getEncoder().encodeToString(encryptedData);
}catch (Exception e){
log.error(&quot;AES加密失败:【{}】&quot;,e.getMessage());
throw new RuntimeException(&quot;AES加密失败!&quot;);
}
}
/**
* AES-ECB-PKCS5Padding 解密
* @param encryptedData 密文
* @param key AES加密 kEY
* @return 解密后值
*/
public static String decrypt(String encryptedData, String key) {
try{
// 创建一个 AES 密钥
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), &quot;AES&quot;);
// 创建一个 Cipher 对象,指定 AES 解密算法,ECB 模式,PKCS5Padding 填充方式
Cipher cipher = Cipher.getInstance(&quot;AES/ECB/PKCS5Padding&quot;);
// 初始化为解密模式
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 将 Base64 编码的加密数据解码为字节数组
byte[] decodedData = Base64.getDecoder().decode(encryptedData);
// 执行解密操作
byte[] decryptedData = cipher.doFinal(decodedData);
// 将解密后的字节数组转换为字符串
return new String(decryptedData);
}catch (Exception e){
log.error(&quot;AES解密失败:【{}】&quot;,e.getMessage());
throw new RuntimeException(&quot;AES解密失败!&quot;);
}
}
/**
* sha256获取KEY
* @param data 这边指的是时间戳
* @return AES加密 kEY
*/
public static String sha256(String data) {
try{
MessageDigest digest = MessageDigest.getInstance(&quot;SHA-256&quot;);
digest.reset();
digest.update(data.getBytes(StandardCharsets.UTF_8));
return String.format(&quot;%064x&quot;, new BigInteger(1, digest.digest())).substring(4, 20);
}catch (Exception e){
log.error(&quot;SHA256解密失败:【{}】&quot;,e.getMessage());
throw new RuntimeException(&quot;SHA256解密失败!&quot;);
}
}
public static void main(String[] args) {
try {
Long timestamp = System.currentTimeMillis();
String key = sha256(String.valueOf(timestamp)); // 生成随机16位,密钥
// AES加密 kEY
System.out.println(key);
// 示例数据
JSONObject param=new JSONObject();
param.put(&quot;timestamp&quot;, timestamp);
param.put(&quot;merchantNo&quot;, &quot;17170000000000000000&quot;);
param.put(&quot;merchantOrderNo&quot;, &quot;NO1234567890&quot;);
// 加密
encrypt(param, key);
System.out.println(param);
// 解密
decrypt(param, key);
System.out.println(param);
} catch (Exception e) {
log.error(&quot;测试AES加解密失败:【{}】&quot;,e.getMessage());
}
}
}
</code></pre>