From c0b630c7956a0a94b34dfd920c858ab280ea16e4 Mon Sep 17 00:00:00 2001 From: Hamdanil Rasyid Date: Sat, 13 Jul 2013 20:12:35 +0800 Subject: [PATCH] Decrypt rar - first attempt, test still fails --- .../Common/Rar/Headers/RarHeaderFactory.cs | 9 +- SharpCompress/IO/MarkingBinaryReader.cs | 198 ++++++++++++++++-- 2 files changed, 183 insertions(+), 24 deletions(-) diff --git a/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index 3955b3f6..7b05a2ef 100644 --- a/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -110,12 +110,18 @@ namespace SharpCompress.Common.Rar.Headers return rewindableStream; } + private RarHeader ReadNextHeader(Stream stream) { - MarkingBinaryReader reader = new MarkingBinaryReader(stream); + if (IsEncrypted) { + reader.Salt = null; + reader.SkipQueue(); + Console.WriteLine(reader.BaseStream.Position); + byte[] salt = reader.ReadBytes(8); + reader.Salt = salt; } RarHeader header = RarHeader.Create(reader); @@ -161,6 +167,7 @@ namespace SharpCompress.Common.Rar.Headers } case HeaderType.FileHeader: { + Console.WriteLine(reader.BaseStream.Position); FileHeader fh = header.PromoteHeader(reader); switch (StreamingMode) { diff --git a/SharpCompress/IO/MarkingBinaryReader.cs b/SharpCompress/IO/MarkingBinaryReader.cs index f0154641..2d2f6a82 100644 --- a/SharpCompress/IO/MarkingBinaryReader.cs +++ b/SharpCompress/IO/MarkingBinaryReader.cs @@ -1,10 +1,21 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; namespace SharpCompress.IO { internal class MarkingBinaryReader : BinaryReader { + private byte[] _salt; + private string _password = "test"; + private byte[] _aesInitializationVector = new byte[16]; + private byte[] _aesKey = new byte[16]; + private Rijndael _rijndael; + private Queue _data = new Queue(); + public MarkingBinaryReader(Stream stream) : base(stream) { @@ -12,6 +23,82 @@ namespace SharpCompress.IO public long CurrentReadByteCount { get; private set; } + internal byte[] Salt + { + get { return _salt; } + set + { + _salt = value; + if (value != null) InitializeAes(); + + } + } + + private void InitializeAes() + { + _rijndael = new RijndaelManaged() {Padding = PaddingMode.None}; + 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++) + { + rawPassword[i * 2] = passwordBytes[i]; + rawPassword[i * 2 + 1] = 0; + } + for (int i = 0; i < _salt.Length; i++) + { + rawPassword[i + rawLength] = _salt[i]; + } + + // rawLength += 8; + + // SHA-1 + + var sha = new SHA1Managed(); + + const int noOfRounds = (1 << 18); + const int xh = noOfRounds / 16; + //List content = new ArrayList(); + IList bytes = new List(); + //byte[] input = null; + byte[] digest = null; + // byte[] pswNum = new byte[3]; + //long ax = System.currentTimeMillis(); + for (int i = 0; i < noOfRounds; i++) + { + bytes.AddRange(rawPassword); + + bytes.AddRange(new[] { (byte)i, (byte)(i >> 8), (byte)(i >> 16) }); + if (i % xh == 0) + { + + //long bx = System.currentTimeMillis(); + + + //long cx = System.currentTimeMillis(); + //System.out.println(cx-bx); + digest = sha.ComputeHash(bytes.ToArray()); + //AESInit[i / xh] = digest[digest.length-1]; + _aesInitializationVector[i / xh] = digest[19]; + } + } + + digest = sha.ComputeHash(bytes.ToArray()); + //System.out.println(System.currentTimeMillis()-ax); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + _aesKey[i * 4 + j] = (byte) + (((digest[i * 4] * 0x1000000) & 0xff000000 | + ((digest[i * 4 + 1] * 0x10000) & 0xff0000) | + ((digest[i * 4 + 2] * 0x100) & 0xff00) | + digest[i * 4 + 3] & 0xff) >> (j * 8)); + + _rijndael.IV = new byte[16]; + _rijndael.Key = _aesKey; + _rijndael.BlockSize = 16*8; + } + + public void Mark() { CurrentReadByteCount = 0; @@ -42,14 +129,66 @@ namespace SharpCompress.IO public override byte ReadByte() { - CurrentReadByteCount++; - return base.ReadByte(); + return ReadBytes(1).Single(); } public override byte[] ReadBytes(int count) { CurrentReadByteCount += count; - return base.ReadBytes(count); + return UseEncryption ? + ReadAndDecryptBytes(count) + : base.ReadBytes(count); + } + + protected bool UseEncryption + { + get { return Salt != null; } + } + + private byte[] ReadAndDecryptBytes(int count) + { + int queueSize = _data.Count; + int sizeToRead = count - queueSize; + + if (sizeToRead > 0) { + int alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf); + for(int i=0;i