private ZipCrypto SetupCipher(string password) { ZipCrypto cipher = null; // decrypt the file header data here if necessary. if (Encryption == EncryptionAlgorithm.PkzipWeak) { if (password == null) throw new BadPasswordException("This entry requires a password."); cipher = new ZipCrypto(); cipher.InitCipher(password); // Decrypt the header. This has a side effect of "further initializing the // encryption keys" in the traditional zip encryption. byte[] DecryptedHeader = cipher.DecryptMessage(_WeakEncryptionHeader, _WeakEncryptionHeader.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)((_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', the last byte of the decrypted // header is sometimes compared with the high-order byte of the lastmodified // time, and not the CRC, to verify the password. // // This is not documented in the PKWare Appnote.txt. // This was discovered this by analysis of the Crypt.c source file in the InfoZip library // http://www.info-zip.org/pub/infozip/ if ((_BitField & 0x0008) != 0x0008) { throw new BadPasswordException("The password did not match."); } else if (DecryptedHeader[11] != (byte)((_TimeBlob >> 8) & 0xff)) { throw new BadPasswordException("The password did not match."); } } // We have a good password. } return cipher; }