public static ZipCrypto ForRead(string password, ZipEntry e) { Stream archiveStream = e._archiveStream; e._WeakEncryptionHeader = new byte[12]; byte[] weakEncryptionHeader = e._WeakEncryptionHeader; ZipCrypto zipCrypto = new ZipCrypto(); if (password == null) { throw new BadPasswordException("This entry requires a password."); } zipCrypto.InitCipher(password); ZipEntry.ReadWeakEncryptionHeader(archiveStream, weakEncryptionHeader); byte[] array = zipCrypto.DecryptMessage(weakEncryptionHeader, weakEncryptionHeader.Length); if (array[11] != (byte)(e._Crc32 >> 24 & 255)) { if ((e._BitField & 8) != 8) { throw new BadPasswordException("The password did not match."); } if (array[11] != (byte)(e._TimeBlob >> 8 & 255)) { throw new BadPasswordException("The password did not match."); } } return(zipCrypto); }
public override int Read(byte[] buffer, int offset, int count) { if (_mode == CryptoMode.Encrypt) { throw new NotSupportedException("This stream does not encrypt via Read()"); } if (buffer == null) { throw new ArgumentNullException("buffer"); } byte[] db = new byte[count]; int n = _s.Read(db, 0, count); byte[] decrypted = _cipher.DecryptMessage(db, n); for (int i = 0; i < n; i++) { buffer[offset + i] = decrypted[i]; } return(n); }
public static ZipCrypto ForRead(string password, ZipEntry e) { System.IO.Stream s = e._archiveStream; e._WeakEncryptionHeader = new byte[12]; byte[] eh = e._WeakEncryptionHeader; ZipCrypto z = new ZipCrypto(); if (password == null) { throw new BadPasswordException("This entry requires a password."); } z.InitCipher(password); ZipEntry.ReadWeakEncryptionHeader(s, eh); // Decrypt the header. This has a side effect of "further initializing the // encryption keys" in the traditional zip encryption. byte[] DecryptedHeader = z.DecryptMessage(eh, eh.Length); // CRC check // According to the pkzip spec, the final byte in the decrypted header // is the highest-order byte in the CRC. We check it here. if (DecryptedHeader[11] != (byte)((e._Crc32 >> 24) & 0xff)) { // In the case that bit 3 of the general purpose bit flag is set to // indicate the presence of an 'Extended File Header' or a 'data // descriptor' (signature 0x08074b50), the last byte of the decrypted // header is sometimes compared with the high-order byte of the // lastmodified time, rather than the high-order byte of the CRC, to // verify the password. // // This is not documented in the PKWare Appnote.txt. It was // discovered this by analysis of the Crypt.c source file in the // InfoZip library http://www.info-zip.org/pub/infozip/ // // The reason for this is that the CRC for a file cannot be known // until the entire contents of the file have been streamed. This // means a tool would have to read the file content TWICE in its // entirety in order to perform PKZIP encryption - once to compute // the CRC, and again to actually encrypt. // // This is so important for performance that using the timeblob as // the verification should be the standard practice for DotNetZip // when using PKZIP encryption. This implies that bit 3 must be // set. The downside is that some tools still cannot cope with ZIP // files that use bit 3. Therefore, DotNetZip DOES NOT force bit 3 // when PKZIP encryption is in use, and instead, reads the stream // twice. // if ((e._BitField & 0x0008) != 0x0008) { throw new BadPasswordException("The password did not match."); } else if (DecryptedHeader[11] != (byte)((e._TimeBlob >> 8) & 0xff)) { throw new BadPasswordException("The password did not match."); } // We have a good password. } else { // A-OK } return(z); }