From 00871badc11bbd010dd2037fbd174dc8fc1c2e65 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Sun, 14 Mar 2021 23:22:58 +0000 Subject: [PATCH 1/3] Move the Password property from DeflaterOutputStream into ZipOutputStream --- .../Streams/DeflaterOutputStream.cs | 25 ----------------- .../Zip/ZipOutputStream.cs | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index 03cac7358..7a43c42a2 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -153,8 +153,6 @@ public bool CanPatchEntries #region Encryption - private string password; - private ICryptoTransform cryptoTransform_; /// @@ -162,29 +160,6 @@ public bool CanPatchEntries /// protected byte[] AESAuthCode; - /// - /// Get/set the password used for encryption. - /// - /// When set to null or if the password is empty no encryption is performed - public string Password - { - get - { - return password; - } - set - { - if ((value != null) && (value.Length == 0)) - { - password = null; - } - else - { - password = value; - } - } - } - /// /// Encrypt a block of data /// diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs index e2c0426fd..5a91ef554 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs @@ -154,6 +154,29 @@ public UseZip64 UseZip64 /// public INameTransform NameTransform { get; set; } = new PathTransformer(); + /// + /// Get/set the password used for encryption. + /// + /// When set to null or if the password is empty no encryption is performed + public string Password + { + get + { + return password; + } + set + { + if ((value != null) && (value.Length == 0)) + { + password = null; + } + else + { + password = value; + } + } + } + /// /// Write an unsigned short in little endian byte order. /// @@ -1010,6 +1033,11 @@ public override void Flush() // NOTE: Setting the size for entries before they are added is the best solution! private UseZip64 useZip64_ = UseZip64.Dynamic; + /// + /// The password to use when encrypting archive entries. + /// + private string password; + #endregion Instance Fields } } From 2c30b8e8b753ea2f2e5246da1f7e1e8aee33a122 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Wed, 28 Apr 2021 17:36:53 +0100 Subject: [PATCH 2/3] Move cryptoTransform setup machinery from DeflatorOutputStream to ZipOutputStream --- .../Streams/DeflaterOutputStream.cs | 40 ++----------------- .../Zip/ZipOutputStream.cs | 36 +++++++++++++++++ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index 7a43c42a2..b6d4025d1 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -153,7 +153,10 @@ public bool CanPatchEntries #region Encryption - private ICryptoTransform cryptoTransform_; + /// + /// The CryptoTransform currently being used to encrypt the compressed data. + /// + protected ICryptoTransform cryptoTransform_; /// /// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream. @@ -177,34 +180,6 @@ protected void EncryptBlock(byte[] buffer, int offset, int length) cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); } - /// - /// Initializes encryption keys based on given . - /// - /// The password. - protected void InitializePassword(string password) - { - var pkManaged = new PkzipClassicManaged(); - byte[] key = PkzipClassic.GenerateKeys(ZipStrings.ConvertToArray(password)); - cryptoTransform_ = pkManaged.CreateEncryptor(key, null); - } - - /// - /// Initializes encryption keys based on given password. - /// - protected void InitializeAESPassword(ZipEntry entry, string rawPassword, - out byte[] salt, out byte[] pwdVerifier) - { - salt = new byte[entry.AESSaltLen]; - // Salt needs to be cryptographically random, and unique per file - if (_aesRnd == null) - _aesRnd = RandomNumberGenerator.Create(); - _aesRnd.GetBytes(salt); - int blockSize = entry.AESKeySize / 8; // bits to bytes - - cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); - pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; - } - #endregion Encryption #region Deflation Support @@ -459,12 +434,5 @@ public override void Write(byte[] buffer, int offset, int count) private bool isClosed_; #endregion Instance Fields - - #region Static Fields - - // Static to help ensure that multiple files within a zip will get different random salt - private static RandomNumberGenerator _aesRnd = RandomNumberGenerator.Create(); - - #endregion Static Fields } } diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs index 5a91ef554..3fb475b5f 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs @@ -1,5 +1,6 @@ using ICSharpCode.SharpZipLib.Checksum; using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Encryption; using ICSharpCode.SharpZipLib.Zip.Compression; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using System; @@ -657,6 +658,34 @@ public void CloseEntry() curEntry = null; } + /// + /// Initializes encryption keys based on given . + /// + /// The password. + private void InitializePassword(string password) + { + var pkManaged = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipStrings.ConvertToArray(password)); + cryptoTransform_ = pkManaged.CreateEncryptor(key, null); + } + + /// + /// Initializes encryption keys based on given password. + /// + private void InitializeAESPassword(ZipEntry entry, string rawPassword, + out byte[] salt, out byte[] pwdVerifier) + { + salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file + if (_aesRnd == null) + _aesRnd = RandomNumberGenerator.Create(); + _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); + pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; + } + private void WriteEncryptionHeader(long crcValue) { offset += ZipConstants.CryptoHeaderSize; @@ -1039,5 +1068,12 @@ public override void Flush() private string password; #endregion Instance Fields + + #region Static Fields + + // Static to help ensure that multiple files within a zip will get different random salt + private static RandomNumberGenerator _aesRnd = RandomNumberGenerator.Create(); + + #endregion Static Fields } } From c15cb91b6dc5cb5d0681eb2a2572a576207f384e Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Wed, 28 Apr 2021 19:52:57 +0100 Subject: [PATCH 3/3] remove duplicate setup of _aesRnd --- src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs index 3fb475b5f..79d65f560 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs @@ -676,10 +676,10 @@ private void InitializePassword(string password) out byte[] salt, out byte[] pwdVerifier) { salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file - if (_aesRnd == null) - _aesRnd = RandomNumberGenerator.Create(); _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true);