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

C++ Botan库可否将同一个文件同时用作DataSource_Stream与DataSink_Stream

问题原因

你直接指定输出为in.txt默认是追加写入,就算改成覆盖模式也会出现读写冲突:你在读取后半段明文之前,前半段写入的密文就会覆盖还没读取的明文内容,最终得到错误的加密结果。


方案1:小文件场景(内存足够容纳完整文件)

这是最稳妥的实现方式,不存在读写冲突风险:

  • 先将整个文件的明文全部读取到内存中,关闭原文件的读句柄
  • 在内存中完成明文加密
  • 以覆盖写入模式打开原文件,将密文写入
    实现代码示例:
// 二进制模式读取完整明文到内存
DataSource_Stream in("in.txt", true);
secure_vector<uint8_t> plaintext = in.read_all();
in.close();

// 执行加密
Pipe pipe(get_cipher("AES-128/CTR-BE", key, iv, Cipher_Dir::Encryption));
pipe.process_msg(plaintext);
secure_vector<uint8_t> ciphertext = pipe.read_all();

// 覆盖写回原文件,第二个参数false表示非追加的覆盖模式
DataSink_Stream out("in.txt", false);
out.write(ciphertext);
out.close();

方案2:大文件场景(无法全量加载到内存)

该方案仅适用于不需要填充的加密模式(比如你用的CTR,以及GCM、ChaCha20等流加密/流模式块加密),这类模式加密前后的数据长度完全一致,可以通过分块随机读写实现原地加密,完全不占用额外存储空间:

const size_t CHUNK_SIZE = 4096; // 可调整为和磁盘块对齐的大小,比如16KB
std::fstream file("in.txt", std::ios::in | std::ios::out | std::ios::binary);
if (!file.is_open()) {
    // 自行处理文件打开错误逻辑
}

// 获取文件总大小
file.seekg(0, std::ios::end);
const size_t total_size = file.tellg();
file.seekg(0, std::ios::beg);

auto cipher = get_cipher("AES-128/CTR-BE", key, iv, Cipher_Dir::Encryption);
size_t current_offset = 0;
secure_vector<uint8_t> chunk_buf(CHUNK_SIZE);

while (current_offset < total_size) {
    const size_t read_len = std::min(CHUNK_SIZE, total_size - current_offset);
    // 读当前块明文
    file.read(reinterpret_cast<char*>(chunk_buf.data()), read_len);
    // 加密当前块
    cipher->process(chunk_buf.data(), chunk_buf.data(), read_len);
    // 跳回当前块起始位置写入密文
    file.seekp(current_offset);
    file.write(reinterpret_cast<const char*>(chunk_buf.data()), read_len);
    // 跳到下一个块的读位置
    current_offset += read_len;
    file.seekg(current_offset);
}
file.close();

注意事项

  • 如果使用CBC、ECB等需要填充的块加密模式,密文长度会比明文多一个块大小,无法使用该原地加密方案
  • 建议操作前备份重要文件,避免中途程序崩溃、掉电导致文件不可逆损坏
  • 如果需要做完整性校验,建议先计算明文的MAC值,加密完成后将MAC存在文件末尾或者单独的存储位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:36:03