You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# AES解密场景下如何识别已被篡改的byte[]数组

AES加密数据篡改检测解决方案

问题根源

AES默认的CBC加密模式仅提供数据机密性能力,没有内置完整性校验逻辑:当密文被篡改后,解密过程要么抛出异常(你当前代码全局捕获异常返回null),要么不抛出异常但输出包含乱码的无效明文,程序无法直接识别明文是否被篡改。
另外你现有代码存在两处明显的逻辑错误:

  • AES要求密钥长度必须为16/24/32字节(对应128/192/256位),IV长度必须为16字节(AES块大小),你硬编码的abc密钥和xyzIV长度不符合要求,实际运行会直接抛出参数异常。
  • 用ASCII编码转换密钥/IV,如果后续调整为带非ASCII字符的密钥会出现数据丢失,建议用UTF8或直接使用字节数组定义密钥。

推荐解决方案:使用AES-GCM认证加密模式

AES-GCM属于AEAD(带关联数据的认证加密)标准模式,一次操作同时完成加密和完整性校验,只要密文、IV、认证标签任意部分被篡改,解密时会直接抛出认证失败异常,无需额外手动实现校验逻辑,是当前工业界的主流方案。

完整实现代码

加密方法

using System.Security.Cryptography;
using System.Text;

// 注意:密钥请妥善保管,不要硬编码在代码中,建议从配置中心/环境变量读取
// 此处示例为32字节AES-256密钥,实际使用请替换为自己的安全密钥
private static readonly byte[] AesKey = new byte[32] { /* 你的32字节密钥 */ };

public static string Encrypt(string plainText)
{
    if (string.IsNullOrEmpty(plainText))
        throw new ArgumentNullException(nameof(plainText));

    var plainBytes = Encoding.UTF8.GetBytes(plainText);
    
    // GCM模式推荐使用12字节的随机IV,每次加密生成新的IV,不要复用
    var nonce = new byte[12];
    RandomNumberGenerator.Fill(nonce);
    
    // 认证标签长度固定为16字节即可
    var tag = new byte[16];
    var cipherBytes = new byte[plainBytes.Length];

    using (var aesGcm = new AesGcm(AesKey, tag.Length))
    {
        aesGcm.Encrypt(nonce, plainBytes, cipherBytes, tag);
    }

    // 把nonce、密文、标签拼接后转Base64,方便传输
    var combined = new byte[nonce.Length + cipherBytes.Length + tag.Length];
    Buffer.BlockCopy(nonce, 0, combined, 0, nonce.Length);
    Buffer.BlockCopy(cipherBytes, 0, combined, nonce.Length, cipherBytes.Length);
    Buffer.BlockCopy(tag, 0, combined, nonce.Length + cipherBytes.Length, tag.Length);
    
    return Convert.ToBase64String(combined);
}

解密方法(自带篡改检测)

public static string Decrypt(string encryptedText)
{
    try
    {
        if (string.IsNullOrEmpty(encryptedText))
            return null;

        var combined = Convert.FromBase64String(encryptedText);
        if (combined.Length < 12 + 16) // 最少需要12字节nonce + 16字节tag
            return null;

        // 拆分nonce、密文、标签
        var nonce = combined.AsSpan(0, 12);
        var tag = combined.AsSpan(combined.Length - 16, 16);
        var cipherBytes = combined.AsSpan(12, combined.Length - 12 - 16);
        var plainBytes = new byte[cipherBytes.Length];

        using (var aesGcm = new AesGcm(AesKey, 16))
        {
            // 数据被篡改时,此处会抛出CryptographicException
            aesGcm.Decrypt(nonce, cipherBytes, tag, plainBytes);
        }

        return Encoding.UTF8.GetString(plainBytes);
    }
    catch (CryptographicException)
    {
        // 捕获到加密相关异常,说明数据被篡改或格式错误
        return null;
    }
    catch (Exception)
    {
        return null;
    }
}

兼容原有CBC模式的替代方案

如果因为业务要求不能更换加密模式,可以在原有CBC逻辑基础上增加HMAC校验:

  1. 加密完成后,使用独立的HMAC密钥(不要和AES密钥共用)计算密文的HMAC值,将HMAC值拼接到密文后一起转Base64输出
  2. 解密时先拆分出HMAC值和密文,重新计算密文的HMAC和接收的HMAC做比对,不一致直接判定为数据被篡改,无需走后续解密流程。

内容的提问来源于stack exchange,提问作者Dyan test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 14:54:00