Files
UmaViewer/Assets/Scripts/Audio/ClHcaSharp/Cipher.cs
T
1605296300@qq.com 7607c8b4d2 add acb&awb support
2022-09-07 01:22:44 +08:00

139 lines
3.7 KiB
C#

using System;
namespace ClHcaSharp
{
internal static class Cipher
{
public static void Decrypt(byte[] cipherData, byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = cipherData[data[i]];
}
}
public static byte[] Init(int type, ulong keyCode)
{
if (type == 56 && keyCode == 0) type = 0;
return type switch
{
0 => Init0(),
1 => Init1(),
56 => Init56(keyCode),
_ => throw new ArgumentException("Invalid cipher type."),
};
}
private static byte[] Init0()
{
byte[] cipherTable = new byte[256];
for (int i = 0; i < 256; i++)
{
cipherTable[i] = (byte)i;
}
return cipherTable;
}
private static byte[] Init1()
{
byte[] cipherTable = new byte[256];
const int mul = 13;
const int add = 11;
uint v = 0;
for (int i = 1; i < 256 - 1; i++)
{
v = (v * mul + add) & 0xFF;
if (v == 0 || v == 0xFF)
v = (v * mul + add) & 0xFF;
cipherTable[i] = (byte)v;
}
cipherTable[0] = 0;
cipherTable[0xFF] = 0xFF;
return cipherTable;
}
private static void Init56CreateTable(byte[] table, byte key)
{
int mul = ((key & 1) << 3) | 5;
int add = (key & 0xE) | 1;
key >>= 4;
for (int i = 0; i < 16; i++)
{
key = (byte)((key * mul + add) & 0xF);
table[i] = key;
}
}
private static byte[] Init56(ulong keyCode)
{
byte[] cipherTable = new byte[256];
byte[] kc = new byte[8];
byte[] seed = new byte[16];
byte[] baseTable = new byte[256];
byte[] baseTableR = new byte[16];
byte[] baseTableC = new byte[16];
if (keyCode != 0) keyCode--;
for (int r = 0; r < (8 - 1); r++)
{
kc[r] = (byte)(keyCode & 0xFF);
keyCode >>= 8;
}
seed[0x00] = kc[1];
seed[0x01] = (byte)(kc[1] ^ kc[6]);
seed[0x02] = (byte)(kc[2] ^ kc[3]);
seed[0x03] = kc[2];
seed[0x04] = (byte)(kc[2] ^ kc[1]);
seed[0x05] = (byte)(kc[3] ^ kc[4]);
seed[0x06] = kc[3];
seed[0x07] = (byte)(kc[3] ^ kc[2]);
seed[0x08] = (byte)(kc[4] ^ kc[5]);
seed[0x09] = kc[4];
seed[0x0A] = (byte)(kc[4] ^ kc[3]);
seed[0x0B] = (byte)(kc[5] ^ kc[6]);
seed[0x0C] = kc[5];
seed[0x0D] = (byte)(kc[5] ^ kc[4]);
seed[0x0E] = (byte)(kc[6] ^ kc[1]);
seed[0x0F] = kc[6];
Init56CreateTable(baseTableR, kc[0]);
for (int r = 0; r < 16; r++)
{
byte nb;
Init56CreateTable(baseTableC, seed[r]);
nb = (byte)(baseTableR[r] << 4);
for (int c = 0; c < 16; c++)
{
baseTable[r * 16 + c] = (byte)(nb | baseTableC[c]);
}
}
uint x = 0;
uint pos = 1;
for (int i = 0; i < 256; i++)
{
x = (x + 17) & 0xFF;
if (baseTable[x] != 0 && baseTable[x] != 0xFF)
cipherTable[pos++] = baseTable[x];
}
cipherTable[0] = 0;
cipherTable[0xFF] = 0xFF;
return cipherTable;
}
}
}