Skip to content

[DRAFT][WIP]Add Zip Archives password support#122093

Draft
alinpahontu2912 wants to merge 66 commits intodotnet:mainfrom
alinpahontu2912:zip_password
Draft

[DRAFT][WIP]Add Zip Archives password support#122093
alinpahontu2912 wants to merge 66 commits intodotnet:mainfrom
alinpahontu2912:zip_password

Conversation

@alinpahontu2912
Copy link
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
Copilot AI review requested due to automatic review settings February 13, 2026 10:30
Copy link
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 29 out of 29 changed files in this pull request and generated 8 comments.

Copilot AI review requested due to automatic review settings February 16, 2026 11:19
Copy link
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 29 out of 29 changed files in this pull request and generated 1 comment.

Copy link
Member

@bartonjs bartonjs left a comment

Choose a reason for hiding this comment

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

General feedback:

  • Secrets (including an input password) should never be copied to the heap, unless it's utterly impractical.
  • Secrets (including an input password) should also only minimally be copied around on the stack.
  • Copied secrets should be cleared.
  • Avoid having cryptographic keys (HMAC, AES, etc) stored in arrays.

GitHub's current UI is making this change hard to holistically review, and it's marked as draft, so I've only sprinkled in the most important comments.

Comment on lines +415 to +423
private static void XorBytes(Span<byte> dest, ReadOnlySpan<byte> src)
{
Debug.Assert(dest.Length <= src.Length);

for (int i = 0; i < dest.Length; i++)
{
dest[i] ^= src[i];
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This undoubtedly could be vectorized to go faster, if you expect the operation to generally be bigger than a few bytes. Even just doing something like

Span<ulong> destUL = Marshal.As<byte, ulong>(dest);
ReadOnlySpan<ulong> srcUL = Marshal.As<byte, ulong>(src);

XorUL(destUL, srcUL);

for (int i = destUL.Length * sizeof(ulong); i < dest.Length; i++)
{
    ...
}

(Though I think if src/dest isn't QWORD aligned that might do something less happy on ARM?)

Copy link
Member

@rzikm rzikm Mar 5, 2026

Choose a reason for hiding this comment

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

Might be premature, but if we want to vectorize this, then approach with something like Vector<byte> might be better.

Copilot AI review requested due to automatic review settings March 5, 2026 11:02
Copy link
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 32 out of 32 changed files in this pull request and generated 9 comments.

Copilot AI review requested due to automatic review settings March 11, 2026 14:42
Copy link
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 34 out of 34 changed files in this pull request and generated 16 comments.

Copilot AI review requested due to automatic review settings March 13, 2026 09:32
Copy link
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 34 out of 34 changed files in this pull request and generated 9 comments.

Comment on lines +251 to +254
if (string.IsNullOrEmpty(password))
{
throw new ArgumentNullException(nameof(password), SR.EmptyPassword);
}
Comment on lines +718 to +722
public WinZipAesExtraField(ushort VendorVersion, byte AesStrength, ushort CompressionMethod)
{
this.VendorVersion = VendorVersion;
this.AesStrength = AesStrength;
this.CompressionMethod = CompressionMethod;
Comment on lines +807 to +821
BitFlagValues savedFlags = _generalPurposeBitFlag;
EncryptionMethod savedEncryption = Encryption;

// For AES entries: clear Encryption so WriteLocalFileHeaderAsync doesn't create a new
// AES extra field (the original one in _lhUnknownExtraFields will be used).
if (savedEncryption is EncryptionMethod.Aes128 or EncryptionMethod.Aes192 or EncryptionMethod.Aes256)
{
Encryption = EncryptionMethod.None;
}

await WriteLocalFileHeaderAsync(isEmptyFile: _uncompressedSize == 0, forceWrite: true, cancellationToken).ConfigureAwait(false);

// Restore original state
_generalPurposeBitFlag = savedFlags;
Encryption = savedEncryption;
/// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length.
/// For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.</exception>
/// <exception cref="DirectoryNotFoundException">The specified path is invalid, (for example, it is on an unmapped drive).</exception>
/// <exception cref="IOException">An archive entry?s name is zero-length, contains only whitespace, or contains one or more invalid
@@ -0,0 +1,106 @@
// The .NET Foundation licenses this file to you under the MIT license.
Comment on lines +55 to +66
byte[] encryptionKey = new byte[keySizeBytes];
Array.Copy(keyMaterial, offset, encryptionKey, 0, keySizeBytes);
offset += keySizeBytes;

byte[] hmacKey = new byte[keySizeBytes];
Array.Copy(keyMaterial, offset, hmacKey, 0, keySizeBytes);
offset += keySizeBytes;

byte[] passwordVerifier = new byte[2];
Array.Copy(keyMaterial, offset, passwordVerifier, 0, 2);

return new WinZipAesKeyMaterial(salt, encryptionKey, hmacKey, passwordVerifier, keySizeBits);
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

6 participants