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

C# AWS Lambda读取S3中AES加密Excel文件的解密问题

Excel文件解密失败问题分析与修复方案

问题背景

AWS S3存储桶中存放了自定义加密的CSV文件,基于C#/.NET 6的Lambda函数通过AesManaged解密后转UTF-8编码上传,流程对CSV完全正常。新增Excel(xls/xlsx)支持时,无报错但解密后文件仍处于加密状态,格式与扩展名不匹配,转CSV尝试也未成功。

核心问题定位

现有代码错误地将二进制格式的Excel文件当成文本文件处理:

  • 对解密后的Excel流执行了Encoding.Convert编码转换,破坏了二进制文件的结构
  • 使用StreamReader读取二进制流,引入编码猜测,进一步损坏原始数据
  • CSV是文本文件,编码转换逻辑适用,但Excel是二进制格式,完全不兼容这套处理流程

修复步骤

  1. 区分文件类型处理:根据文件名后缀判断是CSV还是Excel,分别执行不同的流处理逻辑
  2. Excel文件直接保留二进制流:解密后直接复制原始二进制流,不做任何编码转换
  3. 确保流位置正确:上传前重置流的Position到开头,避免数据读取不全
  4. 替换过时的Aes实现:将AesManaged替换为.NET 6推荐的Aes.Create()

修改后的代码示例

主流程修改

var ddresult = DownloadAndDecrypt(s3client, bucketName, fileName, credInput);
MemoryStream tempms = null;

if (ddresult.Stream != null)
{
    var fileExt = Path.GetExtension(fileName).ToLowerInvariant();
    if (fileExt == ".csv")
    {
        // CSV文件沿用原有文本编码转换逻辑
        var resultms = new MemoryStream();
        CopyStream(ddresult.Stream, resultms);
        
        resultms.Position = 0; // 重置流位置,确保StreamReader能读取到内容
        var encBytes = resultms.ToArray();
        using var sr = new StreamReader(resultms);
        var encoding = sr.CurrentEncoding;
        var utf8Bytes = Encoding.Convert(encoding, Encoding.UTF8, encBytes);
        tempms = new MemoryStream(utf8Bytes);
    }
    else if (fileExt is ".xls" or ".xlsx")
    {
        // Excel文件直接复制解密后的二进制流,跳过编码转换
        tempms = new MemoryStream();
        CopyStream(ddresult.Stream, tempms);
        tempms.Position = 0;
    }
}

if (tempms != null)
{
    var s3uploadresult = WriteFileToS3(newBucketName, fileName, tempms, s3Client);
    tempms.Dispose(); // 手动释放资源,Lambda环境中避免泄漏
}

DownloadAndDecrypt方法优化

public StreamResultModel DownloadAndDecrypt(AmazonS3Client s3Client, string bucketName, string filename, CredInputModel credInput)
{
    var result = new StreamResultModel
    {
        Error = false
    };

    try
    {
        using var transferUtility = new TransferUtility(s3Client);
        var request = new TransferUtilityOpenStreamRequest
        {
            BucketName = bucketName,
            Key = filename,
        };
        var originalStream = transferUtility.OpenStream(request);

        // 替换为.NET官方推荐的非过时Aes实现
        using var aes = Aes.Create();
        aes.BlockSize = 128;
        aes.KeySize = 256;
        aes.Mode = CipherMode.CBC;
        aes.Key = Convert.FromBase64String(credInput.KeySharedSecret);
        aes.IV = Convert.FromBase64String(credInput.Salt);
        
        var decryptor = aes.CreateDecryptor();
        result.Stream = new CryptoStream(originalStream, decryptor, CryptoStreamMode.Read);
        return result;
    }
    catch (Exception e)
    {
        result.Error = true;
        result.ErrorMsg = e.Message;
        return result;
    }
}

额外建议

  • 增加日志记录:记录解密前后的流长度,验证解密是否成功(解密后Excel流长度应与原始未加密文件一致)
  • 完善错误处理:针对Excel文件添加格式校验,避免无效文件上传
  • 资源管理:使用using语句自动管理流资源,Lambda环境中减少资源泄漏风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:07:05