主题
加密与解密
加密算法
- 加密算法为AES,加密模式为GCM,填充方式为NoPadding,密钥长度为256位(bit),IV向量为AES密钥的前128位(bit)
加密说明
- 明文数据进行AES加密后,对结果做Base64编码,得到密文数据,编码格式为UTF-8。 注:仅针对敏感数据进行AES加密,需加密的字段见具体接口参数备注。
解密说明
- 密文数据先进行Base64解码,然后再进行AES解密,编码格式为UTF-8。
代码示例
- 加密方法
Java 实现
java
/**
* 加密方法
* @param data 待加密的数据
* @param key 密钥
* @return 加密后的数据(Base64编码)
*/
public static String encrypt(String data, String key) {
try {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, key.substring(0, 16).getBytes()); // 初始化向量IV
cipher.init(Cipher.ENCRYPT_MODE, skey, gcmParameterSpec);
byte[] encryptedData = cipher.doFinal(data.getBytes());
byte[] iv = cipher.getIV();
return Base64.getEncoder().encodeToString(iv) + ":" + Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
logger.error("AES encrypt error:", e);
return null;
}
}.NET 实现
.NET
/**
* 加密方法
* @param data 待加密的数据
* @param key 密钥
* @return 加密后的数据(Base64编码)
*/
public static string Encrypt(string data, string key)
{
try
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
if (keyBytes.Length != 32)
throw new ArgumentException("密钥长度必须为32字节(256位)");
// Java示例中使用16字节IV
byte[] ivBytes = new byte[16];
Array.Copy(keyBytes, 0, ivBytes, 0, 16);
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
// 使用BouncyCastle库(需要安装)
return EncryptWithBouncyCastle(plainBytes, keyBytes, ivBytes);
}
catch (Exception e)
{
Console.Error.WriteLine($"AES encrypt error: {e}");
return null;
}
}
private static string EncryptWithBouncyCastle(byte[] plainBytes, byte[] keyBytes, byte[] ivBytes)
{
// 使用BouncyCastle处理16字节IV
// Install-Package Portable.BouncyCastle
AesEngine cipher = new AesEngine();
var gcmCipher = new GcmBlockCipher(cipher);
var parameters = new AeadParameters(
new KeyParameter(keyBytes),
128, // MAC大小
ivBytes
);
gcmCipher.Init(true, parameters);
byte[] encryptedBytes = new byte[gcmCipher.GetOutputSize(plainBytes.Length)];
int len = gcmCipher.ProcessBytes(plainBytes, 0, plainBytes.Length, encryptedBytes, 0);
gcmCipher.DoFinal(encryptedBytes, len);
string ivBase64 = Convert.ToBase64String(ivBytes);
string encryptedBase64 = Convert.ToBase64String(encryptedBytes);
return $"{ivBase64}:{encryptedBase64}";
}- 解密方法
Java 实现
java
/**
* 解密方法
* @param encryptedData 待解密的数据(Base64编码)
* @param key 密钥
* @return 解密后的数据
*/
public static String decrypt(String encryptedData, String key) {
try {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
String[] parts = encryptedData.split(":");
byte[] iv = Base64.getDecoder().decode(parts[0]);
byte[] encryptedDataBytes = Base64.getDecoder().decode(parts[1]);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, skey, gcmParameterSpec);
byte[] original = cipher.doFinal(encryptedDataBytes);
return new String(original);
} catch (Exception e) {
logger.error("AES decrypt error:", e);
return null;
}
}.NET 实现
.NET
public static string Decrypt(string encryptedData, string key)
{
try
{
// 1. 验证输入参数
if (string.IsNullOrEmpty(encryptedData))
throw new ArgumentNullException(nameof(encryptedData));
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
// 2. 准备密钥
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
if (keyBytes.Length != 32)
throw new ArgumentException("密钥必须为32字节(256位)");
// 3. 分割IV和密文
string[] parts = encryptedData.Split(':');
if (parts.Length != 2)
throw new FormatException("加密数据格式不正确,应为 'IV:密文' 格式");
byte[] iv = Convert.FromBase64String(parts[0]);
byte[] cipherText = Convert.FromBase64String(parts[1]);
// 4. 验证IV长度(GCM通常支持12或16字节)
if (iv.Length != 12 && iv.Length != 16)
Console.WriteLine($"警告:非标准IV长度 {iv.Length} 字节");
// 5. 使用BouncyCastle解密
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(
new KeyParameter(keyBytes),
128, // 认证标签长度(位)
iv
);
cipher.Init(false, parameters);
// 6. 执行解密
byte[] plainBytes = new byte[cipher.GetOutputSize(cipherText.Length)];
int len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainBytes, 0);
cipher.DoFinal(plainBytes, len);
// 7. 返回解密结果(移除可能的空字符)
return Encoding.UTF8.GetString(plainBytes).TrimEnd('\0');
}
catch (Exception ex)
{
Console.WriteLine($"解密失败: {ex.Message}");
return null;
}
}