Ejemplo n.º 1
0
        private void _EmitOne(System.IO.Stream outstream, out ZipCrypto cipher)
        {
            // If PKZip (weak) encryption is in use, then the entry data is preceded by
            // 12-byte "encryption header" for the entry.
            byte[] encryptionHeader = null;
            cipher = null;
            if (_Password != null && Encryption == EncryptionAlgorithm.PkzipWeak)
            {
                cipher = new ZipCrypto();
                // apply the password to the keys
                cipher.InitCipher(_Password);

                // generate the random 12-byte header:
                var rnd = new System.Random();
                encryptionHeader = new byte[12];
                rnd.NextBytes(encryptionHeader);

                // Here, it is important to encrypt the random header, INCLUDING the final byte
                // which is the high-order byte of the CRC32.  We must do this before
                // we encrypt the file data.  This step changes the state of the cipher, or in the
                // words of the PKZIP spec, it "further initializes" the cipher keys.

                // No way around this: must read the stream to compute the actual CRC
                FigureCrc32();
                encryptionHeader[11] = (byte)((this._Crc32 >> 24) & 0xff);

                byte[] cipherText = cipher.EncryptMessage(encryptionHeader, encryptionHeader.Length);

                // Write the ciphered bonafide encryption header.
                outstream.Write(cipherText, 0, cipherText.Length);
            }

            // write the (potentially compressed, potentially encrypted) file data
            _WriteFileData(cipher, outstream);

            _TotalEntrySize = _LengthOfHeader + _CompressedSize;
        }
Ejemplo n.º 2
0
        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;
        }