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

AES加密XSL文件后解密丢失末尾内容问题排查

问题排查与解决方案

看起来你已经走对了大部分流程,但确实有几个关键细节没处理到位,导致解密后内容丢失。咱们一步步梳理:

核心问题分析

  1. AES-CBC模式缺少初始化向量(IV)
    AES-CBC是分组加密模式,必须使用随机生成的初始化向量(IV)才能保证加密安全性,而且解密时必须用同一个IV。你之前的代码完全没处理IV,这会直接导致解密时的块对齐错误,造成内容损坏或丢失——这很可能是你遇到问题的核心原因。

  2. 解密阶段未调用cipher.final
    不管加密还是解密,cipher.update只能处理完整的加密块,最后不完整的块需要用cipher.final来收尾。你加密时补了这个步骤,但解密时没加,这必然会丢失部分数据。

  3. 文件操作的指针问题
    直接操作临时文件对象时,File.read会把文件指针移到末尾,后续写入可能出现覆盖不完整的情况,先把文件内容读入变量再处理更稳妥。

修正后的代码示例

加密流程修正

tempFile = params[:stylesheet].tempfile
# 先读取完整文件内容,避免文件指针位置问题
file_content = File.read(tempFile)

# AES加密准备
pub_file = CaseCenter::Config::Reader.get('pub_key')
public_key = OpenSSL::PKey::RSA.new(File.read(pub_file))
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt
aes_key = cipher.random_key
aes_iv = cipher.random_iv # 生成随机IV,必须保存下来用于解密

# 执行加密
enc_data = cipher.update(file_content)
enc_data << cipher.final # 处理最后一个块

# 将加密内容写回临时文件
tempFile.rewind # 重置文件指针到开头
tempFile.write(enc_data)
tempFile.truncate(tempFile.pos) # 截断多余内容,确保文件长度正确

# 加密AES密钥和IV(IV也可以直接存Base64,不需要RSA加密,这里按你现有逻辑加密)
encrypted_aes_key = Base64.encode64(public_key.public_encrypt(aes_key))
encrypted_aes_iv = Base64.encode64(public_key.public_encrypt(aes_iv))

# 保存到MongoDB
stylesheet.aes_key = encrypted_aes_key
stylesheet.aes_iv = encrypted_aes_iv # 新增字段存储加密后的IV
grid_fs = Mongoid::GridFS
grid_file = grid_fs.put(tempFile.path)
stylesheet.stylesheet_id = grid_file.id

解密流程修正

grid_fs = Mongoid::GridFS
f = grid_fs.get(stylesheet_id)
encrypted_content = f.data

# 读取私钥并解密AES密钥、IV
key_source = CaseCenter::Config::Reader.get('priv_key')
passphrase = CaseCenter::Config::Reader.get('key_pass')

private_key = if key_source.include? "-----BEGIN RSA PRIVATE KEY-----"
                OpenSSL::PKey::RSA.new(key_source, passphrase)
              else
                OpenSSL::PKey::RSA.new(File.read(key_source), passphrase)
              end

decrypted_aes_key = private_key.private_decrypt(Base64.decode64(doc[:aes_key]))
decrypted_aes_iv = private_key.private_decrypt(Base64.decode64(doc[:aes_iv]))

# AES解密准备
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = decrypted_aes_key
cipher.iv = decrypted_aes_iv # 必须设置和加密时一致的IV

# 执行解密
decrypted_data = cipher.update(encrypted_content)
decrypted_data << cipher.final # 一定要加这行,处理最后一个块

测试建议

你可以先拿一个短文本文件测试,对比加密前和解密后的内容哈希值(比如用Digest::SHA256.hexdigest),确认完全一致后再处理大文件,这样更容易验证修复效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:57:37