将 AES 加密的 zip 提取到 MemoryStream
Extracting AES encrypted zip to MemoryStream
我正在开发一个过程来压缩和加密我的桌面应用程序中的字节数组,并通过 WebMethod 将它发送到我的 Web 应用程序,然后 uncompress/unencrypt 它返回到字节数组。我目前正在尝试使用 SharpZipLib 执行此操作。文件的压缩似乎按预期工作。我能够将文件保存到磁盘并使用 7zip 毫无问题地解压缩它。
我遇到的问题是当我在网络服务器上收到字节数组并尝试提取它时。
我在桌面端使用CompressData方式压缩数据
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 示例中逐字提取的):
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();
}
}
}
预期的结果是在服务器上取回我原来的字节数组。
在服务器上,当涉及到行时:
Stream zipStream = zipFile.GetInputStream(zipEntry);
我收到错误 'No password available for AES encrypted stream.'
我唯一看到设置密码的地方是在 ZipOutputStream 对象中,我在运行时检查过,这个设置正确。
解包时,密码必须赋给ZipFile
-实例的password
-属性,即必须在RecursiveExtractRebuild
-方法中设置(为此必须将密码添加为附加参数):
zipFile.Password = password;
如图this example.
需要注意的是,目前的DoRebuildData
-方法实际上并没有解压数据,而是re-packs it into a new zip。 DoRebuildData
-方法中的(可选)行:
zipOut.Password = password;
不指定解压密码(即旧 zip),但定义 新 zip 的密码。
我正在开发一个过程来压缩和加密我的桌面应用程序中的字节数组,并通过 WebMethod 将它发送到我的 Web 应用程序,然后 uncompress/unencrypt 它返回到字节数组。我目前正在尝试使用 SharpZipLib 执行此操作。文件的压缩似乎按预期工作。我能够将文件保存到磁盘并使用 7zip 毫无问题地解压缩它。
我遇到的问题是当我在网络服务器上收到字节数组并尝试提取它时。
我在桌面端使用CompressData方式压缩数据
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 示例中逐字提取的):
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();
}
}
}
预期的结果是在服务器上取回我原来的字节数组。
在服务器上,当涉及到行时:
Stream zipStream = zipFile.GetInputStream(zipEntry);
我收到错误 'No password available for AES encrypted stream.'
我唯一看到设置密码的地方是在 ZipOutputStream 对象中,我在运行时检查过,这个设置正确。
解包时,密码必须赋给ZipFile
-实例的password
-属性,即必须在RecursiveExtractRebuild
-方法中设置(为此必须将密码添加为附加参数):
zipFile.Password = password;
如图this example.
需要注意的是,目前的DoRebuildData
-方法实际上并没有解压数据,而是re-packs it into a new zip。 DoRebuildData
-方法中的(可选)行:
zipOut.Password = password;
不指定解压密码(即旧 zip),但定义 新 zip 的密码。