当前位置:首页 > 技术 > 正文内容

AES加密模式演进:ECB、CBC与GCM的C#实现与对比

访客 技术 2026年9月9日 13
数据安全在数字化时代至关重要,AES作为现代对称加密的核心标准,其不同工作模式直接影响安全性与性能。本文通过C#代码示例,分析ECB、CBC和GCM三种模式的特性与演进。

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);
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。