(IDecryptExtra): added Encrypt methods.

This commit is contained in:
morkt 2016-09-07 20:34:36 +04:00
parent d8531398d9
commit f12b65dc37

View File

@ -64,6 +64,65 @@ namespace GameRes.Formats.ShiinaRio
} }
public void Decrypt (byte[] data, int index, uint data_length) public void Decrypt (byte[] data, int index, uint data_length)
{
DoEncryption (data, index, data_length, DecryptContent);
}
public void Encrypt (byte[] data, int index, uint data_length)
{
DoEncryption (data, index, data_length, EncryptContent);
}
public void DecryptIndex (uint index_offset, byte[] index)
{
Decrypt (index, 0, (uint)index.Length);
XorIndex (index_offset, index);
}
public void EncryptIndex (uint index_offset, byte[] index)
{
XorIndex (index_offset, index);
Encrypt (index, 0, (uint)index.Length);
}
void DecryptContent (int x, byte[] data, int index, uint length)
{
int n = 0;
for (int i = 2; i < length; ++i)
{
byte d = data[index+i];
if (WarcVersion > 120)
d ^= (byte)((double)NextRand() / 16777216.0);
d = Binary.RotByteR (d, 1);
d ^= (byte)(m_scheme.CryptKey[n++] ^ m_scheme.CryptKey[x]);
data[index+i] = d;
x = d % m_scheme.CryptKey.Length;
if (n >= m_scheme.CryptKey.Length)
n = 0;
}
}
void EncryptContent (int x, byte[] data, int index, uint length)
{
int n = 0;
for (int i = 2; i < length; ++i)
{
byte k = (byte)(m_scheme.CryptKey[n++] ^ m_scheme.CryptKey[x]);
byte d = data[index+i];
x = d % m_scheme.CryptKey.Length;
d ^= k;
d = Binary.RotByteL (d, 1);
if (WarcVersion > 120)
d ^= (byte)((double)NextRand() / 16777216.0);
data[index+i] = d;
if (n >= m_scheme.CryptKey.Length)
n = 0;
}
}
delegate void ContentEncryptor (int start_key, byte[] data, int index, uint length);
void DoEncryption (byte[] data, int index, uint data_length, ContentEncryptor encryptor)
{ {
if (data_length < 3) if (data_length < 3)
return; return;
@ -130,40 +189,22 @@ namespace GameRes.Formats.ShiinaRio
if (b < 0) if (b < 0)
token = 360.0 - token; token = 360.0 - token;
uint x = (fac + (byte)DecryptHelper2 (token)) % (uint)m_scheme.CryptKey.Length; int x = (int)((fac + (byte)DecryptHelper2 (token)) % (uint)m_scheme.CryptKey.Length);
int n = 0; encryptor (x, data, index, effective_length);
for (int i = 2; i < effective_length; ++i)
{
byte d = data[index+i];
if (WarcVersion > 120)
d ^= (byte)((double)NextRand() / 16777216.0);
else
d ^= (byte)((double)NextRand() / 4294967296.0); // ? effectively a no-op
d = Binary.RotByteR (d, 1);
d ^= (byte)(m_scheme.CryptKey[n++] ^ m_scheme.CryptKey[x]);
data[index+i] = d;
x = d % (uint)m_scheme.CryptKey.Length;
if (n >= m_scheme.CryptKey.Length)
n = 0;
}
} }
public void DecryptIndex (uint index_offset, byte[] enc_index) unsafe void XorIndex (uint index_offset, byte[] index)
{ {
Decrypt (enc_index, 0, (uint)enc_index.Length); fixed (byte* buf_raw = index)
unsafe
{ {
fixed (byte* buf_raw = enc_index) uint* encoded = (uint*)buf_raw;
for (int i = 0; i < index.Length/4; ++i)
encoded[i] ^= index_offset;
if (WarcVersion >= 170)
{ {
uint* encoded = (uint*)buf_raw; byte key = (byte)~WarcVersion;
for (int i = 0; i < enc_index.Length/4; ++i) for (int i = 0; i < index.Length; ++i)
encoded[i] ^= index_offset; buf_raw[i] ^= key;
if (WarcVersion >= 170)
{
byte key = (byte)~WarcVersion;
for (int i = 0; i < enc_index.Length; ++i)
buf_raw[i] ^= key;
}
} }
} }
} }
@ -555,6 +596,7 @@ namespace GameRes.Formats.ShiinaRio
public interface IDecryptExtra public interface IDecryptExtra
{ {
void Decrypt (byte[] data, int index, uint length, uint flags); void Decrypt (byte[] data, int index, uint length, uint flags);
void Encrypt (byte[] data, int index, uint length, uint flags);
} }
[Serializable] [Serializable]
@ -580,6 +622,16 @@ namespace GameRes.Formats.ShiinaRio
DecryptPost (data, index, length); DecryptPost (data, index, length);
} }
public void Encrypt (byte[] data, int index, uint length, uint flags)
{
if (length < MinLength)
return;
if ((flags & 0x102) == 0x102)
DecryptPre (data, index, length);
if ((flags & 0x104) == 0x104)
DecryptPost (data, index, length);
}
protected abstract void DecryptPre (byte[] data, int index, uint length); protected abstract void DecryptPre (byte[] data, int index, uint length);
protected virtual void DecryptPost (byte[] data, int index, uint length) protected virtual void DecryptPost (byte[] data, int index, uint length)
@ -677,10 +729,9 @@ namespace GameRes.Formats.ShiinaRio
{ {
int sum = 0; int sum = 0;
int bit = 0; int bit = 0;
byte v;
for (int i = 0; i < 0x100; ++i) for (int i = 0; i < 0x100; ++i)
{ {
v = data[index+i]; byte v = data[index+i];
sum += v >> 1; sum += v >> 1;
data[index+i] = (byte)(v >> 1 | bit); data[index+i] = (byte)(v >> 1 | bit);
bit = v << 7; bit = v << 7;
@ -690,6 +741,27 @@ namespace GameRes.Formats.ShiinaRio
data[index + 0x105] ^= (byte)(sum >> 8); data[index + 0x105] ^= (byte)(sum >> 8);
} }
} }
public void Encrypt (byte[] data, int index, uint length, uint flags)
{
if (length < 0x200)
return;
if ((flags & 0x102) == 0x102)
{
int sum = 0;
int bit = 0;
for (int i = 0xFF; i >= 0; --i)
{
byte v = data[index+i];
sum += v & 0x7F;
data[index+i] = (byte)(v << 1 | bit);
bit = v >> 7;
}
data[index + 0xFF] |= (byte)bit;
data[index + 0x104] ^= (byte)sum;
data[index + 0x105] ^= (byte)(sum >> 8);
}
}
} }
[Serializable] [Serializable]
@ -697,16 +769,23 @@ namespace GameRes.Formats.ShiinaRio
{ {
public void Decrypt (byte[] data, int index, uint length, uint flags) public void Decrypt (byte[] data, int index, uint length, uint flags)
{ {
if (length < 0x400) if (length >= 0x400 && (flags & 0x204) == 0x204)
return; Crc16Crypt (data, index, (int)length);
if ((flags & 0x204) == 0x204) }
{
var crc16 = new Kogado.Crc16(); public void Encrypt (byte[] data, int index, uint length, uint flags)
crc16.Update (data, index, (int)length & 0x7E | 1); {
var sum = crc16.Value ^ 0xFFFF; if (length >= 0x400 && (flags & 0x104) == 0x104)
data[index + 0x104] ^= (byte)sum; Crc16Crypt (data, index, (int)length);
data[index + 0x105] ^= (byte)(sum >> 8); }
}
void Crc16Crypt (byte[] data, int index, int length)
{
var crc16 = new Kogado.Crc16();
crc16.Update (data, index, length & 0x7E | 1);
var sum = crc16.Value ^ 0xFFFF;
data[index + 0x104] ^= (byte)sum;
data[index + 0x105] ^= (byte)(sum >> 8);
} }
} }
@ -757,5 +836,95 @@ namespace GameRes.Formats.ShiinaRio
data[index + 0x203] ^= (byte)(length >> 24); data[index + 0x203] ^= (byte)(length >> 24);
} }
} }
public void Encrypt (byte[] data, int index, uint length, uint flags)
{
if (length < 0x200)
return;
if ((flags & 0x104) == 0x104)
{
throw new NotImplementedException();
}
}
}
[Serializable]
public class JokersCrypt : IDecryptExtra
{
public void Decrypt (byte[] data, int index, uint length, uint flags)
{
if (length < 0x400)
return;
if ((flags & 0x204) == 0x204)
{
if (0x718E958D == LittleEndian.ToUInt32 (data, index))
{
var input = new byte[0x200];
Buffer.BlockCopy (data, index, input, 0, 0x200);
int remaining = LittleEndian.ToInt32 (input, 8);
int src = 12;
int dst = index;
var ranges_hi = new uint[0x100];
var ranges_lo = new uint[0x101];
for (int i = 0; i < 0x100; ++i)
{
uint v = input[src++];
ranges_hi[i] = v;
ranges_lo[i+1] = v + ranges_lo[i];
}
uint denominator = ranges_lo[0x100];
var symbol_table = new byte[denominator];
uint low, high;
for (int i = 0; i < 0x100; ++i)
{
low = ranges_lo[i];
high = ranges_lo[i + 1];
int count = (int)(high - low);
for (int j = 0; j < count; ++j)
symbol_table[low + j] = (byte)i;
}
low = 0;
high = 0xFFFFFFFF;
uint current = BigEndian.ToUInt32 (input, src);
src += 4;
for (int i = 0; i < remaining; ++i)
{
uint range = high / denominator;
byte symbol = symbol_table[(current - low) / range];
data[index+i] = symbol;
low += ranges_lo[symbol] * range;
high = ranges_hi[symbol] * range;
while (0 == ((low ^ (high + low)) & 0xFF000000u))
{
low <<= 8;
high <<= 8;
current <<= 8;
current |= input[src++];
}
while (high < 0x10000)
{
low <<= 8;
high = 0x1000000 - (low & 0xFFFF00);
current <<= 8;
current |= input[src++];
}
}
}
data[index + 0x200] ^= (byte)length;
data[index + 0x201] ^= (byte)(length >> 8);
data[index + 0x202] ^= (byte)(length >> 16);
data[index + 0x203] ^= (byte)(length >> 24);
}
}
public void Encrypt (byte[] data, int index, uint length, uint flags)
{
if (length < 0x400)
return;
if ((flags & 0x104) == 0x104)
{
throw new NotImplementedException();
}
}
} }
} }