in src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs [503:583]
private int StoredDescriptorEntry(byte[] destination, int offset, int count) =>
throw new StreamUnsupportedException(
"The combination of Stored compression method and Descriptor flag is not possible to read using ZipInputStream");
/// <summary>
/// Perform the initial read on an entry which may include
/// reading encryption headers and setting up inflation.
/// </summary>
/// <param name="destination">The destination to fill with data read.</param>
/// <param name="offset">The offset to start reading at.</param>
/// <param name="count">The maximum number of bytes to read.</param>
/// <returns>The actual number of bytes read.</returns>
private int InitialRead(byte[] destination, int offset, int count)
{
var usesDescriptor = (entry.Flags & (int)GeneralBitFlags.Descriptor) != 0;
// Handle encryption if required.
if (entry.IsCrypted)
{
if (password == null)
{
throw new ZipException("No password set.");
}
// Generate and set crypto transform...
var managed = new PkzipClassicManaged();
byte[] key = PkzipClassic.GenerateKeys(_stringCodec.ZipCryptoEncoding.GetBytes(password));
inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null);
byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize];
inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CryptoHeaderSize);
if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue)
{
throw new ZipException("Invalid password");
}
if (csize >= ZipConstants.CryptoHeaderSize)
{
csize -= ZipConstants.CryptoHeaderSize;
}
else if (!usesDescriptor)
{
throw new ZipException($"Entry compressed size {csize} too small for encryption");
}
}
else
{
inputBuffer.CryptoTransform = null;
}
if (csize > 0 || usesDescriptor)
{
if (method == CompressionMethod.Deflated && inputBuffer.Available > 0)
{
inputBuffer.SetInflaterInput(inf);
}
// It's not possible to know how many bytes to read when using "Stored" compression (unless using encryption)
if (!entry.IsCrypted && method == CompressionMethod.Stored && usesDescriptor)
{
internalReader = StoredDescriptorEntry;
return StoredDescriptorEntry(destination, offset, count);
}
if (!CanDecompressEntry)
{
internalReader = ReadingNotSupported;
return ReadingNotSupported(destination, offset, count);
}
internalReader = BodyRead;
return BodyRead(destination, offset, count);
}
internalReader = ReadingNotAvailable;
return 0;
}