Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) { CryptoStream result = null; if (entry.Version < ZipConstants.VERSION_STRONG_ENCRYPTION || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { PkzipClassicManaged classicManaged = new PkzipClassicManaged(); OnKeysRequired(entry.Name); if (HaveKeys == false) { throw new ZipException("No password available for encrypted stream"); } result = new CryptoStream(baseStream, classicManaged.CreateDecryptor(key, iv), CryptoStreamMode.Read); CheckClassicPassword(result, entry); } else { throw new ZipException("Decryption method not supported"); } return result; }
// Perform the initial read on an entry which may include // reading encryption headers and setting up inflation. int InitialRead(byte[] destination, int offset, int count) { if (entry.Version > ZipConstants.VERSION_MADE_BY) { throw new ZipException("Libray cannot extract this entry version required (" + entry.Version.ToString() + ")"); } // test for encryption if (entry.IsCrypted) { if (password == null) { throw new ZipException("No password set."); } // Generate and set crypto transform... PkzipClassicManaged managed = new PkzipClassicManaged(); byte[] key = PkzipClassic.GenerateKeys(Encoding.ASCII.GetBytes(password)); inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null); byte[] cryptbuffer = new byte[ZipConstants.CRYPTO_HEADER_SIZE]; inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CRYPTO_HEADER_SIZE); if ((flags & 8) == 0) { if (cryptbuffer[ZipConstants.CRYPTO_HEADER_SIZE - 1] != (byte)(entry.Crc >> 24)) { throw new ZipException("Invalid password"); } } else { if (cryptbuffer[ZipConstants.CRYPTO_HEADER_SIZE - 1] != (byte)((entry.DosTime >> 8) & 0xff)) { throw new ZipException("Invalid password"); } } if (csize >= ZipConstants.CRYPTO_HEADER_SIZE) { csize -= ZipConstants.CRYPTO_HEADER_SIZE; } } else { inputBuffer.CryptoTransform = null; } if (method == (int)CompressionMethod.Deflated && inputBuffer.Available > 0) { inputBuffer.SetInflaterInput(inf); } internalReader = new ReaderDelegate(BodyRead); return BodyRead(destination, offset, count); }