Exemplo n.º 1
0
		/// <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");
			}
		}
Exemplo n.º 2
0
        // File format for AES:
        // Size (bytes)   Content
        // ------------   -------
        // Variable       Salt value
        // 2              Password verification value
        // Variable       Encrypted file data
        // 10             Authentication code
        //
        // Value in the "compressed size" fields of the local file header and the central directory entry
        // is the total size of all the items listed above. In other words, it is the total size of the
        // salt value, password verification value, encrypted data, and authentication code.

        /// <summary>
        /// Initializes encryption keys based on given password.
        /// </summary>
        protected byte[] InitializeAESPassword(ZipEntry entry, string rawPassword)
        {
            var salt = new byte[entry.AESSaltLen];

            // Salt needs to be cryptographically random, and unique per file
            if (_aesRnd == null)
            {
                _aesRnd = RandomNumberGenerator.Create();
            }
            _aesRnd.GetBytes(salt);
            int blockSize = entry.AESKeySize / 8;               // bits to bytes

            cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true);

            var headBytes = new byte[salt.Length + 2];

            Array.Copy(salt, headBytes, salt.Length);
            Array.Copy(((ZipAESTransform)cryptoTransform_).PwdVerifier, 0,
                       headBytes, headBytes.Length - 2, 2);

            return(headBytes);
        }
Exemplo n.º 3
0
		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;
		}