@@ -20,131 +20,103 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
20
using MapleLib . MapleCryptoLib ;
21
21
using Newtonsoft . Json . Linq ;
22
22
using System . Linq ;
23
+ using System . Runtime . InteropServices ;
23
24
24
25
namespace MapleLib . WzLib . Util
25
26
{
26
27
public sealed class WzMutableKey : IEquatable < WzMutableKey >
27
28
{
29
+ private static readonly int BatchSize = 4096 ;
30
+ private readonly byte [ ] _iv ;
31
+ private readonly byte [ ] _aesUserKey ;
32
+ private byte [ ] ? _keys ;
33
+
28
34
/// <summary>
29
- ///
35
+ /// Constructor
30
36
/// </summary>
31
37
/// <param name="WzIv"></param>
32
38
/// <param name="AesKey">The 32-byte AES UserKey (derived from 32 DWORD)</param>
33
39
public WzMutableKey ( byte [ ] WzIv , byte [ ] AesKey )
34
40
{
35
- this . IV = WzIv ;
36
- this . AESUserKey = AesKey ;
41
+ this . _iv = WzIv ;
42
+ this . _aesUserKey = AesKey ;
37
43
}
38
44
39
- private static readonly int BatchSize = 4096 ;
40
- private readonly byte [ ] IV ;
41
- private readonly byte [ ] AESUserKey ;
42
-
43
- private byte [ ] keys ;
44
- public byte [ ] GetKeys ( )
45
- {
46
- byte [ ] keysCopy = new byte [ keys . Length ] ;
47
- Array . Copy ( keys , keysCopy , keys . Length ) ;
48
-
49
- return keysCopy ;
50
- }
45
+ public byte [ ] GetKeys ( ) => _keys ? . ToArray ( ) ?? Array . Empty < byte > ( ) ;
51
46
52
47
public byte this [ int index ]
53
48
{
54
49
get
55
50
{
56
- if ( keys == null || keys . Length <= index )
57
- {
58
- EnsureKeySize ( index + 1 ) ;
59
- }
60
- return this . keys [ index ] ;
51
+ EnsureKeySize ( index + 1 ) ;
52
+ return _keys ! [ index ] ;
61
53
}
62
54
}
63
55
64
56
public void EnsureKeySize ( int size )
65
57
{
66
- if ( keys != null && keys . Length >= size )
58
+ if ( _keys != null && _keys . Length >= size )
67
59
{
68
60
return ;
69
61
}
70
62
71
63
size = ( int ) Math . Ceiling ( 1.0 * size / BatchSize ) * BatchSize ;
72
64
byte [ ] newKeys = new byte [ size ] ;
73
65
74
- if ( BitConverter . ToInt32 ( this . IV , 0 ) == 0 )
66
+ if ( BitConverter . ToInt32 ( this . _iv , 0 ) == 0 )
75
67
{
76
- this . keys = newKeys ;
68
+ this . _keys = newKeys ;
77
69
return ;
78
70
}
79
71
80
72
int startIndex = 0 ;
81
-
82
- if ( keys != null )
73
+ if ( _keys != null )
83
74
{
84
- Buffer . BlockCopy ( keys , 0 , newKeys , 0 , keys . Length ) ;
85
- startIndex = keys . Length ;
75
+ _keys . CopyTo ( newKeys , 0 ) ;
76
+ startIndex = _keys . Length ;
86
77
}
87
78
88
- Rijndael aes = Rijndael . Create ( ) ;
79
+ this . _keys = newKeys ;
80
+ using var aes = Aes . Create ( ) ;
89
81
aes . KeySize = 256 ;
90
82
aes . BlockSize = 128 ;
91
- aes . Key = AESUserKey ;
83
+ aes . Key = _aesUserKey ;
92
84
aes . Mode = CipherMode . ECB ;
93
- MemoryStream ms = new MemoryStream ( newKeys , startIndex , newKeys . Length - startIndex , true ) ;
94
- CryptoStream s = new CryptoStream ( ms , aes . CreateEncryptor ( ) , CryptoStreamMode . Write ) ;
85
+ aes . Padding = PaddingMode . None ; // Ensure no padding is added
86
+
87
+ using var encryptor = aes . CreateEncryptor ( ) ;
88
+ using var ms = new MemoryStream ( newKeys , startIndex , newKeys . Length - startIndex , true ) ;
89
+ using var cs = new CryptoStream ( ms , encryptor , CryptoStreamMode . Write ) ;
95
90
91
+ Span < byte > block = stackalloc byte [ 16 ] ;
96
92
for ( int i = startIndex ; i < size ; i += 16 )
97
93
{
98
94
if ( i == 0 )
99
95
{
100
- byte [ ] block = new byte [ 16 ] ;
101
96
for ( int j = 0 ; j < block . Length ; j ++ )
102
- {
103
- block [ j ] = IV [ j % 4 ] ;
104
- }
105
- s . Write ( block , 0 , block . Length ) ;
97
+ block [ j ] = _iv [ j % 4 ] ;
98
+ cs . Write ( block ) ;
106
99
}
107
100
else
108
101
{
109
- s . Write ( newKeys , i - 16 , 16 ) ;
102
+ cs . Write ( newKeys . AsSpan ( i - 16 , 16 ) ) ;
110
103
}
111
104
}
112
105
113
- s . Flush ( ) ;
114
- ms . Close ( ) ;
115
- this . keys = newKeys ;
106
+ _keys = newKeys ;
116
107
}
117
108
118
- public bool Equals ( WzMutableKey other )
119
- {
120
- if ( ReferenceEquals ( null , other ) ) return false ;
121
- if ( ReferenceEquals ( this , other ) ) return true ;
122
- return IV . SequenceEqual ( other . IV ) && AESUserKey . SequenceEqual ( other . AESUserKey ) ;
123
- }
109
+ public bool Equals ( WzMutableKey ? other ) =>
110
+ other != null && _iv . AsSpan ( ) . SequenceEqual ( other . _iv ) && _aesUserKey . AsSpan ( ) . SequenceEqual ( other . _aesUserKey ) ;
124
111
125
- public override bool Equals ( object obj )
126
- {
127
- return ReferenceEquals ( this , obj ) || obj is WzMutableKey other && Equals ( other ) ;
128
- }
112
+ public override bool Equals ( object ? obj ) =>
113
+ ReferenceEquals ( this , obj ) || ( obj is WzMutableKey other && Equals ( other ) ) ;
129
114
130
- public override int GetHashCode ( )
131
- {
132
- unchecked
133
- {
134
- return ( IV . GetHashCode ( ) * 397 ) ^ AESUserKey . GetHashCode ( ) ;
135
- }
136
- }
115
+ public override int GetHashCode ( ) => HashCode . Combine ( MemoryMarshal . Read < int > ( _iv ) , MemoryMarshal . Read < int > ( _aesUserKey ) ) ;
137
116
138
- public static bool operator == ( WzMutableKey left , WzMutableKey right )
139
- {
140
- if ( ReferenceEquals ( left , right ) ) return true ;
141
- if ( left is null || right is null ) return false ;
142
- return left . Equals ( right ) ;
143
- }
117
+ public static bool operator == ( WzMutableKey ? left , WzMutableKey ? right ) =>
118
+ ReferenceEquals ( left , right ) || ( left is not null && left . Equals ( right ) ) ;
144
119
145
- public static bool operator != ( WzMutableKey left , WzMutableKey right )
146
- {
147
- return ! ( left == right ) ;
148
- }
120
+ public static bool operator != ( WzMutableKey ? left , WzMutableKey ? right ) => ! ( left == right ) ;
149
121
}
150
122
}
0 commit comments