import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
/**
* AES加密解密
*
* @author ning
* @since 2023/9/18 14:23
*/
public class AESEncrypt {
/**
* 加密
*/
public static String getEncrypt(String userProvidedPassword) throws Exception {
// 生成128位(16字节)AES密钥
byte[] keyBytes = new byte[16];
// 创建SecretKey
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
// 初始化Cipher为AES/GCM/NoPadding,因为GCM不需要额外的填充
// GCM需要一个额外的参数来指定认证标签的长度(通常为128位)
int tagLength = 128; // 认证标签的长度,以位为单位
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// 生成一个安全的随机IV
SecureRandom random = new SecureRandom();
byte[] iv = new byte[12]; // GCM需要96位(12字节)的IV
random.nextBytes(iv);
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, iv);
// 初始化Cipher
cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);
// 加密密码
byte[] encryptedPasswordBytes = cipher.doFinal(userProvidedPassword.getBytes(StandardCharsets.UTF_8));
// nonce是必需的,因为GCM在解密时需要它。将其附加到密文的前面是一个常见的做法。
// 这里简单起见,我们将nonce和密文合并,但在实际应用中,您可能需要一种更复杂的方法来处理它们。
// 加密结果包括IV和密文,我们可以将它们组合在一起
ByteBuffer result = ByteBuffer.allocate(iv.length + encryptedPasswordBytes.length);
result.put(iv);
result.put(encryptedPasswordBytes);
// 将加密后的密码和nonce编码为Base64
return Base64.getEncoder().encodeToString(result.array());
}
/**
* 解密
*/
public static String getDecode(String encryptedPassword) throws Exception{
// 生成128位(16字节)AES密钥
byte[] keyBytes = new byte[16];
// 创建SecretKey
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
// 假设encryptedPassword是Base64编码的,并且包含了nonce和密文
byte[] encodedData = Base64.getDecoder().decode(encryptedPassword);
// 提取nonce(IV),假设它位于密文的最前面
byte[] nonce = new byte[12]; // GCM的nonce长度通常为96位(12字节)
System.arraycopy(encodedData, 0, nonce, 0, nonce.length);
// 提取密文,跳过nonce
byte[] cipherText = new byte[encodedData.length - nonce.length];
System.arraycopy(encodedData, nonce.length, cipherText, 0, cipherText.length);
// 初始化Cipher为AES/GCM/NoPadding,并设置nonce
int tagLength = 128; // 认证标签的长度,以位为单位
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, nonce);
// 初始化Cipher为解密模式
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec);
// 解密密码
byte[] decryptedPasswordBytes = cipher.doFinal(cipherText);
// 将解密后的密码转换为字符串
return new String(decryptedPasswordBytes, StandardCharsets.UTF_8);
}
}
AES加密解密(GCM模式)
最新推荐文章于 2025-10-31 20:03:52 发布
该文章已生成可运行项目,
本文章已经生成可运行项目
2218






