Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment with using ITaggedData for AES extra data handling #470

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 8 additions & 13 deletions src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs
Expand Up @@ -962,26 +962,21 @@ internal void ProcessExtraData(bool localHeader)
// For AES the method in the entry is 99, and the real compression method is in the extradata
private void ProcessAESExtraData(ZipExtraData extraData)
{
if (extraData.Find(0x9901))
var aesData = extraData.GetData<WinZipAESTaggedData>();

if (aesData != null)
{
// Set version for Zipfile.CreateAndInitDecryptionStream
versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter

//
// Unpack AES extra data field see http://www.winzip.com/aes_info.htm
int length = extraData.ValueLength; // Data size currently 7
if (length < 7)
throw new ZipException("AES Extra Data Length " + length + " invalid.");
int ver = extraData.ReadShort(); // Version number (1=AE-1 2=AE-2)
int vendorId = extraData.ReadShort(); // 2-character vendor ID 0x4541 = "AE"
int encrStrength = extraData.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256
int actualCompress = extraData.ReadShort(); // The actual compression method used to compress the file
_aesVer = ver;
_aesEncryptionStrength = encrStrength;
method = (CompressionMethod)actualCompress;
_aesVer = (int)aesData.Version;
_aesEncryptionStrength = aesData.EncryptionStrength;
method = aesData.CompressionMethod;
}
else
{
throw new ZipException("AES Extra Data missing");
}
}

/// <summary>
Expand Down
116 changes: 110 additions & 6 deletions src/ICSharpCode.SharpZipLib/Zip/ZipExtraData.cs
Expand Up @@ -15,7 +15,7 @@ public interface ITaggedData
/// <summary>
/// Get the ID for this tagged data value.
/// </summary>
short TagID { get; }
ushort TagID { get; }

/// <summary>
/// Set the contents of this instance from the data passed.
Expand All @@ -41,7 +41,7 @@ public class RawTaggedData : ITaggedData
/// Initialise a new instance.
/// </summary>
/// <param name="tag">The tag ID.</param>
public RawTaggedData(short tag)
public RawTaggedData(ushort tag)
{
_tag = tag;
}
Expand All @@ -51,7 +51,7 @@ public RawTaggedData(short tag)
/// <summary>
/// Get the ID for this tagged data value.
/// </summary>
public short TagID
public ushort TagID
{
get { return _tag; }
set { _tag = value; }
Expand Down Expand Up @@ -100,7 +100,7 @@ public byte[] Data
/// <summary>
/// The tag ID for this instance.
/// </summary>
private short _tag;
private ushort _tag;

private byte[] _data;

Expand Down Expand Up @@ -139,7 +139,7 @@ public enum Flags : byte
/// <summary>
/// Get the ID
/// </summary>
public short TagID
public ushort TagID
{
get { return 0x5455; }
}
Expand Down Expand Up @@ -328,7 +328,7 @@ public class NTTaggedData : ITaggedData
/// <summary>
/// Get the ID for this tagged data value.
/// </summary>
public short TagID
public ushort TagID
{
get { return 10; }
}
Expand Down Expand Up @@ -475,6 +475,110 @@ public DateTime LastAccessTime
#endregion Instance Fields
}

