Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the Password property from DeflaterOutputStream into ZipOutputStream #604

Merged
merged 3 commits into from May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -153,37 +153,15 @@ public bool CanPatchEntries

#region Encryption

private string password;

private ICryptoTransform cryptoTransform_;

/// <summary>
/// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream.
/// The CryptoTransform currently being used to encrypt the compressed data.
/// </summary>
protected byte[] AESAuthCode;
protected ICryptoTransform cryptoTransform_;

/// <summary>
/// Get/set the password used for encryption.
/// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream.
/// </summary>
/// <remarks>When set to null or if the password is empty no encryption is performed</remarks>
public string Password
{
get
{
return password;
}
set
{
if ((value != null) && (value.Length == 0))
{
password = null;
}
else
{
password = value;
}
}
}
protected byte[] AESAuthCode;

/// <summary>
/// Encrypt a block of data
Expand All @@ -202,34 +180,6 @@ protected void EncryptBlock(byte[] buffer, int offset, int length)
cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0);
}

/// <summary>
/// Initializes encryption keys based on given <paramref name="password"/>.
/// </summary>
/// <param name="password">The password.</param>
protected void InitializePassword(string password)
{
var pkManaged = new PkzipClassicManaged();
byte[] key = PkzipClassic.GenerateKeys(ZipStrings.ConvertToArray(password));
cryptoTransform_ = pkManaged.CreateEncryptor(key, null);
}

/// <summary>
/// Initializes encryption keys based on given password.
/// </summary>
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
Expand Down Expand Up @@ -484,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
}
}
64 changes: 64 additions & 0 deletions 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;
Expand Down Expand Up @@ -154,6 +155,29 @@ public UseZip64 UseZip64
/// </summary>
public INameTransform NameTransform { get; set; } = new PathTransformer();

/// <summary>
/// Get/set the password used for encryption.
/// </summary>
/// <remarks>When set to null or if the password is empty no encryption is performed</remarks>
public string Password
{
get
{
return password;
}
set
{
if ((value != null) && (value.Length == 0))
{
password = null;
}
else
{
password = value;
}
}
}

/// <summary>
/// Write an unsigned short in little endian byte order.
/// </summary>
Expand Down Expand Up @@ -634,6 +658,34 @@ public void CloseEntry()
curEntry = null;
}

/// <summary>
/// Initializes encryption keys based on given <paramref name="password"/>.
/// </summary>
/// <param name="password">The password.</param>
private void InitializePassword(string password)
{
var pkManaged = new PkzipClassicManaged();
byte[] key = PkzipClassic.GenerateKeys(ZipStrings.ConvertToArray(password));
cryptoTransform_ = pkManaged.CreateEncryptor(key, null);
}

/// <summary>
/// Initializes encryption keys based on given password.
/// </summary>
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
_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;
Expand Down Expand Up @@ -1010,6 +1062,18 @@ public override void Flush()
// NOTE: Setting the size for entries before they are added is the best solution!
private UseZip64 useZip64_ = UseZip64.Dynamic;

/// <summary>
/// The password to use when encrypting archive entries.
/// </summary>
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
}
}