From 14c973558b975d6288788fe53882517283b5a4ec Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Fri, 26 Jan 2024 10:54:41 -0500 Subject: [PATCH] Zip: Use last modified time from basic header when validating zip decryption The last modified time used for zip decryption validation must be the one from the basic header. If UnixTimeExtraFields are present, the previous implementation was attempting to verify against that value instead. Fixed #804 --- .../Common/Zip/Headers/DirectoryEntryHeader.cs | 4 ++-- .../Common/Zip/Headers/LocalEntryHeader.cs | 4 ++-- .../Common/Zip/Headers/ZipFileEntry.cs | 18 ++++++++++++++++++ .../Zip/PkwareTraditionalEncryptionData.cs | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index 184bdfa3..ef40a6f3 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -14,8 +14,8 @@ internal override void Read(BinaryReader reader) VersionNeededToExtract = reader.ReadUInt16(); Flags = (HeaderFlags)reader.ReadUInt16(); CompressionMethod = (ZipCompressionMethod)reader.ReadUInt16(); - LastModifiedTime = reader.ReadUInt16(); - LastModifiedDate = reader.ReadUInt16(); + OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); + OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index d0a87100..a7c83b24 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -13,8 +13,8 @@ internal override void Read(BinaryReader reader) Version = reader.ReadUInt16(); Flags = (HeaderFlags)reader.ReadUInt16(); CompressionMethod = (ZipCompressionMethod)reader.ReadUInt16(); - LastModifiedTime = reader.ReadUInt16(); - LastModifiedDate = reader.ReadUInt16(); + OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); + OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index 98d230f5..edba3ebe 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -67,8 +67,26 @@ internal PkwareTraditionalEncryptionData ComposeEncryptionData(Stream archiveStr internal WinzipAesEncryptionData WinzipAesEncryptionData { get; set; } + /// + /// The last modified date as read from the Local or Central Directory header. + /// + internal ushort OriginalLastModifiedDate { get; set; } + + /// + /// The last modified date from the UnixTimeExtraField, if present, or the + /// Local or Cental Directory header, if not. + /// internal ushort LastModifiedDate { get; set; } + /// + /// The last modified time as read from the Local or Central Directory header. + /// + internal ushort OriginalLastModifiedTime { get; set; } + + /// + /// The last modified time from the UnixTimeExtraField, if present, or the + /// Local or Cental Directory header, if not. + /// internal ushort LastModifiedTime { get; set; } internal uint Crc { get; set; } diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index 353000d8..d6c4e96d 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs @@ -39,7 +39,7 @@ byte[] encryptionHeader { throw new CryptographicException("The password did not match."); } - if (plainTextHeader[11] != (byte)((header.LastModifiedTime >> 8) & 0xff)) + if (plainTextHeader[11] != (byte)((header.OriginalLastModifiedTime >> 8) & 0xff)) { throw new CryptographicException("The password did not match."); }