Skip to content

Commit 44da647

Browse files
committed
Experiment with using ITaggedData for AES extra data handling
1 parent f36ca37 commit 44da647

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
@@ -1129,26 +1129,21 @@ private DateTime GetDateTime(ZipExtraData extraData)
11291129
//
11301130
private void ProcessAESExtraData(ZipExtraData extraData)
11311131
{
1132-
if (extraData.Find(0x9901))
1132+
var aesData = extraData.GetData<WinZipAESTaggedData>();
1133+
1134+
if (aesData != null)
11331135
{
11341136
// Set version for Zipfile.CreateAndInitDecryptionStream
11351137
versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter
11361138

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

11541149
/// <summary>

src/ICSharpCode.SharpZipLib/Zip/ZipExtraData.cs

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

1919
/// <summary>
2020
/// Set the contents of this instance from the data passed.
@@ -40,7 +40,7 @@ public class RawTaggedData : ITaggedData
4040
/// Initialise a new instance.
4141
/// </summary>
4242
/// <param name="tag">The tag ID.</param>
43-
public RawTaggedData(short tag)
43+
public RawTaggedData(ushort tag)
4444
{
4545
_tag = tag;
4646
}
@@ -50,7 +50,7 @@ public RawTaggedData(short tag)
5050
/// <summary>
5151
/// Get the ID for this tagged data value.
5252
/// </summary>
53-
public short TagID
53+
public ushort TagID
5454
{
5555
get { return _tag; }
5656
set { _tag = value; }
@@ -99,7 +99,7 @@ public byte[] Data
9999
/// <summary>
100100
/// The tag ID for this instance.
101101
/// </summary>
102-
private short _tag;
102+
private ushort _tag;
103103

104104
private byte[] _data;
105105

@@ -138,7 +138,7 @@ public enum Flags : byte
138138
/// <summary>
139139
/// Get the ID
140140
/// </summary>
141-
public short TagID
141+
public ushort TagID
142142
{
143143
get { return 0x5455; }
144144
}
@@ -327,7 +327,7 @@ public class NTTaggedData : ITaggedData
327327
/// <summary>
328328
/// Get the ID for this tagged data value.
329329
/// </summary>
330-
public short TagID
330+
public ushort TagID
331331
{
332332
get { return 10; }
333333
}
@@ -474,6 +474,110 @@ public DateTime LastAccessTime
474474
#endregion Instance Fields
475475
}
476476

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

src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs

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

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

626621
// Replaces WriteEncryptionHeader for AES

0 commit comments

Comments
 (0)