33using System . Text ;
44using System . Security . Cryptography ;
55
6- using UnityAsset . NET . Extensions ;
76using UnityAsset . NET . IO ;
87
98namespace 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 ) ) ;
0 commit comments