/// <summary> /// Constructor /// </summary> /// <param name="stream">The stream on which to perform the cryptographic transformation.</param> /// <param name="transform">Instance of ZipAESTransform</param> /// <param name="mode">Read or Write</param> public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode) : base(stream, transform, mode) { _stream = stream; _transform = transform; _slideBuffer = new byte[1024]; _blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH; // mode: // CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method. // Write bypasses this stream and uses the Transform directly. if (mode != CryptoStreamMode.Read) { throw new Exception("ZipAESStream only for read"); } }
Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) { CryptoStream result = null; if ( (entry.Version < ZipConstants.VersionStrongEncryption) || (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, null), CryptoStreamMode.Read); CheckClassicPassword(result, entry); } else { #if !NET_1_1 && !NETCF_2_0 if (entry.Version == ZipConstants.VERSION_AES) { // OnKeysRequired(entry.Name); if (HaveKeys == false) { throw new ZipException("No password available for AES encrypted stream"); } int saltLen = entry.AESSaltLen; byte[] saltBytes = new byte[saltLen]; int saltIn = baseStream.Read(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); int blockSize = entry.AESKeySize / 8; // bits to bytes ZipAESTransform decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false); byte[] pwdVerifyCalc = decryptor.PwdVerifier; if (pwdVerifyCalc[0] != pwdVerifyRead[0] || pwdVerifyCalc[1] != pwdVerifyRead[1]) throw new Exception("Invalid password for AES"); result = new ZipAESStream(baseStream, decryptor, CryptoStreamMode.Read); } else #endif { throw new ZipException("Decryption method not supported"); } } return result; }