private int ReadNextBlock(byte[] buffer, ref int offset, ref int count) { int length; var readBytes = 0; var blockPosition = Position % BlockSize_; var blockStart = Position - blockPosition; if (count <= 0 || Position >= Length) { return(readBytes); } // Read and decrypt SHA1 portion of the block var hashPartStream = new SubStream(_baseStream, blockStart, BlockHashSize_); if (blockPosition < BlockHashSize_) { var cbcHashPartStream = new CbcStream(hashPartStream, _partitionKey, new byte[0x10]); length = (int)Math.Min(BlockHashSize_ - blockPosition, count); cbcHashPartStream.Position = blockPosition; readBytes += cbcHashPartStream.Read(buffer, offset, length); Position += length; offset += length; count -= length; blockPosition = Position % BlockSize_; } if (count <= 0 || Position >= Length) { return(readBytes); } // Read and decrypt user data hashPartStream.Position = BlockDataIvStart_; var dataIv = new byte[0x10]; hashPartStream.Read(dataIv, 0, 0x10); var dataPartStream = new SubStream(_baseStream, blockStart + BlockHashSize_, BlockDataSize_); var cbcDataPartStream = new CbcStream(dataPartStream, _partitionKey, dataIv); length = (int)Math.Min(BlockSize_ - blockPosition, count); cbcDataPartStream.Position = blockPosition - BlockHashSize_; readBytes += cbcDataPartStream.Read(buffer, offset, length); Position += length; offset += length; count -= length; return(readBytes); }
public void ReadTest1() { var key = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; var iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; var content = new byte[] { 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e }; var ms = new MemoryStream(content); var cbc = new CbcStream(ms, key, iv); var result = new byte[16]; var expected = new byte[16]; cbc.Read(result, 0, 16); Assert.IsTrue(result.SequenceEqual(expected)); Assert.AreEqual(16, cbc.Position); Assert.AreEqual(0, ms.Position); }
private Task <bool> DoCipher(Stream input, Stream output, IProgress <ProgressReport> progress, bool decrypt) { var key = OnRequestKey("AES128 CBC Key", 32, out var error); if (key == null) { return(Task.Factory.StartNew(() => { progress.Report(new ProgressReport { Percentage = 0, Message = error }); return false; })); } var iv = OnRequestKey("AES128 CBC IV", 32, out error); if (iv == null) { return(Task.Factory.StartNew(() => { progress.Report(new ProgressReport { Percentage = 0, Message = error }); return false; })); } return(Task.Factory.StartNew(() => { progress.Report(new ProgressReport { Percentage = 0, Message = decrypt ? "Decryption..." : "Encryption..." }); using (var cbc = new CbcStream(decrypt ? input : output, key, iv)) { var buffer = new byte[0x10000]; var totalLength = decrypt ? cbc.Length : input.Length; while (cbc.Position < totalLength) { var length = (int)Math.Min(0x10000, totalLength - cbc.Position); if (decrypt) { cbc.Read(buffer, 0, length); output.Write(buffer, 0, length); } else { input.Read(buffer, 0, length); cbc.Write(buffer, 0, length); } progress.Report(new ProgressReport { Percentage = (double)cbc.Position / totalLength * 100, Message = decrypt ? "Decryption..." : "Encryption...", }); } } progress.Report(new ProgressReport { Percentage = 100, Message = decrypt ? "Decryption finished." : "Encryption finished." }); return true; })); }