Skip to content

Commit 9bd70bd

Browse files
committed
Experiment with using ITaggedData for AES extra data handling
1 parent b5b1a92 commit 9bd70bd

File tree

3 files changed

+125
-31
lines changed

3 files changed

+125
-31
lines changed

src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -962,26 +962,21 @@ internal void ProcessExtraData(bool localHeader)
962962
// For AES the method in the entry is 99, and the real compression method is in the extradata
963963
private void ProcessAESExtraData(ZipExtraData extraData)
964964
{
965-
if (extraData.Find(0x9901))
965+
var aesData = extraData.GetData<WinZipAESTaggedData>();
966+
967+
if (aesData != null)
966968
{
967969
// Set version for Zipfile.CreateAndInitDecryptionStream
968970
versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter
969971

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

987982
/// <summary>

src/ICSharpCode.SharpZipLib/Zip/ZipExtraData.cs

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface ITaggedData
1515
/// <summary>
1616
/// Get the ID for this tagged data value.
1717
/// </summary>
18-
short TagID { get; }
18+
ushort TagID { get; }
1919

2020
/// <summary>
2121
/// Set the contents of this instance from the data passed.
@@ -41,7 +41,7 @@ public class RawTaggedData : ITaggedData
4141
/// Initialise a new instance.
4242
/// </summary>
4343
/// <param name="tag">The tag ID.</param>
44-
public RawTaggedData(short tag)
44+
public RawTaggedData(ushort tag)
4545
{
4646
_tag = tag;
4747
}
@@ -51,7 +51,7 @@ public RawTaggedData(short tag)
5151
/// <summary>
5252
/// Get the ID for this tagged data value.
5353
/// </summary>
54-
public short TagID
54+
public ushort TagID
5555
{
5656
get { return _tag; }
5757
set { _tag = value; }
@@ -100,7 +100,7 @@ public byte[] Data
100100
/// <summary>
101101
/// The tag ID for this instance.
102102
/// </summary>
103-
private short _tag;
103+
private ushort _tag;
104104

105105
private byte[] _data;
106106

@@ -139,7 +139,7 @@ public enum Flags : byte
139139
/// <summary>
140140
/// Get the ID
141141
/// </summary>
142-
public short TagID
142+
public ushort TagID
143143
{
144144
get { return 0x5455; }
145145
}
@@ -328,7 +328,7 @@ public class NTTaggedData : ITaggedData
328328
/// <summary>
329329
/// Get the ID for this tagged data value.
330330
/// </summary>
331-
public short TagID
331+
public ushort TagID
332332
{
333333
get { return 10; }
334334
}
@@ -475,6 +475,110 @@ public DateTime LastAccessTime
475475
#endregion Instance Fields
476476
}
477477

478+
/// <summary>
479+
/// A TaggedData for handling WinzipAES extra data.
480+
/// </summary>
481+
/// <remarks>
482+
/// See http://www.winzip.com/aes_info.htm for format documentation.
483+
/// </remarks>
484+
internal class WinZipAESTaggedData : ITaggedData
485+
{
486+
/// <summary>
487+
/// The Version used by this entry.
488+
/// </summary>
489+
/// <remarks>
490+
/// AE-1 iS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored.
491+
/// </remarks>
492+
public enum VendorVersion : int
493+
{
494+
/// <summary>
495+
/// Version AE-1.
496+
/// </summary>
497+
AE1 = 0x0001,
498+
499+
/// <summary>
500+
/// Version AE-2.
501+
/// </summary>
502+
AE2 = 0x0002,
503+
}
504+
505+
/// <summary>
506+
/// Get the ID for this tagged data value.
507+
/// </summary>
508+
public ushort TagID => 0x9901;
509+
510+
/// <summary>
511+
/// Set the data from the raw values provided.
512+
/// </summary>
513+
/// <param name="data">The raw data to extract values from.</param>
514+
/// <param name="index">The index to start extracting values from.</param>
515+
/// <param name="count">The number of bytes available.</param>
516+
public void SetData(byte[] data, int index, int count)
517+
{
518+
using (MemoryStream ms = new MemoryStream(data, index, count, false))
519+
using (ZipHelperStream helperStream = new ZipHelperStream(ms))
520+
{
521+
//
522+
// Unpack AES extra data field see http://www.winzip.com/aes_info.htm
523+
var length = helperStream.Length; // Data size currently 7
524+
if (length < 7)
525+
throw new ZipException("AES Extra Data Length " + length + " invalid.");
526+
527+
int ver = helperStream.ReadLEShort(); // Version number (1=AE-1 2=AE-2)
528+
int vendorId = helperStream.ReadLEShort(); // 2-character vendor ID 0x4541 = "AE"
529+
int encrStrength = helperStream.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256
530+
int actualCompress = helperStream.ReadLEShort(); // The actual compression method used to compress the file
531+
532+
this.Version = (VendorVersion)ver;
533+
this.EncryptionStrength = (byte)encrStrength;
534+
this.CompressionMethod = (CompressionMethod)actualCompress;
535+
}
536+
}
537+
538+
/// <summary>
539+
/// Get the binary data representing this instance.
540+
/// </summary>
541+
/// <returns>The raw binary data representing this instance.</returns>
542+
public byte[] GetData()
543+
{
544+
using (MemoryStream ms = new MemoryStream())
545+
using (ZipHelperStream helperStream = new ZipHelperStream(ms))
546+
{
547+
helperStream.IsStreamOwner = false;
548+
549+
// Vendor ID is the two ASCII characters "AE".
550+
const int VENDOR_ID = 0x4541; //not 6965;
551+
552+
// Pack AES extra data field see http://www.winzip.com/aes_info.htm
553+
// extraData.AddLeShort(7); // Data size (currently 7)
554+
helperStream.WriteLEShort((int)this.Version); // Entry version
555+
helperStream.WriteLEShort(VENDOR_ID); // "AE"
556+
helperStream.WriteByte(this.EncryptionStrength); // 1 = 128, 2 = 192, 3 = 256
557+
helperStream.WriteLEShort((int)this.CompressionMethod); // The actual compression method used to compress the file
558+
559+
return ms.ToArray();
560+
}
561+
}
562+
563+
/// <summary>
564+
/// Get/set the <see cref="VendorVersion"> for this entry.</see>
565+
/// </summary>
566+
/// <remarks>
567+
/// Defaults to 2 because we always use that when encrypting new entries.
568+
/// </remarks>
569+
public VendorVersion Version { get; set; } = VendorVersion.AE2;
570+
571+
/// <summary>
572+
/// Get /set the real <see cref="CompressionMethod"> for this entry.</see>.
573+
/// </summary>
574+
public CompressionMethod CompressionMethod { get; set; }
575+
576+
/// <summary>
577+
/// Get /set the encryption strength for this entry - 1 = 128 bit, 2 = 192 bit, 3 = 256 bit
578+
/// </summary>
579+
public byte EncryptionStrength { get; set; }
580+
}
581+
478582
/// <summary>
479583
/// A factory that creates <see cref="ITaggedData">tagged data</see> instances.
480584
/// </summary>

src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -706,18 +706,13 @@ private void WriteEncryptionHeader(long crcValue)
706706

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

723718
// Replaces WriteEncryptionHeader for AES

0 commit comments

Comments
 (0)