diff --git a/src/ICSharpCode.SharpZipLib/Core/StreamUtils.cs b/src/ICSharpCode.SharpZipLib/Core/StreamUtils.cs
index 348fe68de..6d0d9b304 100644
--- a/src/ICSharpCode.SharpZipLib/Core/StreamUtils.cs
+++ b/src/ICSharpCode.SharpZipLib/Core/StreamUtils.cs
@@ -64,6 +64,54 @@ static public void ReadFully(Stream stream, byte[] buffer, int offset, int count
}
}
+ ///
+ /// Read as much data as possible from a ", up to the requested number of bytes
+ ///
+ /// The stream to read data from.
+ /// The buffer to store data in.
+ /// The offset at which to begin storing data.
+ /// The number of bytes of data to store.
+ /// Required parameter is null
+ /// and or are invalid.
+ static public int ReadRequestedBytes(Stream stream, byte[] buffer, int offset, int count)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException(nameof(stream));
+ }
+
+ if (buffer == null)
+ {
+ throw new ArgumentNullException(nameof(buffer));
+ }
+
+ // Offset can equal length when buffer and count are 0.
+ if ((offset < 0) || (offset > buffer.Length))
+ {
+ throw new ArgumentOutOfRangeException(nameof(offset));
+ }
+
+ if ((count < 0) || (offset + count > buffer.Length))
+ {
+ throw new ArgumentOutOfRangeException(nameof(count));
+ }
+
+ int totalReadCount = 0;
+ while (count > 0)
+ {
+ int readCount = stream.Read(buffer, offset, count);
+ if (readCount <= 0)
+ {
+ break;
+ }
+ offset += readCount;
+ count -= readCount;
+ totalReadCount += readCount;
+ }
+
+ return totalReadCount;
+ }
+
///
/// Copy the contents of one to another.
///
diff --git a/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs b/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs
index dc16a7c4d..cf0792c47 100644
--- a/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs
+++ b/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Security.Cryptography;
+using ICSharpCode.SharpZipLib.Core;
namespace ICSharpCode.SharpZipLib.Encryption
{
@@ -78,7 +79,7 @@ public override int Read(byte[] buffer, int offset, int count)
_slideBufFreePos -= _slideBufStartPos; // Note the -=
_slideBufStartPos = 0;
}
- int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead);
+ int obtained = StreamUtils.ReadRequestedBytes(_stream, _slideBuffer, _slideBufFreePos, lengthToRead);
_slideBufFreePos += obtained;
// Recalculate how much data we now have
diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
index fa4c09401..75d298922 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
@@ -3523,12 +3523,12 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry)
}
int saltLen = entry.AESSaltLen;
byte[] saltBytes = new byte[saltLen];
- int saltIn = baseStream.Read(saltBytes, 0, saltLen);
+ int saltIn = StreamUtils.ReadRequestedBytes(baseStream, saltBytes, 0, saltLen);
if (saltIn != saltLen)
throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn);
//
byte[] pwdVerifyRead = new byte[2];
- baseStream.Read(pwdVerifyRead, 0, 2);
+ StreamUtils.ReadFully(baseStream, pwdVerifyRead);
int blockSize = entry.AESKeySize / 8; // bits to bytes
var decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false);
diff --git a/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Streams.cs b/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Streams.cs
index dd8dd1dd9..f649e4175 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Streams.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Streams.cs
@@ -453,4 +453,22 @@ protected override void Dispose(bool disposing)
#endregion Instance Fields
}
+
+ internal class SingleByteReadingStream : MemoryStream
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SingleByteReadingStream()
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count > 0)
+ count = 1;
+
+ return base.Read(buffer, offset, count);
+ }
+ }
}
diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs
index 6d4c3d74b..bac6d2fb3 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.IO;
using System.Text;
+using ICSharpCode.SharpZipLib.Tests.TestSupport;
namespace ICSharpCode.SharpZipLib.Tests.Zip
{
@@ -56,6 +57,37 @@ public void ZipFileAesDecryption()
}
}
+ [Test]
+ [Category("Encryption")]
+ [Category("Zip")]
+ public void ZipFileAesRead()
+ {
+ var password = "password";
+
+ using (var ms = new SingleByteReadingStream())
+ {
+ WriteEncryptedZipToStream(ms, password, 256);
+ ms.Seek(0, SeekOrigin.Begin);
+
+ var zipFile = new ZipFile(ms)
+ {
+ Password = password
+ };
+
+ foreach (ZipEntry entry in zipFile)
+ {
+ if (!entry.IsFile) continue;
+
+ using (var zis = zipFile.GetInputStream(entry))
+ using (var sr = new StreamReader(zis, Encoding.UTF8))
+ {
+ var content = sr.ReadToEnd();
+ Assert.AreEqual(DummyDataString, content, "Decompressed content does not match input data");
+ }
+ }
+ }
+ }
+
private static readonly string[] possible7zPaths = new[] {
// Check in PATH
"7z", "7za",