123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- #if !NO_CRYPTO
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using SharpCompress.Converters;
- namespace SharpCompress.Common.Zip
- {
- internal class WinzipAesCryptoStream : Stream
- {
- private const int BLOCK_SIZE_IN_BYTES = 16;
- private readonly SymmetricAlgorithm _cipher;
- private readonly byte[] _counter = new byte[BLOCK_SIZE_IN_BYTES];
- private readonly Stream _stream;
- private readonly ICryptoTransform _transform;
- private int _nonce = 1;
- private byte[] _counterOut = new byte[BLOCK_SIZE_IN_BYTES];
- private bool _isFinalBlock;
- private long _totalBytesLeftToRead;
- private bool _isDisposed;
- internal WinzipAesCryptoStream(Stream stream, WinzipAesEncryptionData winzipAesEncryptionData, long length)
- {
- this._stream = stream;
- _totalBytesLeftToRead = length;
- _cipher = CreateCipher(winzipAesEncryptionData);
- var iv = new byte[BLOCK_SIZE_IN_BYTES];
- _transform = _cipher.CreateEncryptor(winzipAesEncryptionData.KeyBytes, iv);
- }
- private SymmetricAlgorithm CreateCipher(WinzipAesEncryptionData winzipAesEncryptionData)
- {
- var cipher = Aes.Create();
- cipher.BlockSize = BLOCK_SIZE_IN_BYTES * 8;
- cipher.KeySize = winzipAesEncryptionData.KeyBytes.Length * 8;
- cipher.Mode = CipherMode.ECB;
- cipher.Padding = PaddingMode.None;
- return cipher;
- }
- public override bool CanRead
- {
- get { return true; }
- }
- public override bool CanSeek
- {
- get { return false; }
- }
- public override bool CanWrite
- {
- get { return false; }
- }
- public override long Length
- {
- get { throw new NotSupportedException(); }
- }
- public override long Position
- {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
- protected override void Dispose(bool disposing)
- {
- if (_isDisposed)
- {
- return;
- }
- _isDisposed = true;
- if (disposing)
- {
- //read out last 10 auth bytes
- var ten = new byte[10];
- _stream.ReadFully(ten);
- _stream.Dispose();
- }
- }
- public override void Flush()
- {
- throw new NotSupportedException();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (_totalBytesLeftToRead == 0)
- {
- return 0;
- }
- int bytesToRead = count;
- if (count > _totalBytesLeftToRead)
- {
- bytesToRead = (int)_totalBytesLeftToRead;
- }
- int read = _stream.Read(buffer, offset, bytesToRead);
- _totalBytesLeftToRead -= read;
- ReadTransformBlocks(buffer, offset, read);
- return read;
- }
- private int ReadTransformOneBlock(byte[] buffer, int offset, int last)
- {
- if (_isFinalBlock)
- {
- throw new InvalidOperationException();
- }
- int bytesRemaining = last - offset;
- int bytesToRead = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
- ? BLOCK_SIZE_IN_BYTES
- : bytesRemaining;
- // update the counter
- DataConverter.LittleEndian.PutBytes(_counter, 0, _nonce++);
- // Determine if this is the final block
- if ((bytesToRead == bytesRemaining) && (_totalBytesLeftToRead == 0))
- {
- _counterOut = _transform.TransformFinalBlock(_counter,
- 0,
- BLOCK_SIZE_IN_BYTES);
- _isFinalBlock = true;
- }
- else
- {
- _transform.TransformBlock(_counter,
- 0, // offset
- BLOCK_SIZE_IN_BYTES,
- _counterOut,
- 0); // offset
- }
- XorInPlace(buffer, offset, bytesToRead);
- return bytesToRead;
- }
- private void XorInPlace(byte[] buffer, int offset, int count)
- {
- for (int i = 0; i < count; i++)
- {
- buffer[offset + i] = (byte)(_counterOut[i] ^ buffer[offset + i]);
- }
- }
- private void ReadTransformBlocks(byte[] buffer, int offset, int count)
- {
- int posn = offset;
- int last = count + offset;
- while (posn < buffer.Length && posn < last)
- {
- int n = ReadTransformOneBlock(buffer, posn, last);
- posn += n;
- }
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException();
- }
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
- }
- }
- #endif
|