Skip to content

Commit b9b6153

Browse files
committed
UnityCN ref
1 parent f71e195 commit b9b6153

3 files changed

Lines changed: 61 additions & 145 deletions

File tree

UnityAsset.NET/BundleFiles/UnityCN.cs

Lines changed: 61 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Text;
44
using System.Security.Cryptography;
55

6-
using UnityAsset.NET.Extensions;
76
using UnityAsset.NET.IO;
87

98
namespace UnityAsset.NET.BundleFiles;
@@ -12,107 +11,108 @@ public sealed unsafe class UnityCN
1211
{
1312
private const string Signature = "#$unity3dchina!@";
1413

15-
private ICryptoTransform Encryptor;
16-
17-
uint value;
14+
private ICryptoTransform _encryptor;
1815

16+
public UInt32 Value;
1917
public readonly byte[] InfoBytes;
2018
public readonly byte[] InfoKey;
21-
2219
public readonly byte[] SignatureBytes;
2320
public readonly byte[] SignatureKey;
2421

2522
public readonly byte[] Index = new byte[0x10];
2623
public readonly byte[] Sub = new byte[0x10];
2724

28-
private GCHandle subHandle;
29-
private GCHandle indexHandle;
30-
private readonly byte* subPtr;
31-
private readonly byte* indexPtr;
25+
private GCHandle _subHandle;
26+
private GCHandle _indexHandle;
27+
private readonly byte* _subPtr;
28+
private readonly byte* _indexPtr;
3229

33-
private bool isIndexSpecial = true;
30+
private readonly bool _isIndexSpecial = true;
3431

3532
public UnityCN(ref DataBuffer db, string key)
3633
{
3734
SetKey(key);
3835

39-
value = db.ReadUInt32();
40-
36+
Value = db.ReadUInt32();
4137
InfoBytes = db.ReadBytes(0x10);
4238
InfoKey = db.ReadBytes(0x10);
4339
db.Advance(1);
44-
4540
SignatureBytes = db.ReadBytes(0x10);
4641
SignatureKey = db.ReadBytes(0x10);
4742
db.Advance(1);
4843

49-
reset();
44+
Reset();
5045

5146
for (int i = 0; i < Index.Length; i++)
5247
{
5348
if (Index[i] != i)
5449
{
55-
isIndexSpecial = false;
50+
_isIndexSpecial = false;
5651
break;
5752
}
5853
}
5954

60-
subHandle = GCHandle.Alloc(Sub, GCHandleType.Pinned);
61-
indexHandle = GCHandle.Alloc(Index, GCHandleType.Pinned);
55+
_subHandle = GCHandle.Alloc(Sub, GCHandleType.Pinned);
56+
_indexHandle = GCHandle.Alloc(Index, GCHandleType.Pinned);
6257

63-
subPtr = (byte*)subHandle.AddrOfPinnedObject();
64-
indexPtr = (byte*)indexHandle.AddrOfPinnedObject();
58+
_subPtr = (byte*)_subHandle.AddrOfPinnedObject();
59+
_indexPtr = (byte*)_indexHandle.AddrOfPinnedObject();
6560
}
6661

6762
~UnityCN()
6863
{
69-
if (subHandle.IsAllocated) subHandle.Free();
70-
if (indexHandle.IsAllocated) indexHandle.Free();
64+
if (_subHandle.IsAllocated) _subHandle.Free();
65+
if (_indexHandle.IsAllocated) _indexHandle.Free();
7166
}
7267

7368
public UnityCN(string key)
7469
{
7570
SetKey(key);
7671

77-
value = 0;
72+
Value = 0;
7873

7974
InfoBytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xA6, 0xB1, 0xDE, 0x48, 0x9E, 0x2B, 0x53, 0x5C];
8075
InfoKey = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10];
81-
EncryptKey(InfoKey, InfoBytes);
76+
XorWithKey(InfoKey, InfoBytes);
8277

8378
SignatureKey = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10];
8479
SignatureBytes = Encoding.UTF8.GetBytes(Signature);
85-
EncryptKey(SignatureKey, SignatureBytes);
80+
XorWithKey(SignatureKey, SignatureBytes);
8681

87-
reset();
82+
Reset();
8883

89-
subHandle = GCHandle.Alloc(Sub, GCHandleType.Pinned);
90-
indexHandle = GCHandle.Alloc(Index, GCHandleType.Pinned);
84+
_subHandle = GCHandle.Alloc(Sub, GCHandleType.Pinned);
85+
_indexHandle = GCHandle.Alloc(Index, GCHandleType.Pinned);
9186

92-
subPtr = (byte*)subHandle.AddrOfPinnedObject();
93-
indexPtr = (byte*)indexHandle.AddrOfPinnedObject();
87+
_subPtr = (byte*)_subHandle.AddrOfPinnedObject();
88+
_indexPtr = (byte*)_indexHandle.AddrOfPinnedObject();
9489
}
9590

