mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-27 15:44:00 +08:00
(IDecryptExtra): added Encrypt methods.
This commit is contained in:
parent
d8531398d9
commit
f12b65dc37
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user