Skip to content

Commit c328b3c

Browse files
committed
Attempt to get AES decryption working in the case where reading the underlying stream returns less data than requested.
1 parent 1847274 commit c328b3c

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

src/ICSharpCode.SharpZipLib/Core/StreamUtils.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,54 @@ static public void ReadFully(Stream stream, byte[] buffer, int offset, int count
6464
}
6565
}
6666

67+
/// <summary>
68+
/// Read as much data as possible from a <see cref="Stream"/>", up to the requested number of bytes
69+
/// </summary>
70+
/// <param name="stream">The stream to read data from.</param>
71+
/// <param name="buffer">The buffer to store data in.</param>
72+
/// <param name="offset">The offset at which to begin storing data.</param>
73+
/// <param name="count">The number of bytes of data to store.</param>
74+
/// <exception cref="ArgumentNullException">Required parameter is null</exception>
75+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> and or <paramref name="count"/> are invalid.</exception>
76+
static public int ReadRequestedBytes(Stream stream, byte[] buffer, int offset, int count)
77+
{
78+
if (stream == null)
79+
{
80+
throw new ArgumentNullException(nameof(stream));
81+
}
82+
83+
if (buffer == null)
84+
{
85+
throw new ArgumentNullException(nameof(buffer));
86+
}
87+
88+
// Offset can equal length when buffer and count are 0.
89+
if ((offset < 0) || (offset > buffer.Length))
90+
{
91+
throw new ArgumentOutOfRangeException(nameof(offset));
92+
}
93+
94+
if ((count < 0) || (offset + count > buffer.Length))
95+
{
96+
throw new ArgumentOutOfRangeException(nameof(count));
97+
}
98+
99+
int totalReadCount = 0;
100+
while (count > 0)
101+
{
102+
int readCount = stream.Read(buffer, offset, count);
103+
if (readCount <= 0)
104+
{
105+
break;
106+
}
107+
offset += readCount;
108+
count -= readCount;
109+
totalReadCount += readCount;
110+
}
111+
112+
return totalReadCount;
113+
}
114+
67115
/// <summary>
68116
/// Copy the contents of one <see cref="Stream"/> to another.
69117
/// </summary>

src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.Security.Cryptography;
4+
using ICSharpCode.SharpZipLib.Core;
45

56
namespace ICSharpCode.SharpZipLib.Encryption
67
{
@@ -78,7 +79,7 @@ public override int Read(byte[] buffer, int offset, int count)
7879
_slideBufFreePos -= _slideBufStartPos; // Note the -=
7980
_slideBufStartPos = 0;
8081
}
81-
int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead);
82+
int obtained = StreamUtils.ReadRequestedBytes(_stream, _slideBuffer, _slideBufFreePos, lengthToRead);
8283
_slideBufFreePos += obtained;
8384

8485
// Recalculate how much data we now have

src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,12 +3523,12 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry)
35233523
}
35243524
int saltLen = entry.AESSaltLen;
35253525
byte[] saltBytes = new byte[saltLen];
3526-
int saltIn = baseStream.Read(saltBytes, 0, saltLen);
3526+
int saltIn = StreamUtils.ReadRequestedBytes(baseStream, saltBytes, 0, saltLen);
35273527
if (saltIn != saltLen)
35283528
throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn);
35293529
//
35303530
byte[] pwdVerifyRead = new byte[2];
3531-
baseStream.Read(pwdVerifyRead, 0, 2);
3531+
StreamUtils.ReadFully(baseStream, pwdVerifyRead);
35323532
int blockSize = entry.AESKeySize / 8; // bits to bytes
35333533

35343534
var decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false);

0 commit comments

Comments
 (0)