diff --git a/ArcFormats/Blowfish.cs b/ArcFormats/Blowfish.cs index 01576802..78722102 100644 --- a/ArcFormats/Blowfish.cs +++ b/ArcFormats/Blowfish.cs @@ -25,10 +25,11 @@ |***************************************************************************/ using System; -using System.Text; using System.IO; +using System.Security.Cryptography; +using GameRes.Utility; -namespace Simias.Encryption +namespace GameRes.Cryptography { /// /// Class that provides blowfish encryption. @@ -285,11 +286,6 @@ namespace Simias.Encryption } } - /// - /// - /// - /// - /// private uint F(uint x) { ushort a; @@ -443,235 +439,61 @@ namespace Simias.Encryption } } - public class BlowfishStream : Stream - { - class CBState : IAsyncResult - { - internal AsyncCallback callback; - internal object state; - internal byte[] buffer; - internal IAsyncResult result; - internal CBState(AsyncCallback callback, object state, byte[] buffer) + /// + /// ICryptoTransform implementation for use with CryptoStream. + /// + public sealed class BlowfishDecryptor : ICryptoTransform + { + Blowfish m_bf; + + public const int BlockSize = 8; + + public bool CanTransformMultipleBlocks { get { return true; } } + public bool CanReuseTransform { get { return true; } } + public int InputBlockSize { get { return BlockSize; } } + public int OutputBlockSize { get { return BlockSize; } } + + public BlowfishDecryptor (Blowfish bf) + { + m_bf = bf; + } + + public int TransformBlock (byte[] inBuffer, int offset, int count, byte[] outBuffer, int outOffset) + { + for (int i = 0; i < count; i += BlockSize) { - this.callback = callback; - this.state = state; - this.buffer = buffer; - } - #region IAsyncResult Members + uint xl = LittleEndian.ToUInt32 (inBuffer, offset+i); + uint xr = LittleEndian.ToUInt32 (inBuffer, offset+i+4); + m_bf.Decipher (ref xl, ref xr); + LittleEndian.Pack (xl, outBuffer, outOffset+i); + LittleEndian.Pack (xr, outBuffer, outOffset+i+4); + } + return count; + } - public object AsyncState - { - get - { - return state; - } - } + static readonly byte[] EmptyArray = new byte[0]; - public bool CompletedSynchronously - { - get - { - return result.CompletedSynchronously; - } - } + public byte[] TransformFinalBlock (byte[] inBuffer, int offset, int count) + { + if (0 == count) + return EmptyArray; + if (0 != count % BlockSize) + throw new InvalidDataException ("Non-padded block in Blowfish encrypted stream"); + var output = new byte[count]; + TransformBlock (inBuffer, offset, count, output, 0); + return output; + } - public System.Threading.WaitHandle AsyncWaitHandle - { - get - { - return result.AsyncWaitHandle; - } - } - - public bool IsCompleted - { - get - { - return result.IsCompleted; - } - } - - #endregion - } - - public enum Target - { - Encrypted, - Normal - }; - - Stream stream; - Blowfish bf; - Target target; - - BlowfishStream(Stream stream, Blowfish bf, Target target) - { - this.stream = stream; - this.bf = bf; - this.target = target; - } - - /// - /// Returns true if the stream support reads. - /// - public override bool CanRead - { - get {return stream.CanRead;} - } - - /// - /// Returns true is the stream supports seeks. - /// - public override bool CanSeek - { - get {return stream.CanSeek;} - } - - /// - /// Returns true if the stream supports writes. - /// - public override bool CanWrite - { - get {return stream.CanWrite;} - } - - /// - /// Returns the length of the stream. - /// - public override long Length - { - get {return stream.Length;} - } - - /// - /// Gets or Sets the posistion of the stream. - /// - public override long Position - { - get {return stream.Position;} - set {stream.Position = value;} - } - - /// - /// Flushes the stream. - /// - public override void Flush() - { - stream.Flush(); - } - - /// - /// Read data from the stream and encrypt it. - /// - /// The buffer to read into. - /// The offset in the buffer to begin storing data. - /// The number of bytes to read. - /// - public override int Read(byte[] buffer, int offset, int count) - { - int bytesRead = stream.Read(buffer, offset, count); - if (target == Target.Normal) - bf.Encipher(buffer, bytesRead); - else - bf.Decipher(buffer, bytesRead); - return bytesRead; - } - - /// - /// Write data to the stream after decrypting it. - /// - /// The buffer containing the data to write. - /// The offset in the buffer where the data begins. - /// The number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (target == Target.Normal) - bf.Decipher(buffer, count); - else - bf.Encipher(buffer, count); - stream.Write(buffer, offset, count); - } - - /// - /// - /// - /// - /// - /// - /// - /// - /// - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - CBState cbs = new CBState(callback, state, buffer); - cbs.result = base.BeginRead (buffer, offset, count, new AsyncCallback(ReadComplete), cbs); - return cbs; - } - - /// - /// - /// - /// - /// - public override int EndRead(IAsyncResult asyncResult) - { - CBState cbs = (CBState)asyncResult.AsyncState; - int bytesRead = base.EndRead (cbs.result); - if (target == Target.Normal) - bf.Encipher(cbs.buffer, bytesRead); - else - bf.Decipher(cbs.buffer, bytesRead); - return bytesRead; - } - - - /// - /// The Read has completed. - /// - /// The result of the async write. - private void ReadComplete(IAsyncResult result) - { - CBState cbs = (CBState)result.AsyncState; - cbs.callback(cbs); - } - - - /// - /// - /// - /// - /// - /// - /// - /// - /// - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - if (target == Target.Normal) - bf.Decipher(buffer, count); - else - bf.Encipher(buffer, count); - return base.BeginWrite (buffer, offset, count, callback, state); - } - - /// - /// Move the current stream posistion to the specified location. - /// - /// The offset from the origin to seek. - /// The origin to seek from. - /// The new position. - public override long Seek(long offset, SeekOrigin origin) - { - return stream.Seek(offset, origin); - } - - /// - /// Set the stream length. - /// - /// The length to set. - public override void SetLength(long value) - { - stream.SetLength(value); - } - } + #region IDisposable implementation + bool _disposed = false; + public void Dispose () + { + if (!_disposed) + { + _disposed = true; + } + GC.SuppressFinalize (this); + } + #endregion + } } diff --git a/ArcFormats/CatSystem/ArcINT.cs b/ArcFormats/CatSystem/ArcINT.cs index 8da3103d..fd0a93f8 100644 --- a/ArcFormats/CatSystem/ArcINT.cs +++ b/ArcFormats/CatSystem/ArcINT.cs @@ -30,7 +30,6 @@ using System.Text; using System.ComponentModel; using System.ComponentModel.Composition; using System.Collections.Generic; -using Simias.Encryption; using System.Runtime.InteropServices; using GameRes.Formats.Strings; using GameRes.Formats.Properties;