首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将AES加密压缩到MemoryStream

将AES加密压缩到MemoryStream
EN

Stack Overflow用户
提问于 2019-08-09 17:16:20
回答 1查看 810关注 0票数 2

我正在开发一个进程,用于压缩和加密桌面应用程序中的字节数组,并通过WebMethod将其发送到我的web应用程序,然后将其解压缩/解加密回字节数组。我目前正试图用SharpZipLib来实现这一点。文件的压缩似乎如预期的那样正常工作。我能够将文件保存到磁盘,并使用7zip进行解压缩,没有问题。

我遇到的问题是,当我在我的web服务器上接收到字节数组并试图提取它时。

我使用CompressData方法压缩桌面端的数据。

代码语言:javascript
运行
复制
private byte[] CompressData(byte[] data, string password)
{
    MemoryStream input = new MemoryStream(data);
    MemoryStream ms = new MemoryStream();
    ZipOutputStream os = new ZipOutputStream(ms);
    os.SetLevel(9);
    if (!string.IsNullOrEmpty(password)) os.Password = password;
    ZipEntry entry = new ZipEntry("data")
    {
        DateTime = DateTime.Now
    };
    if (!string.IsNullOrEmpty(password)) entry.AESKeySize = 256;
    os.PutNextEntry(entry);
    StreamUtils.Copy(input, os, new byte[4096]);
    os.CloseEntry();
    os.IsStreamOwner = false;
    os.Close();
    ms.Position = 0;
    return ms.ToArray();
}

我使用以下代码提取服务器端的数据(几乎逐字从SharpZipLib示例中提取):

代码语言:javascript
运行
复制
    private byte[] DoRebuildData(byte[] data, string password)
    {
        MemoryStream inStream = new MemoryStream(data);

        MemoryStream outputMemStream = new MemoryStream();
        ZipOutputStream zipOut = new ZipOutputStream(outputMemStream)
        {
            IsStreamOwner = false  // False stops the Close also Closing the underlying stream.
        };

        zipOut.SetLevel(3);
        zipOut.Password = password;        // optional

        RecursiveExtractRebuild(inStream, zipOut);
        inStream.Close();

        // Must finish the ZipOutputStream to finalise output before using outputMemStream.
        zipOut.Close();

        outputMemStream.Position = 0;
        return outputMemStream.ToArray();
    }

    // Calls itself recursively if embedded zip
    //
    private void RecursiveExtractRebuild(Stream str, ZipOutputStream os)
    {

        ZipFile zipFile = new ZipFile(str)
        {
            IsStreamOwner = false
        };

        foreach (ZipEntry zipEntry in zipFile)
        {
            if (!zipEntry.IsFile)
                continue;
            String entryFileName = zipEntry.Name; // or Path.GetFileName(zipEntry.Name) to omit folder
                                                  // Specify any other filtering here.

            Stream zipStream = zipFile.GetInputStream(zipEntry);
            // Zips-within-zips are extracted. If you don't want this and wish to keep embedded zips as-is, just delete these 3 lines. 
            if (entryFileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
            {
                RecursiveExtractRebuild(zipStream, os);
            }
            else
            {
                ZipEntry newEntry = new ZipEntry(entryFileName);
                newEntry.DateTime = zipEntry.DateTime;
                newEntry.Size = zipEntry.Size;
                // Setting the Size will allow the zip to be unpacked by XP's built-in extractor and other older code.

                os.PutNextEntry(newEntry);

                StreamUtils.Copy(zipStream, os, new byte[4096]);
                os.CloseEntry();
            }
        }
    }

预期的结果是返回服务器上的原始字节数组。

在服务器上,当涉及到行时:

代码语言:javascript
运行
复制
Stream zipStream = zipFile.GetInputStream(zipEntry);

我收到错误“无法为AES加密流提供密码”。

我看到设置密码的唯一地方是在ZipOutputStream对象中,我已经在运行时进行了检查,这是适当设置的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-10 08:00:02

解压缩时,必须将密码分配给password-property of ZipFile-instance,即必须在RecursiveExtractRebuild-method中设置密码(为此,必须将密码添加为附加参数):

代码语言:javascript
运行
复制
zipFile.Password = password;

这个例子所示。

应该注意的是,当前的DoRebuildData-method实际上并不是解压缩数据,而是把它重新装进新的拉链里DoRebuildData-method中的(可选)行:

代码语言:javascript
运行
复制
zipOut.Password = password;

不为解压缩(即旧zip)指定密码,而是为新zip定义密码。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57434610

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档