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

如何正确从CryptoStream读取字符串?字符串截断问题求解

解决CryptoStream结合压缩加密读写多字符串时的截断问题

核心问题在于多数据块无边界标记,加上CryptoStream缓冲未正确刷新导致的截断。数字能正常读取是因为其字节长度固定,读取逻辑刚好匹配;而字符串长度不固定,加密压缩后字节流连在一起,读取时无法准确分割两个字符串,最终出现截断现象。

下面是正确的实现思路和代码示例:

关键解决要点

  • 给每个数据块添加长度标记:写入前先记录当前字符串的字节长度,读取时先读长度再读对应字节,确保准确分割每个字符串
  • 强制刷新CryptoStream缓冲:加密/压缩完成后必须调用FlushFinalBlock(),避免最后一部分缓冲数据未写入文件
  • 统一字符编码:字符串转字节数组时固定编码(如UTF-8),读写保持一致,避免编码差异导致的长度计算错误

完整代码示例

写入逻辑(加密+压缩)

using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;

class CryptoWriter
{
    public static void WriteEncryptedStrings(string filePath, string[] strings, byte[] aesKey)
    {
        using (var fs = new FileStream(filePath, FileMode.Create))
        using (var aes = Aes.Create())
        {
            aes.Key = aesKey;
            aes.GenerateIV(); // 生成随机IV,需和读取时一致,先写入文件头部
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            // 写入IV到文件,读取时需用此IV解密
            fs.Write(aes.IV, 0, aes.IV.Length);

            using (var encryptor = aes.CreateEncryptor())
            using (var cryptoStream = new CryptoStream(fs, encryptor, CryptoStreamMode.Write))
            using (var deflateStream = new DeflateStream(cryptoStream, CompressionMode.Compress))
            using (var writer = new BinaryWriter(deflateStream, Encoding.UTF8))
            {
                foreach (var str in strings)
                {
                    byte[] strBytes = Encoding.UTF8.GetBytes(str);
                    writer.Write(strBytes.Length); // 先写字符串字节长度
                    writer.Write(strBytes); // 再写字符串字节数据
                }

                cryptoStream.FlushFinalBlock(); // 强制刷新加密流缓冲,确保所有数据写入
            }
        }
    }
}

读取逻辑(解密+解压缩)

using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;

class CryptoReader
{
    public static string[] ReadEncryptedStrings(string filePath, byte[] aesKey)
    {
        var result = new List<string>();
        using (var fs = new FileStream(filePath, FileMode.Open))
        using (var aes = Aes.Create())
        {
            // 读取文件头部的IV
            byte[] iv = new byte[aes.BlockSize / 8];
            fs.Read(iv, 0, iv.Length);

            aes.Key = aesKey;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            using (var decryptor = aes.CreateDecryptor())
            using (var cryptoStream = new CryptoStream(fs, decryptor, CryptoStreamMode.Read))
            using (var deflateStream = new DeflateStream(cryptoStream, CompressionMode.Decompress))
            using (var reader = new BinaryReader(deflateStream, Encoding.UTF8))
            {
                try
                {
                    while (true)
                    {
                        int strLength = reader.ReadInt32(); // 先读取字符串字节长度
                        byte[] strBytes = reader.ReadBytes(strLength); // 读取对应长度的字节数组
                        result.Add(Encoding.UTF8.GetString(strBytes));
                    }
                }
                catch (EndOfStreamException)
                {
                    // 流读取完毕,正常退出循环
                }
            }
        }
        return result.ToArray();
    }
}

使用示例

// 256位AES密钥(实际需用安全方式生成,如Rfc2898DeriveBytes)
byte[] aesKey = Encoding.UTF8.GetBytes("0123456789ABCDEF0123456789ABCDEF");
string[] inputStrings = { "TestString", "TestString2" };

// 写入加密压缩后的字符串
CryptoWriter.WriteEncryptedStrings("encrypted_data.bin", inputStrings, aesKey);

// 读取解密解压缩后的字符串
string[] outputStrings = CryptoReader.ReadEncryptedStrings("encrypted_data.bin", aesKey);
foreach (var str in outputStrings)
{
    Console.WriteLine(str); // 输出:TestString、TestString2
}

额外注意事项

  • IV必须随机生成并随加密数据存储,不要硬编码IV,否则会降低加密安全性
  • 密钥需使用安全的生成方式(如基于密码的Rfc2898DeriveBytes),避免使用明文密钥
  • 处理大文件或大量数据时,需注意流的内存占用,避免一次性读取全部数据到内存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:13:24