Skip to content

Commit 596c9c3

Browse files
committed
WzMutableKey : optimisation for .net 8.0, replace obsolete Rijndael class
1 parent c16eb6c commit 596c9c3

File tree

1 file changed

+39
-67
lines changed

1 file changed

+39
-67
lines changed

MapleLib/WzLib/Util/WzMutableKey.cs

Lines changed: 39 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -20,131 +20,103 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2020
using MapleLib.MapleCryptoLib;
2121
using Newtonsoft.Json.Linq;
2222
using System.Linq;
23+
using System.Runtime.InteropServices;
2324

2425
namespace MapleLib.WzLib.Util
2526
{
2627
public sealed class WzMutableKey : IEquatable<WzMutableKey>
2728
{
29+
private static readonly int BatchSize = 4096;
30+
private readonly byte[] _iv;
31+
private readonly byte[] _aesUserKey;
32+
private byte[]? _keys;
33+
2834
/// <summary>
29-
///
35+
/// Constructor
3036
/// </summary>
3137
/// <param name="WzIv"></param>
3238
/// <param name="AesKey">The 32-byte AES UserKey (derived from 32 DWORD)</param>
3339
public WzMutableKey(byte[] WzIv, byte[] AesKey)
3440
{
35-
this.IV = WzIv;
36-
this.AESUserKey = AesKey;
41+
this._iv = WzIv;
42+
this._aesUserKey = AesKey;
3743
}
3844

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>();
5146

5247
public byte this[int index]
5348
{
5449
get
5550
{
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];
6153
}
6254
}
6355

6456
public void EnsureKeySize(int size)
6557
{
66-
if (keys != null && keys.Length >= size)
58+
if (_keys != null && _keys.Length >= size)
6759
{
6860
return;
6961
}
7062

7163
size = (int)Math.Ceiling(1.0 * size / BatchSize) * BatchSize;
7264
byte[] newKeys = new byte[size];
7365

74-
if (BitConverter.ToInt32(this.IV, 0) == 0)
66+
if (BitConverter.ToInt32(this._iv, 0) == 0)
7567
{
76-
this.keys = newKeys;
68+
this._keys = newKeys;
7769
return;
7870
}
7971

8072
int startIndex = 0;
81-
82-
if (keys != null)
73+
if (_keys != null)
8374
{
84-
Buffer.BlockCopy(keys, 0, newKeys, 0, keys.Length);
85-
startIndex = keys.Length;
75+
_keys.CopyTo(newKeys, 0);
76+
startIndex = _keys.Length;
8677
}
8778

88-
Rijndael aes = Rijndael.Create();
79+
this._keys = newKeys;
80+
using var aes = Aes.Create();
8981
aes.KeySize = 256;
9082
aes.BlockSize = 128;
91-
aes.Key = AESUserKey;
83+
aes.Key = _aesUserKey;
9284
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);
9590

91+
Span<byte> block = stackalloc byte[16];
9692
for (int i = startIndex; i < size; i += 16)
9793
{
9894
if (i == 0)
9995
{
100-
byte[] block = new byte[16];
10196
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);
10699
}
107100
else
108101
{
109-
s.Write(newKeys, i - 16, 16);
102+
cs.Write(newKeys.AsSpan(i - 16, 16));
110103
}
111104
}
112105

113-
s.Flush();
114-
ms.Close();
115-
this.keys = newKeys;
106+
_keys = newKeys;
116107
}
117108

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);
124111

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));
129114

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));
137116

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));
144119

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);
149121
}
150122
}

0 commit comments

Comments
 (0)