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

解密大文件时出现OpenSSL内存分配失败(NoMemoryError)求助

解决OpenSSL解密大文件时的内存分配错误(NoMemoryError)

嘿,这个坑我踩过!你遇到的问题根源很明确:你一次性把整个0.97GB的文件读进内存了。小文件这么玩没问题,但大文件直接用io.read会把所有内容塞进RAM,内存扛不住就触发了OpenSSL的内存分配失败错误。

咱们直接上解决方案——把一次性读写改成分块处理,每次只读取一小段数据,解密后立即写入输出文件,全程不会把整个文件放在内存里。

修改后的解密代码

首先重构decrypt方法,让它支持分块处理输入和输出流:

def decrypt(input_io, output_io)
  aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
  aes.decrypt
  aes.key = "cryptoKeyString"
  aes.iv = "ivString"

  # 分块大小可以根据你的内存情况调整,64KB是比较稳妥的选择
  chunk_size = 64 * 1024
  while chunk = input_io.read(chunk_size)
    output_io.write(aes.update(chunk))
  end
  # 处理最后一块的收尾数据,这步不能忘!
  output_io.write(aes.final)
end

然后更新解密的调用逻辑,用文件流而非一次性读取:

def do_decrypt(input_file_path, output_file_path)
  # 使用块式打开文件,自动处理关闭,避免资源泄漏
  File.open(input_file_path, 'rb') do |input_io|
    File.open(output_file_path, 'wb') do |output_io|
      decrypt(input_io, output_io)
    end
  end
end

顺便优化你的加密逻辑

既然大文件解密会出问题,加密时也大概率会有同样的内存问题,建议把加密代码也改成分块模式:

def encrypt(input_io, output_io)
  aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
  aes.encrypt
  aes.key = "cryptoKeyString"
  
  # 重要提醒:不要硬编码IV!这里只是示例,实际要随机生成
  aes.iv = SecureRandom.random_bytes(aes.iv_len)
  # 把随机生成的IV写入输出文件开头,解密时先读取这部分
  output_io.write(aes.iv)

  chunk_size = 64 * 1024
  while chunk = input_io.read(chunk_size)
    output_io.write(aes.update(chunk))
  end
  output_io.write(aes.final)
end

def do_encrypt(file_path, output_file_path)
  File.open(file_path, 'rb') do |input_io|
    File.open(output_file_path, 'wb') do |output_io|
      encrypt(input_io, output_io)
    end
  end
end

关键注意事项

  • 分块大小可以灵活调整,比如128KB或1MB,只要不超过你的可用内存就行。
  • 绝对不要硬编码IV!AES-CBC的IV必须是随机且唯一的,硬编码会严重削弱加密安全性。上面的加密示例里已经改成随机生成IV并写入密文开头,解密时需要先读取IV(长度是aes.iv_len)再设置给Cipher。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:37:04