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

C# RijndaelManaged解密结果末尾带\0致单元测试失败排查

Rijndael加解密结果末尾多\0空字符问题排查与修复

问题背景

实现了一套数据加解密工具类,向加密方法传入测试字符串"This is a test.",完成加解密流程后得到的结果字符串末尾多出\0空字符,二者语义等价但无法通过字符串相等断言的单元测试。最初怀疑是PaddingMode.PKCS7填充模式导致返回的字节缓冲区末尾携带额外\0空字符,最终通过调整解密方法返回逻辑解决问题:仅截取CryptoStream实际读取到的readCount长度字节作为返回结果,所有代码块、技术术语均保持原有写法未做修改。

对应单元测试代码

var privateKey = Encryption.GetPrivateKey();
var password = new byte[] { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
var salt = Salt.CreateSalt();
var passPhrase = Encryption.PasswordAndSalt(password, salt);
var thisIsATest = "This is a test.";
var clearArray = Encoding.UTF8.GetBytes(thisIsATest);
var cypherArray = Encryption.Encrypt(clearArray, passPhrase, privateKey);
var decryptedArray = Encryption.Decrypt(cypherArray, passPhrase, privateKey);
var thisIsDecrypted = Encoding.UTF8.GetString(decryptedArray);
//Assert
Assert.IsTrue(thisIsATest == thisIsDecrypted);

原有问题代码

Decrypt解密方法(修复前)

public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
    var result = new byte[] { };
    using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
    {
        using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
        {
            using (var ms = new MemoryStream(cypherBytes))
            {
                using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    result = new byte[cypherBytes.Length];
                    var readCount = cs.Read(result, 0, result.Length);
                }
            }
        }
        rijndael.Clear();
    }
    return result;
}

Encrypt加密方法

public static byte[] Encrypt(byte[] clearBytes, byte[] passPhrase, byte[] privateKey)
{
    var result = new byte[] { };
    using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
    {
        using (var encryptor = rijndael.CreateEncryptor(passPhrase, privateKey))
        {
            using (var ms = new MemoryStream())
            {
                using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.FlushFinalBlock();
                }
                result = ms.ToArray();
            }
        }
        rijndael.Clear();
    }
    return result;
}

PasswordAndSalt密钥派生方法

public const int INITIALIZATION_VECTOR_SIZE = 32;

public static byte[] PasswordAndSalt(byte[] password, byte[] salt)
{
    var result = new byte[] { };
    using (var pwd = new PasswordDeriveBytes(password, salt))
    {
        result = pwd.GetBytes(INITIALIZATION_VECTOR_SIZE);
    }
    return result;
}

问题根因

该问题与PaddingMode.PKCS7填充模式无关。
原有解密逻辑预先分配了和密文等长的字节数组作为接收缓冲区,调用CryptoStream.Read方法时,只会将实际解密得到的有效明文写入缓冲区前readCount个位置,数组剩余未被写入的位置会保留字节类型默认值0x00(即对应\0空字符)。代码直接返回整个长度等于密文的缓冲区,会把末尾的无效0x00字节一并返回,通过Encoding.UTF8.GetString转成字符串后,末尾就会携带多余空字符,导致和原字符串的相等断言失败。

修复方案

调整解密方法返回逻辑,不直接返回预分配的全长度缓冲区,而是根据Read方法返回的实际读取字节数readCount,从临时缓冲区中拷贝对应长度的有效字节作为返回结果,丢弃缓冲区末尾未被写入的无效0x00字节即可。
修复后的Decrypt方法代码如下:

public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
    var result = new byte[] { };
    using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
    {
        using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
        {
            using (var ms = new MemoryStream(cypherBytes))
            {
                using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    var array = new byte[cypherBytes.Length];
                    var readCount = cs.Read(array, 0, array.Length);
                    result = new byte[readCount];
                    Array.Copy(array, result, readCount);
                }
            }
        }
        rijndael.Clear();
    }
    return result;
}

修复后解密得到的字节数组和原始明文字节数组完全一致,单元测试可正常通过。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:48:25