public static WinZipAesCrypto Generate(string password, int KeyStrengthInBits)
        {
            WinZipAesCrypto c = new WinZipAesCrypto(password, KeyStrengthInBits);

            int saltSizeInBytes = c._KeyStrengthInBytes / 2;
            c._Salt = new byte[saltSizeInBytes];
            Random rnd = new Random();
            rnd.NextBytes(c._Salt);
            return c;
        }
        public static WinZipAesCrypto ReadFromStream(string password, int KeyStrengthInBits, Stream s)
        {
            // from http://www.winzip.com/aes_info.htm
            //
            // Size(bytes)   Content
            // -----------------------------------
            // Variable      Salt value
            // 2             Password verification value
            // Variable      Encrypted file data
            // 10            Authentication code
            //
            // ZipEntry.CompressedSize represents the size of all of those elements.

            // salt size varies with key length:
            //    128 bit key => 8 bytes salt
            //    192 bits => 12 bytes salt
            //    256 bits => 16 bytes salt

            WinZipAesCrypto c = new WinZipAesCrypto(password, KeyStrengthInBits);

            int saltSizeInBytes = c._KeyStrengthInBytes / 2;
            c._Salt = new byte[saltSizeInBytes];
            c._providedPv = new byte[2];

            s.Read(c._Salt, 0, c._Salt.Length);
            s.Read(c._providedPv, 0, c._providedPv.Length);

            c.PasswordVerificationStored = (Int16)(c._providedPv[0] + c._providedPv[1] * 256);
            if (password != null)
            {
                c.PasswordVerificationGenerated = (Int16)(c.GeneratedPV[0] + c.GeneratedPV[1] * 256);
                if (c.PasswordVerificationGenerated != c.PasswordVerificationStored)
                    throw new BadPasswordException("bad password");
            }

            return c;
        }
        internal WinZipAesCipherStream(System.IO.Stream s, WinZipAesCrypto cryptoParams, CryptoMode mode)
            : base()
        {
            TraceOutput("-------------------------------------------------------");
            TraceOutput("Create {0:X8}", this.GetHashCode());

            _params = cryptoParams;
            _s = s;
            _mode = mode;
            _nonce = 1;

            if (_params == null)
                throw new BadPasswordException("Supply a password to use AES encryption.");

            int keySizeInBits = _params.KeyBytes.Length * 8;
            if (keySizeInBits != 256 && keySizeInBits != 128 && keySizeInBits != 192)
                throw new ArgumentOutOfRangeException("keysize",
                                                      "size of key must be 128, 192, or 256");

            _mac = new HMACSHA1(_params.MacIv);

            _aesCipher = new System.Security.Cryptography.RijndaelManaged();
            _aesCipher.BlockSize = 128;
            _aesCipher.KeySize = keySizeInBits;  // 128, 192, 256
            _aesCipher.Mode = CipherMode.ECB;
            _aesCipher.Padding = PaddingMode.None;

            byte[] iv = new byte[BLOCK_SIZE_IN_BYTES]; // all zeroes

            // Create an ENCRYPTOR, regardless whether doing decryption or encryption.
            // It is reflexive.
            _xform = _aesCipher.CreateEncryptor(_params.KeyBytes, iv);

            if (_mode == CryptoMode.Encrypt)
            {
                _iobuf = new byte[2048];
                _PendingWriteBlock = new byte[BLOCK_SIZE_IN_BYTES];
            }


#if WANT_TRACE
                traceFileUntransformed = "unpack\\WinZipAesCipherStream.trace.untransformed.out";
            traceFileTransformed = "unpack\\WinZipAesCipherStream.trace.transformed.out";

            untransformed = System.IO.File.Create(traceFileUntransformed);
            transformed = System.IO.File.Create(traceFileTransformed);
#endif
        }
 /// <summary>
 /// The constructor.
 /// </summary>
 /// <param name="s">The underlying stream</param>
 /// <param name="mode">To either encrypt or decrypt.</param>
 /// <param name="cryptoParams">The pre-initialized WinZipAesCrypto object.</param>
 /// <param name="length">The maximum number of bytes to read from the stream.</param>
 internal WinZipAesCipherStream(System.IO.Stream s, WinZipAesCrypto cryptoParams, long length, CryptoMode mode)
     : this(s, cryptoParams, mode)
 {
     // don't read beyond this limit!
     _length = length;
     //Console.WriteLine("max length of AES stream: {0}", _length);
 }