diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index a50676a4..b91bda4f 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -204,6 +204,7 @@ + diff --git a/ArcFormats/Dogenzaka/ImageRSA.cs b/ArcFormats/Dogenzaka/ImageRSA.cs index 3d77635a..4ce37333 100644 --- a/ArcFormats/Dogenzaka/ImageRSA.cs +++ b/ArcFormats/Dogenzaka/ImageRSA.cs @@ -29,6 +29,7 @@ using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; +using GameRes.Cryptography; namespace GameRes.Formats.Dogenzaka { @@ -89,72 +90,4 @@ namespace GameRes.Formats.Dogenzaka throw new NotImplementedException ("Rc4PngFormat.Write not implemented"); } } - - public sealed class Rc4Transform : ICryptoTransform - { - private const int StateLength = 256; - private const int BlockSize = 256; - private byte[] m_state = new byte[StateLength]; - private int x; - private int y; - private byte[] m_key; - - public bool CanReuseTransform { get { return false; } } - public bool CanTransformMultipleBlocks { get { return true; } } - public int InputBlockSize { get { return BlockSize; } } - public int OutputBlockSize { get { return BlockSize; } } - - public Rc4Transform (byte[] key) - { - m_key = key; - x = 0; - y = 0; - - for (int i = 0; i < StateLength; ++i) - { - m_state[i] = (byte)i; - } - - int i1 = 0; - int i2 = 0; - - for (int i = 0; i < StateLength; ++i) - { - i2 = ((m_key[i1] & 0xFF) + m_state[i] + i2) & 0xFF; - byte t = m_state[i]; - m_state[i] = m_state[i2]; - m_state[i2] = t; - i1 = (i1+1) % m_key.Length; - } - } - - public int TransformBlock (byte[] inBuf, int inOffset, int inCount, - byte[] outBuf, int outOffset) - { - for (int i = 0; i < inCount; i++) - { - x = (x + 1) & 0xFF; - y = (m_state[x] + y) & 0xFF; - - byte t = m_state[x]; - m_state[x] = m_state[y]; - m_state[y] = t; - - outBuf[i+outOffset] = (byte)(inBuf[i + inOffset] ^ m_state[(m_state[x] + m_state[y]) & 0xFF]); - } - return inCount; - } - - public byte[] TransformFinalBlock (byte[] inBuf, int inOffset, int inCount) - { - byte[] output = new byte[inCount]; - TransformBlock (inBuf, inOffset, inCount, output, 0); - return output; - } - - public void Dispose () - { - GC.SuppressFinalize (this); - } - } } diff --git a/ArcFormats/RC4.cs b/ArcFormats/RC4.cs new file mode 100644 index 00000000..d713e0da --- /dev/null +++ b/ArcFormats/RC4.cs @@ -0,0 +1,86 @@ +//! \file RC4.cs +//! \date Sat Oct 08 00:38:00 2016 +//! \brief RC4 encryption algorithm implementation. +// + +using System.Security.Cryptography; + +namespace GameRes.Cryptography +{ + public sealed class Rc4Transform : ICryptoTransform + { + private const int StateLength = 256; + private const int BlockSize = 1; + private byte[] m_state; + private int m_x; + private int m_y; + + public bool CanReuseTransform { get { return false; } } + public bool CanTransformMultipleBlocks { get { return true; } } + public int InputBlockSize { get { return BlockSize; } } + public int OutputBlockSize { get { return BlockSize; } } + + public byte[] State { get { return m_state; } } + + public Rc4Transform (byte[] key) + { + m_x = 0; + m_y = 0; + + m_state = new byte[StateLength]; + for (int i = 0; i < StateLength; ++i) + { + m_state[i] = (byte)i; + } + + int s = 0; + for (int i = 0; i < StateLength; ++i) + { + s = (key[i % key.Length] + m_state[i] + s) & 0xFF; + byte t = m_state[i]; + m_state[i] = m_state[s]; + m_state[s] = t; + } + } + + public byte NextByte () + { + m_x = (m_x + 1) & 0xFF; + byte a = m_state[m_x]; + m_y = (m_y + a) & 0xFF; + byte b = m_state[m_y]; + m_state[m_x] = b; + m_state[m_y] = a; + return m_state[(a + b) & 0xFF]; + } + + public byte[] GenerateBlock (int length) + { + var block = new byte[length]; + for (int i = 0; i < block.Length; ++i) + block[i] = NextByte(); + return block; + } + + public int TransformBlock (byte[] inBuf, int inOffset, int inCount, byte[] outBuf, int outOffset) + { + for (int i = 0; i < inCount; i++) + { + outBuf[i+outOffset] = (byte)(inBuf[i + inOffset] ^ NextByte()); + } + return inCount; + } + + public byte[] TransformFinalBlock (byte[] inBuf, int inOffset, int inCount) + { + byte[] output = new byte[inCount]; + TransformBlock (inBuf, inOffset, inCount, output, 0); + return output; + } + + public void Dispose () + { + System.GC.SuppressFinalize (this); + } + } +}