AES加密模式演进:ECB、CBC与GCM的C#实现与对比
ECB模式:基础块加密
ECB是最简单的加密模式,将数据分块后独立加密每个块。优点:实现简单,支持并行处理。
缺点:相同明文块产生相同密文块,易暴露数据模式。
using System;
using System.Security.Cryptography;
using System.Text;
public class EcbCrypto
{
public static byte[] EncryptData(byte[] inputData, byte[] cryptoKey)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = cryptoKey;
aesAlg.Mode = CipherMode.ECB;
aesAlg.Padding = PaddingMode.PKCS7;
using (ICryptoTransform encryptor = aesAlg.CreateEncryptor())
{
return encryptor.TransformFinalBlock(inputData, 0, inputData.Length);
}
}
}
public static byte[] DecryptData(byte[] encryptedData, byte[] cryptoKey)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = cryptoKey;
aesAlg.Mode = CipherMode.ECB;
aesAlg.Padding = PaddingMode.PKCS7;
using (ICryptoTransform decryptor = aesAlg.CreateDecryptor())
{
return decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
}
}
}
}
// 测试示例
byte[] demoKey = new byte[16] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
byte[] plainData = Encoding.UTF8.GetBytes("重复数据块重复数据块");
byte[] encrypted = EcbCrypto.EncryptData(plainData, demoKey);
Console.WriteLine($"加密结果: {Convert.ToBase64String(encrypted)}");
CBC模式:链式加密改进
CBC引入初始化向量(IV),每个明文块与前一个密文块异或后加密。优点:隐藏数据模式,相同明文产生不同密文。
缺点:加密串行,存在填充预言攻击风险。
public class CbcCrypto
{
public static byte[] EncryptData(byte[] inputData, byte[] cryptoKey)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = cryptoKey;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
byte[] ivBytes = aesAlg.IV;
using (ICryptoTransform encryptor = aesAlg.CreateEncryptor())
{
byte[] cipherData = encryptor.TransformFinalBlock(inputData, 0, inputData.Length);
byte[] result = new byte[ivBytes.Length + cipherData.Length];
Buffer.BlockCopy(ivBytes, 0, result, 0, ivBytes.Length);
Buffer.BlockCopy(cipherData, 0, result, ivBytes.Length, cipherData.Length);
return result;
}
}
}
public static byte[] DecryptData(byte[] encryptedData, byte[] cryptoKey)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = cryptoKey;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
byte[] ivBytes = new byte[aesAlg.BlockSize / 8];
Buffer.BlockCopy(encryptedData, 0, ivBytes, 0, ivBytes.Length);
aesAlg.IV = ivBytes;
byte[] cipherData = new byte[encryptedData.Length - ivBytes.Length];
Buffer.BlockCopy(encryptedData, ivBytes.Length, cipherData, 0, cipherData.Length);
using (ICryptoTransform decryptor = aesAlg.CreateDecryptor())
{
return decryptor.TransformFinalBlock(cipherData, 0, cipherData.Length);
}
}
}
}
GCM模式:认证加密演进
GCM结合CTR模式加密和GMAC认证,提供机密性、完整性和真实性验证。优点:支持并行处理,无需填充,内置完整性校验。
缺点:Nonce必须唯一,实现较复杂。
using System.Security.Cryptography;
public class GcmCrypto
{
private const int NonceLength = 12;
private const int TagLength = 16;
public static byte[] EncryptData(byte[] inputData, byte[] cryptoKey)
{
byte[] nonce = new byte[NonceLength];
RandomNumberGenerator.Fill(nonce);
byte[] tag = new byte[TagLength];
byte[] cipherData = new byte[inputData.Length];
using (AesGcm aesGcm = new AesGcm(cryptoKey, TagLength))
{
aesGcm.Encrypt(nonce, inputData, cipherData, tag);
}
byte[] result = new byte[nonce.Length + tag.Length + cipherData.Length];
Buffer.BlockCopy(nonce, 0, result, 0, nonce.Length);
Buffer.BlockCopy(tag, 0, result, nonce.Length, tag.Length);
Buffer.BlockCopy(cipherData, 0, result, nonce.Length + tag.Length, cipherData.Length);
return result;
}
public static byte[] DecryptData(byte[] encryptedData, byte[] cryptoKey)
{
byte[] nonce = new byte[NonceLength];
byte[] tag = new byte[TagLength];
byte[] cipherData = new byte[encryptedData.Length - NonceLength - TagLength];
Buffer.BlockCopy(encryptedData, 0, nonce, 0, nonce.Length);
Buffer.BlockCopy(encryptedData, nonce.Length, tag, 0, tag.Length);
Buffer.BlockCopy(encryptedData, nonce.Length + tag.Length, cipherData, 0, cipherData.Length);
byte[] decryptedData = new byte[cipherData.Length];
using (AesGcm aesGcm = new AesGcm(cryptoKey, TagLength))
{
aesGcm.Decrypt(nonce, cipherData, tag, decryptedData);
}
return decryptedData;
}
}
完整性验证对比
GCM在解密时自动验证数据完整性,而CBC需要应用层自行验证。public void TamperTest()
{
byte[] testKey = new byte[16];
RandomNumberGenerator.Fill(testKey);
byte[] testData = Encoding.UTF8.GetBytes("测试数据内容");
// CBC篡改测试
byte[] cbcEncrypted = CbcCrypto.EncryptData(testData, testKey);
cbcEncrypted[20] ^= 0xFF; // 篡改密文
byte[] cbcDecrypted = CbcCrypto.DecryptData(cbcDecrypted, testKey); // 仍会解密
// GCM篡改测试
byte[] gcmEncrypted = GcmCrypto.EncryptData(testData, testKey);
gcmEncrypted[20] ^= 0xFF; // 篡改密文
try
{
byte[] gcmDecrypted = GcmCrypto.DecryptData(gcmEncrypted, testKey);
}
catch (AuthenticationTagMismatchException)
{
Console.WriteLine("GCM完整性验证失败");
}
}
性能对比分析
GCM在加解密速度上优于CBC,特别是在大数据量处理场景。using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
[MemoryDiagnoser]
public class PerformanceBenchmark
{
private byte[] perfKey;
private byte[] testData;
[Params(1024, 1048576)]
public int DataSize;
[GlobalSetup]
public void Initialize()
{
perfKey = new byte[16];
RandomNumberGenerator.Fill(perfKey);
testData = new byte[DataSize];
RandomNumberGenerator.Fill(testData);
}
[Benchmark]
public byte[] CbcPerformanceTest()
{
byte[] encrypted = CbcCrypto.EncryptData(testData, perfKey);
return CbcCrypto.DecryptData(encrypted, perfKey);
}
[Benchmark]
public byte[] GcmPerformanceTest()
{
byte[] encrypted = GcmCrypto.EncryptData(testData, perfKey);
return GcmCrypto.DecryptData(encrypted, perfKey);
}
}