diff --git a/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/SharpCompress/Common/Rar/RarCryptoWrapper.cs index 90dbe045..4094d6d7 100644 --- a/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -11,9 +11,8 @@ namespace SharpCompress.Common.Rar { private readonly Stream _actualStream; private byte[] _salt; - private Rijndael _rijndael; + private RarRijndael _rijndael; private readonly string _password; - private byte[] _aesInitializationVector; private Queue _data = new Queue(); public RarCryptoWrapper(Stream actualStream, string password) @@ -35,7 +34,7 @@ namespace SharpCompress.Common.Rar private void InitializeAes() { - _rijndael = RarRijndael.Initialize(out _aesInitializationVector, _password, _salt); + _rijndael = RarRijndael.InitializeFrom(_password, _salt); } @@ -75,33 +74,16 @@ namespace SharpCompress.Common.Rar byte[] cipherText = new byte[RarRijndael.CryptoBlockSize]; _actualStream.Read(cipherText, 0, RarRijndael.CryptoBlockSize); - byte[] plainText = new byte[RarRijndael.CryptoBlockSize]; - var decryptor = _rijndael.CreateDecryptor(); - using (MemoryStream msDecrypt = new MemoryStream(cipherText)) - { - using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) - { - csDecrypt.ReadFully(plainText); - } - } + + var readBytes = _rijndael.ProcessBlock(cipherText); + foreach(var readByte in readBytes) + _data.Enqueue(readByte); - for (int j = 0; j < plainText.Length; j++) - { - _data.Enqueue((byte) (plainText[j] ^ _aesInitializationVector[j%16])); //32:114, 33:101 - - } - - for (int j = 0; j < _aesInitializationVector.Length; j++) - { - _aesInitializationVector[j] = cipherText[j]; - } } for (int i = 0; i < count; i++) - { buffer[offset+i] = _data.Dequeue(); - } } return count; diff --git a/SharpCompress/Common/Rar/RarRijndael.cs b/SharpCompress/Common/Rar/RarRijndael.cs index 7a2106f4..e695f0bb 100644 --- a/SharpCompress/Common/Rar/RarRijndael.cs +++ b/SharpCompress/Common/Rar/RarRijndael.cs @@ -1,30 +1,42 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; namespace SharpCompress.Common.Rar { - class RarRijndael + class RarRijndael : IDisposable { + private readonly string _password; + private readonly byte[] _salt; + private byte[] _aesInitializationVector; + private Rijndael _rijndael; + + private RarRijndael(string password, byte[] salt) + { + _password = password; + _salt = salt; + } + internal const int CryptoBlockSize = 16; - internal static Rijndael Initialize(out byte[] aesInitializationVector, string password, byte[] salt) + private void Initialize() { - var rijndael = new RijndaelManaged() {Padding = PaddingMode.None}; - aesInitializationVector = new byte[CryptoBlockSize]; - int rawLength = 2 * password.Length; + _rijndael = new RijndaelManaged() {Padding = PaddingMode.None}; + _aesInitializationVector = new byte[CryptoBlockSize]; + int rawLength = 2 * _password.Length; byte[] rawPassword = new byte[rawLength + 8]; - byte[] passwordBytes = Encoding.UTF8.GetBytes(password); - for (int i = 0; i < password.Length; i++) + byte[] passwordBytes = Encoding.UTF8.GetBytes(_password); + for (int i = 0; i < _password.Length; i++) { rawPassword[i * 2] = passwordBytes[i]; rawPassword[i * 2 + 1] = 0; } - for (int i = 0; i < salt.Length; i++) + for (int i = 0; i < _salt.Length; i++) { - rawPassword[i + rawLength] = salt[i]; + rawPassword[i + rawLength] = _salt[i]; } var sha = new SHA1Managed(); @@ -40,7 +52,7 @@ namespace SharpCompress.Common.Rar if (i % (noOfRounds / CryptoBlockSize) == 0) { digest = sha.ComputeHash(bytes.ToArray()); - aesInitializationVector[i / (noOfRounds / CryptoBlockSize)] = digest[19]; + _aesInitializationVector[i / (noOfRounds / CryptoBlockSize)] = digest[19]; } } @@ -55,10 +67,44 @@ namespace SharpCompress.Common.Rar ((digest[i * 4 + 2] * 0x100) & 0xff00) | digest[i * 4 + 3] & 0xff) >> (j * 8)); - rijndael.IV = new byte[CryptoBlockSize]; - rijndael.Key = aesKey; - rijndael.BlockSize = CryptoBlockSize * 8; + _rijndael.IV = new byte[CryptoBlockSize]; + _rijndael.Key = aesKey; + _rijndael.BlockSize = CryptoBlockSize * 8; + return; + } + + public static RarRijndael InitializeFrom(string password, byte[] salt) + { + var rijndael = new RarRijndael(password, salt); + rijndael.Initialize(); return rijndael; } + + public byte[] ProcessBlock(byte[] cipherText) + { + var plainText = new byte[CryptoBlockSize]; + var decryptedBytes = new List(); + var decryptor = _rijndael.CreateDecryptor(); + using (var msDecrypt = new MemoryStream(cipherText)) + { + using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) + { + csDecrypt.ReadFully(plainText); + } + } + + for (int j = 0; j < plainText.Length; j++) + decryptedBytes.Add((byte)(plainText[j] ^ _aesInitializationVector[j % 16])); //32:114, 33:101 + + for (int j = 0; j < _aesInitializationVector.Length; j++) + _aesInitializationVector[j] = cipherText[j]; + + return decryptedBytes.ToArray(); + } + + public void Dispose() + { + _rijndael.Dispose(); + } } } diff --git a/SharpCompress/IO/MarkingBinaryReader.cs b/SharpCompress/IO/MarkingBinaryReader.cs index 53bff3a1..87e33dd6 100644 --- a/SharpCompress/IO/MarkingBinaryReader.cs +++ b/SharpCompress/IO/MarkingBinaryReader.cs @@ -14,7 +14,7 @@ namespace SharpCompress.IO private readonly string _password; private byte[] _aesInitializationVector; private byte[] _aesKey = new byte[16]; - private Rijndael _rijndael; + private RarRijndael _rijndael; private Queue _data = new Queue(); public MarkingBinaryReader(Stream stream, string password = null) @@ -38,7 +38,7 @@ namespace SharpCompress.IO private void InitializeAes() { - _rijndael = RarRijndael.Initialize(out _aesInitializationVector, _password, _salt); + _rijndael = RarRijndael.InitializeFrom(_password, _salt); } @@ -100,30 +100,9 @@ namespace SharpCompress.IO { //long ax = System.currentTimeMillis(); byte[] cipherText = base.ReadBytes(16); - - byte[] plainText = new byte[16]; - var decryptor = _rijndael.CreateDecryptor(); - using (MemoryStream msDecrypt = new MemoryStream(cipherText)) - { - using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) - { - - csDecrypt.ReadFully(plainText); - - } - } - - - for (int j = 0; j < plainText.Length; j++) - { - _data.Enqueue((byte)(plainText[j] ^ _aesInitializationVector[j % 16])); //32:114, 33:101 - - } - - for (int j = 0; j < _aesInitializationVector.Length; j++) - { - _aesInitializationVector[j] = cipherText[j]; - } + var readBytes = _rijndael.ProcessBlock(cipherText); + foreach (var readByte in readBytes) + _data.Enqueue(readByte); }