/// <summary>
/// A TaggedData for handling WinzipAES extra data.
/// </summary>
/// <remarks>
/// See http://www.winzip.com/aes_info.htm for format documentation.
/// </remarks>
internal class WinZipAESTaggedData : ITaggedData
{
/// <summary>
/// The Version used by this entry.
/// </summary>
/// <remarks>
/// AE-1 iS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored.
/// </remarks>
public enum VendorVersion : int
{
/// <summary>
/// Version AE-1.
/// </summary>
AE1 = 0x0001,

/// <summary>
/// Version AE-2.
/// </summary>
AE2 = 0x0002,
}

/// <summary>
/// Get the ID for this tagged data value.
/// </summary>
public ushort TagID => 0x9901;

/// <summary>
/// Set the data from the raw values provided.
/// </summary>
/// <param name="data">The raw data to extract values from.</param>
/// <param name="index">The index to start extracting values from.</param>
/// <param name="count">The number of bytes available.</param>
public void SetData(byte[] data, int index, int count)
{
using (MemoryStream ms = new MemoryStream(data, index, count, false))
using (ZipHelperStream helperStream = new ZipHelperStream(ms))
{
//
// Unpack AES extra data field see http://www.winzip.com/aes_info.htm
var length = helperStream.Length; // Data size currently 7
if (length < 7)
throw new ZipException("AES Extra Data Length " + length + " invalid.");

int ver = helperStream.ReadLEShort(); // Version number (1=AE-1 2=AE-2)
int vendorId = helperStream.ReadLEShort(); // 2-character vendor ID 0x4541 = "AE"
int encrStrength = helperStream.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256
int actualCompress = helperStream.ReadLEShort(); // The actual compression method used to compress the file

this.Version = (VendorVersion)ver;
this.EncryptionStrength = (byte)encrStrength;
this.CompressionMethod = (CompressionMethod)actualCompress;
}
}

/// <summary>
/// Get the binary data representing this instance.
/// </summary>
/// <returns>The raw binary data representing this instance.</returns>
public byte[] GetData()
{
using (MemoryStream ms = new MemoryStream())
using (ZipHelperStream helperStream = new ZipHelperStream(ms))
{
helperStream.IsStreamOwner = false;

// Vendor ID is the two ASCII characters "AE".
const int VENDOR_ID = 0x4541; //not 6965;

// Pack AES extra data field see http://www.winzip.com/aes_info.htm
// extraData.AddLeShort(7); // Data size (currently 7)
helperStream.WriteLEShort((int)this.Version); // Entry version
helperStream.WriteLEShort(VENDOR_ID); // "AE"
helperStream.WriteByte(this.EncryptionStrength); // 1 = 128, 2 = 192, 3 = 256
helperStream.WriteLEShort((int)this.CompressionMethod); // The actual compression method used to compress the file

return ms.ToArray();
}
}

/// <summary>
/// Get/set the <see cref="VendorVersion"> for this entry.</see>
/// </summary>
/// <remarks>
/// Defaults to 2 because we always use that when encrypting new entries.
/// </remarks>
public VendorVersion Version { get; set; } = VendorVersion.AE2;

/// <summary>
/// Get /set the real <see cref="CompressionMethod"> for this entry.</see>.
/// </summary>
public CompressionMethod CompressionMethod { get; set; }

/// <summary>
/// Get /set the encryption strength for this entry - 1 = 128 bit, 2 = 192 bit, 3 = 256 bit
/// </summary>
public byte EncryptionStrength { get; set; }
}

/// <summary>
/// A factory that creates <see cref="ITaggedData">tagged data</see> instances.
/// </summary>
Expand Down
19 changes: 7 additions & 12 deletions src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs
Expand Up @@ -706,18 +706,13 @@ private void WriteEncryptionHeader(long crcValue)

private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData)
{
// Vendor Version: AE-1 IS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored.
const int VENDOR_VERSION = 2;
// Vendor ID is the two ASCII characters "AE".
const int VENDOR_ID = 0x4541; //not 6965;
extraData.StartNewEntry();
// Pack AES extra data field see http://www.winzip.com/aes_info.htm
//extraData.AddLeShort(7); // Data size (currently 7)
extraData.AddLeShort(VENDOR_VERSION); // 2 = AE-2
extraData.AddLeShort(VENDOR_ID); // "AE"
extraData.AddData(entry.AESEncryptionStrength); // 1 = 128, 2 = 192, 3 = 256
extraData.AddLeShort((int)entry.CompressionMethod); // The actual compression method used to compress the file
extraData.AddNewEntry(0x9901);
var aesData = new WinZipAESTaggedData
{
CompressionMethod = entry.CompressionMethod,
EncryptionStrength = entry.AESEncryptionStrength,
};

extraData.AddEntry(aesData);
}

// Replaces WriteEncryptionHeader for AES
Expand Down