Skip to content

Commit 89e7bdd

Browse files
authored
PR #554: Skip CRC calculation for AES zip entries
1 parent f044a6c commit 89e7bdd

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs

+13-4
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,9 @@ public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandl
960960

961961
if (testing && testData && this[entryIndex].IsFile)
962962
{
963+
// Don't check CRC for AES encrypted archives
964+
var checkCRC = this[entryIndex].AESKeySize == 0;
965+
963966
if (resultHandler != null)
964967
{
965968
status.SetOperation(TestOperation.EntryData);
@@ -975,7 +978,10 @@ public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandl
975978
int bytesRead;
976979
while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0)
977980
{
978-
crc.Update(new ArraySegment<byte>(buffer, 0, bytesRead));
981+
if (checkCRC)
982+
{
983+
crc.Update(new ArraySegment<byte>(buffer, 0, bytesRead));
984+
}
979985

980986
if (resultHandler != null)
981987
{
@@ -986,7 +992,7 @@ public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandl
986992
}
987993
}
988994

989-
if (this[entryIndex].Crc != crc.Value)
995+
if (checkCRC && this[entryIndex].Crc != crc.Value)
990996
{
991997
status.AddError();
992998

@@ -1000,7 +1006,8 @@ public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandl
10001006
var helper = new ZipHelperStream(baseStream_);
10011007
var data = new DescriptorData();
10021008
helper.ReadDataDescriptor(this[entryIndex].LocalHeaderRequiresZip64, data);
1003-
if (this[entryIndex].Crc != data.Crc)
1009+
1010+
if (checkCRC && this[entryIndex].Crc != data.Crc)
10041011
{
10051012
status.AddError();
10061013
resultHandler?.Invoke(status, "Descriptor CRC mismatch");
@@ -2687,6 +2694,8 @@ private void AddEntry(ZipFile workFile, ZipUpdate update)
26872694
}
26882695
}
26892696

2697+
var useCrc = update.Entry.AESKeySize == 0;
2698+
26902699
if (source != null)
26912700
{
26922701
using (source)
@@ -2711,7 +2720,7 @@ private void AddEntry(ZipFile workFile, ZipUpdate update)
27112720

27122721
using (Stream output = workFile.GetOutputStream(update.OutEntry))
27132722
{
2714-
CopyBytes(update, output, source, sourceStreamLength, true);
2723+
CopyBytes(update, output, source, sourceStreamLength, useCrc);
27152724
}
27162725

27172726
long dataEnd = workFile.baseStream_.Position;

src/ICSharpCode.SharpZipLib/Zip/ZipHelperStream.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ public int WriteDataDescriptor(ZipEntry entry)
565565
if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0)
566566
{
567567
// The signature is not PKZIP originally but is now described as optional
568-
// in the PKZIP Appnote documenting trhe format.
568+
// in the PKZIP Appnote documenting the format.
569569
WriteLEInt(ZipConstants.DataDescriptorSignature);
570570
WriteLEInt(unchecked((int)(entry.Crc)));
571571

@@ -599,7 +599,7 @@ public void ReadDataDescriptor(bool zip64, DescriptorData data)
599599
int intValue = ReadLEInt();
600600

601601
// In theory this may not be a descriptor according to PKZIP appnote.
602-
// In practise its always there.
602+
// In practice its always there.
603603
if (intValue != ZipConstants.DataDescriptorSignature)
604604
{
605605
throw new ZipException("Data descriptor signature not found");

src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs

+25-13
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,9 @@ public void PutNextEntry(ZipEntry entry)
500500
/// <summary>
501501
/// Closes the current entry, updating header and footer information as required
502502
/// </summary>
503+
/// <exception cref="ZipException">
504+
/// Invalid entry field values.
505+
/// </exception>
503506
/// <exception cref="System.IO.IOException">
504507
/// An I/O error occurs.
505508
/// </exception>
@@ -530,7 +533,7 @@ public void CloseEntry()
530533
}
531534
else if (curMethod == CompressionMethod.Stored)
532535
{
533-
// This is done by Finsh() for Deflated entries, but we need to do it
536+
// This is done by Finish() for Deflated entries, but we need to do it
534537
// ourselves for Stored ones
535538
base.GetAuthCodeIfAES();
536539
}
@@ -539,6 +542,19 @@ public void CloseEntry()
539542
if (curEntry.AESKeySize > 0)
540543
{
541544
baseOutputStream_.Write(AESAuthCode, 0, 10);
545+
// Always use 0 as CRC for AE-2 format
546+
curEntry.Crc = 0;
547+
}
548+
else
549+
{
550+
if (curEntry.Crc < 0)
551+
{
552+
curEntry.Crc = crc.Value;
553+
}
554+
else if (curEntry.Crc != crc.Value)
555+
{
556+
throw new ZipException($"crc was {crc.Value}, but {curEntry.Crc} was expected");
557+
}
542558
}
543559

544560
if (curEntry.Size < 0)
@@ -547,7 +563,7 @@ public void CloseEntry()
547563
}
548564
else if (curEntry.Size != size)
549565
{
550-
throw new ZipException("size was " + size + ", but I expected " + curEntry.Size);
566+
throw new ZipException($"size was {size}, but {curEntry.Size} was expected");
551567
}
552568

553569
if (curEntry.CompressedSize < 0)
@@ -556,16 +572,7 @@ public void CloseEntry()
556572
}
557573
else if (curEntry.CompressedSize != csize)
558574
{
559-
throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize);
560-
}
561-
562-
if (curEntry.Crc < 0)
563-
{
564-
curEntry.Crc = crc.Value;
565-
}
566-
else if (curEntry.Crc != crc.Value)
567-
{
568-
throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc);
575+
throw new ZipException($"compressed size was {csize}, but {curEntry.CompressedSize} expected");
569576
}
570577

571578
offset += csize;
@@ -718,7 +725,12 @@ public override void Write(byte[] buffer, int offset, int count)
718725
throw new ArgumentException("Invalid offset/count combination");
719726
}
720727

721-
crc.Update(new ArraySegment<byte>(buffer, offset, count));
728+
if (curEntry.AESKeySize == 0)
729+
{
730+
// Only update CRC if AES is not enabled
731+
crc.Update(new ArraySegment<byte>(buffer, offset, count));
732+
}
733+
722734
size += count;
723735

724736
switch (curMethod)

test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,12 @@ public void Encryption(ZipEncryptionMethod encryptionMethod)
193193
ZipEntry entry = zf[0];
194194
Assert.AreEqual(tempName1, entry.Name);
195195
Assert.AreEqual(1, entry.Size);
196-
Assert.IsTrue(zf.TestArchive(true));
196+
Assert.IsTrue(zf.TestArchive(true, TestStrategy.FindFirstError, (status, message) =>
197+
{
198+
if(!string.IsNullOrEmpty(message)) {
199+
Console.WriteLine($"{message} ({status.Entry?.Name ?? "-"})");
200+
}
201+
}));
197202
Assert.IsTrue(entry.IsCrypted);
198203

199204
switch (encryptionMethod)

0 commit comments

Comments
 (0)