diff --git a/SVSim.BattleNode/Wire/NodeCrypto.cs b/SVSim.BattleNode/Wire/NodeCrypto.cs index 98cc2d3..dcbafc3 100644 --- a/SVSim.BattleNode/Wire/NodeCrypto.cs +++ b/SVSim.BattleNode/Wire/NodeCrypto.cs @@ -41,12 +41,7 @@ public static class NodeCrypto { if (key.Length != 32) throw new ArgumentException($"Key must be exactly 32 chars, got {key.Length}", nameof(key)); - using var aes = Aes.Create(); - aes.KeySize = 256; - aes.Mode = CipherMode.CBC; - aes.Padding = PaddingMode.PKCS7; - aes.Key = Encoding.UTF8.GetBytes(key); - aes.IV = Encoding.UTF8.GetBytes(key.Substring(0, 16)); + using var aes = BuildAes(key); using var encryptor = aes.CreateEncryptor(); var plainBytes = Encoding.UTF8.GetBytes(plaintext); var cipherBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); @@ -60,14 +55,25 @@ public static class NodeCrypto throw new ArgumentException("Encrypted blob is shorter than the 32-char key prefix", nameof(encrypted)); var key = encrypted.Substring(0, 32); var cipherBytes = Convert.FromBase64String(encrypted.Substring(32)); - using var aes = Aes.Create(); + using var aes = BuildAes(key); + using var decryptor = aes.CreateDecryptor(); + var plainBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); + return Encoding.UTF8.GetString(plainBytes); + } + + /// + /// Configure an AES-256-CBC instance with the node's IV derivation (first 16 chars + /// of the key, UTF-8). Callers own disposal. Assumes is the + /// 32-char ASCII key the encrypt / decrypt path has already validated. + /// + private static Aes BuildAes(string key) + { + var aes = Aes.Create(); aes.KeySize = 256; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = Encoding.UTF8.GetBytes(key); aes.IV = Encoding.UTF8.GetBytes(key.Substring(0, 16)); - using var decryptor = aes.CreateDecryptor(); - var plainBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); - return Encoding.UTF8.GetString(plainBytes); + return aes; } }