Skip to content

Add Zip Archives password support#122093

Open
alinpahontu2912 wants to merge 94 commits into
dotnet:mainfrom
alinpahontu2912:zip_password
Open

Add Zip Archives password support#122093
alinpahontu2912 wants to merge 94 commits into
dotnet:mainfrom
alinpahontu2912:zip_password

Conversation

@alinpahontu2912
Copy link
Copy Markdown
Member

@alinpahontu2912 alinpahontu2912 commented Dec 2, 2025

Fixes #1545

Big Milestones and status:

  • Read Encrypted Entries (ZipCrypto, WinZip AES)
  • Create Encrypted Entries (ZipCrypto, Winzip AES)
  • Update Mode
  • Add runtime assets for checking compat with WinRar/7zip/WinZip/etc
  • Security check for Cryptography methods
  • Final API design

@rzikm rzikm self-requested a review December 11, 2025 12:22
@alinpahontu2912
Copy link
Copy Markdown
Member Author

Hey @bartonjs can you take a look again ?

Copilot AI review requested due to automatic review settings April 30, 2026 10:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 41 changed files in this pull request and generated 2 comments.

Copilot AI review requested due to automatic review settings May 7, 2026 10:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 41 changed files in this pull request and generated 4 comments.

Comment thread src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAesStream.cs Outdated
Comment thread src/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Copilot AI review requested due to automatic review settings May 7, 2026 13:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 7 comments.

Comment thread src/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Comment thread src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs Outdated
Comment thread src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAesStream.cs Outdated
}
else
{
// For decryption: HMAC first (on ciphertext), then XOR
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this data protocol correctly uses Encrypt-then-MAC (EtM), best practice (and internal security requirements) dictates that you should verify the MAC entirely before doing any decryption. As far as I can tell, this implementation allows decrypted data to be processed by a caller before the MAC is verified.

While that is the more performant approach, it will require a security process exception (ideally before the code is committed). Alternatively, change to verifying the MAC beforehand.

Maybe that discussion was already and and I'm not privy to it, but it's a flaw in implementation that I see here. cc: @blowdart @GrabYourPitchforks

Comment thread src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAesStream.cs Outdated
Comment thread src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAesStream.cs Outdated
Copilot AI review requested due to automatic review settings May 12, 2026 08:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 8 comments.

Comment thread src/libraries/System.IO.Compression/ref/System.IO.Compression.cs
Comment thread src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs
Comment on lines +17 to +18
private const string TestPassword = "test-password";
private const ushort PasswordVerifier = 0x1234;
Comment on lines +19 to +20
private const string TestPassword = "test-password";
private const ushort PasswordVerifier = 0x1234;
Comment on lines +37 to +38
private const string TestPassword = "test-password";

Comment on lines +972 to +975
public async Task DecryptEntries_SamePassword_7Zip(bool async)
{
string password = "S3cur3P@ssw0rd";
using Stream archiveStream = await StreamHelpers.CreateTempCopyStream(passwordProtected("PasswordProtected_7ZIP_SamePassword.zip"));
Copilot AI review requested due to automatic review settings May 12, 2026 14:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 7 comments.

Comment on lines +178 to +180
public System.Threading.Tasks.Task<System.IO.Stream> OpenAsync(System.IO.FileAccess access, System.ReadOnlySpan<char> password, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.Task<System.IO.Stream> OpenAsync(System.IO.FileAccess access, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.Task<System.IO.Stream> OpenAsync(System.ReadOnlySpan<char> password, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
Comment on lines +778 to +786
var crcStream = GetDataCompressor(encryptionStream, leaveBackingStreamOpen: true, onClose: null, streamForPosition: _archive.ArchiveStream);
await using (crcStream.ConfigureAwait(false))
{
_storedUncompressedData.Seek(0, SeekOrigin.Begin);
await _storedUncompressedData.CopyToAsync(crcStream, cancellationToken).ConfigureAwait(false);
}

// Restore CompressionMethod - AesCompressionMethodValue is used directly when writing headers
CompressionMethod = savedMethod;
Comment on lines +834 to +845
BitFlagValues savedFlags = _generalPurposeBitFlag;
ZipEncryptionMethod savedEncryption = Encryption;
ZipCompressionMethod savedCompressionMethod = CompressionMethod;

// For AES entries: set CompressionMethod to Aes so header writes method 99,
// but clear _encryptionMethod so WriteLocalFileHeaderAsync doesn't create a new
// AES extra field (the original one in _lhUnknownExtraFields will be used).
if (savedEncryption is ZipEncryptionMethod.Aes128 or ZipEncryptionMethod.Aes192 or ZipEncryptionMethod.Aes256)
{
CompressionMethod = (ZipCompressionMethod)WinZipAesMethod;
Encryption = ZipEncryptionMethod.None;
}
Comment on lines +131 to +135
if (overwrite && File.Exists(destinationFileName))
{
tempPath = Path.GetTempFileName();
extractPath = tempPath;
}
Comment on lines +137 to +146
// When overwriting, extract to a temporary file first to avoid corrupting the destination file
// if an exception occurs during extraction (e.g., password-protected archive, corrupted data).
string extractPath = destinationFileName;
string? tempPath = null;

if (overwrite && File.Exists(destinationFileName))
{
tempPath = Path.GetTempFileName();
extractPath = tempPath;
}
ThrowIfInvalidArchive();
ValidateAccessForMode(access);

if (IsEncrypted && password.IsEmpty)
Comment on lines +242 to +247

ZipArchiveEntry lastEntry = _entries[_entries.Count - 1];
if (lastEntry.IsEncrypted)
{
await lastEntry.ReadEncryptionSaltIfNeededAsync(cancellationToken).ConfigureAwait(false);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add password to ZipArchive

7 participants