96-
public void reset()
91+
public void Reset()
9792
{
9893
var infoBytes = (byte[])InfoBytes.Clone();
9994
var infoKey = (byte[])InfoKey.Clone();
10095
var signatureBytes = (byte[])SignatureBytes.Clone();
10196
var signatureKey = (byte[])SignatureKey.Clone();
10297

103-
DecryptKey(signatureKey, signatureBytes);
98+
XorWithKey(signatureKey, signatureBytes);
10499

105100
var str = Encoding.UTF8.GetString(signatureBytes);
106101
if (str != Signature)
107102
{
108103
throw new Exception($"Invalid Signature, Expected {Signature} but found {str} instead");
109104
}
110105

111-
DecryptKey(infoKey, infoBytes);
112-
113-
infoBytes = infoBytes.ToUInt4Array();
114-
infoBytes.AsSpan(0, 0x10).CopyTo(Index);
115-
var subBytes = infoBytes.AsSpan(0x10, 0x10);
106+
XorWithKey(infoKey, infoBytes);
107+
var buffer = new byte[infoBytes.Length * 2];
108+
for (var i = 0; i < infoBytes.Length; i++)
109+
{
110+
var idx = i * 2;
111+
buffer[idx] = (byte)(infoBytes[i] >> 4);
112+
buffer[idx + 1] = (byte)(infoBytes[i] & 0xF);
113+
}
114+
buffer.AsSpan(0, 0x10).CopyTo(Index);
115+
var subBytes = buffer.AsSpan(0x10, 0x10);
116116
for (var i = 0; i < subBytes.Length; i++)
117117
{
118118
var idx = (i % 4 * 4) + (i / 4);
@@ -122,33 +122,26 @@ public void reset()
122122

123123
public void Serialize(ref DataBuffer db)
124124
{
125-
db.WriteUInt32(value);
125+
db.WriteUInt32(Value);
126126
db.WriteBytes(InfoBytes);
127127
db.WriteBytes(InfoKey);
128-
db.WriteByte((byte)0);
128+
db.WriteByte(0);
129129
db.WriteBytes(SignatureBytes);
130130
db.WriteBytes(SignatureKey);
131-
db.WriteByte((byte)0);
131+
db.WriteByte(0);
132132
}
133133

134134
public long SerializeSize => 70;
135135

136-
public bool SetKey(string key)
136+
public void SetKey(string key)
137137
{
138-
try
139-
{
140-
using var aes = Aes.Create();
141-
aes.Mode = CipherMode.ECB;
142-
aes.Key = Convert.FromHexString(key);
138+
if (key.Length != 32 && key.Length != 16)
139+
throw new ArgumentException("key must be 32 or 16 characters long");
140+
using var aes = Aes.Create();
141+
aes.Mode = CipherMode.ECB;
142+
aes.Key = Convert.FromHexString(key);
143143

144-
Encryptor = aes.CreateEncryptor();
145-
}
146-
catch (Exception e)
147-
{
148-
Console.WriteLine($"[UnityCN] Invalid key !!\n{e.Message}");
149-
return false;
150-
}
151-
return true;
144+
_encryptor = aes.CreateEncryptor();
152145
}
153146

154147
public void DecryptAndDecompress(ReadOnlySpan<byte> compressedData, Span<byte> decompressedData, int index)
@@ -163,7 +156,7 @@ public void DecryptAndDecompress(ReadOnlySpan<byte> compressedData, Span<byte> d
163156
while (s < sourceEnd)
164157
{
165158
var innerIndex = index;
166-
var token = DecryptByteSp(*s++, innerIndex++);
159+
var token = DecryptByteUnsafe(*s++, innerIndex++);
167160
var literalLength = token >> 4;
168161
var matchLength = token & 0xF;
169162
if (literalLength != 0xF)
@@ -182,7 +175,7 @@ public void DecryptAndDecompress(ReadOnlySpan<byte> compressedData, Span<byte> d
182175
int b;
183176
do
184177
{
185-
b = DecryptByteSp(*s++, innerIndex++);
178+
b = DecryptByteUnsafe(*s++, innerIndex++);
186179
literalLength += b;
187180
} while (b == 0xFF);
188181
Buffer.MemoryCopy(s, t, literalLength, literalLength);
@@ -194,14 +187,14 @@ public void DecryptAndDecompress(ReadOnlySpan<byte> compressedData, Span<byte> d
194187
if (s == sourceEnd && matchLength == 0) break;
195188
if (s >= sourceEnd) throw new Exception("Invalid compressed data");
196189

197-
var offset = (int)DecryptByteSp(*s++, innerIndex++);
198-
offset |= DecryptByteSp(*s++, innerIndex++) << 8;
190+
var offset = (int)DecryptByteUnsafe(*s++, innerIndex++);
191+
offset |= DecryptByteUnsafe(*s++, innerIndex++) << 8;
199192
if (matchLength == 0xF)
200193
{
201194
int b;
202195
do
203196
{
204-
b = DecryptByteSp(*s++, innerIndex++);
197+
b = DecryptByteUnsafe(*s++, innerIndex++);
205198
matchLength += b;
206199
} while (b == 0xFF);
207200
}
@@ -236,16 +229,6 @@ public void DecryptAndDecompress(ReadOnlySpan<byte> compressedData, Span<byte> d
236229
}
237230
}
238231

239-
[Obsolete("This method is obsolete. Use DecryptAndDecompress instead.")]
240-
public void DecryptBlock(Span<byte> bytes, int size, int index)
241-
{
242-
var offset = 0;
243-
while (offset < size)
244-
{
245-
offset += Decrypt(bytes[offset..], index++, size - offset);
246-
}
247-
}
248-
249232
public void EncryptBlock(Span<byte> bytes, int size, int index)
250233
{
251234
var offset = 0;
@@ -254,25 +237,12 @@ public void EncryptBlock(Span<byte> bytes, int size, int index)
254237
offset += Encrypt(bytes[offset..], index++, size - offset);
255238
}
256239
}
257-
258-
private void DecryptKey(byte[] key, byte[] data)
259-
{
260-
if (Encryptor != null)
261-
{
262-
key = Encryptor.TransformFinalBlock(key, 0, key.Length);
263-
for (int i = 0; i < 0x10; i++)
264-
data[i] ^= key[i];
265-
}
266-
}
267240

268-
private void EncryptKey(byte[] key, byte[] data)
241+
private void XorWithKey(byte[] key, byte[] data)
269242
{
270-
if (Encryptor != null)
271-
{
272-
key = Encryptor.TransformFinalBlock(key, 0, key.Length);
273-
for (int i = 0; i < 0x10; i++)
274-
data[i] ^= key[i];
275-
}
243+
key = _encryptor.TransformFinalBlock(key, 0, key.Length);
244+
for (int i = 0; i < 0x10; i++)
245+
data[i] ^= key[i];
276246
}
277247

278248
private int DecryptByte(Span<byte> bytes, ref int offset, ref int index)
@@ -288,27 +258,17 @@ private int DecryptByte(Span<byte> bytes, ref int offset, ref int index)
288258
[MethodImpl(MethodImplOptions.AggressiveInlining)]
289259
private byte DecryptByteUnsafe(byte b, int index)
290260
{
291-
var mb = subPtr[index & 3]
292-
+ subPtr[((index >> 2) & 3) + 4]
293-
+ subPtr[((index >> 4) & 3) + 8]
294-
+ subPtr[((byte)index >> 6) + 12];
295-
return (byte)((indexPtr[b & 0xF] - mb) & 0xF | (indexPtr[b >> 4] - mb) << 4);
296-
}
297-
298-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
299-
private byte DecryptByteSp(byte b, int index)
300-
{
301-
var mb = subPtr[index & 3]
302-
+ subPtr[((index >> 2) & 3) + 4]
303-
+ subPtr[((index >> 4) & 3) + 8]
304-
+ subPtr[((byte)index >> 6) + 12];
305-
if (isIndexSpecial)
261+
var mb = _subPtr[index & 3]
262+
+ _subPtr[((index >> 2) & 3) + 4]
263+
+ _subPtr[((index >> 4) & 3) + 8]
264+
+ _subPtr[((byte)index >> 6) + 12];
265+
if (_isIndexSpecial)
306266
{
307267
return (byte)(((b & 0xF) - mb) & 0xF | ((b >> 4) - mb) << 4);
308268
}
309269
else
310270
{
311-
return (byte)((indexPtr[b & 0xF] - mb) & 0xF | (indexPtr[b >> 4] - mb) << 4);
271+
return (byte)((_indexPtr[b & 0xF] - mb) & 0xF | (_indexPtr[b >> 4] - mb) << 4);
312272
}
313273
}
314274

@@ -322,15 +282,11 @@ private int EncryptByte(Span<byte> bytes, ref int offset, ref int index)
322282

323283
int i = 0;
324284
while (((Index[i] - b) & 0xF) != low && i < 0x10)
325-
{
326285
i++;
327-
}
328286
low = i;
329287
i = 0;
330288
while (((Index[i] - b) & 0xF) != high && i < 0x10)
331-
{
332289
i++;
333-
}
334290
high = i;
335291

336292
bytes[offset] = (byte)(low | (high << 4));

UnityAsset.NET/Extensions/ByteArrayExtensions.cs

Lines changed: 0 additions & 17 deletions
This file was deleted.

UnityAsset.NET/Extensions/StreamExtensions.cs

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)