From 8aacf1b21e04b59014940a21a778e04c272971d9 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Mon, 13 Feb 2023 17:43:46 +0100 Subject: [PATCH] feat(crypto): add methods for converting unknown packets --- .../CryptographyManager.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Core/NosSmooth.Cryptography/CryptographyManager.cs b/Core/NosSmooth.Cryptography/CryptographyManager.cs index f09a181..d96d701 100644 --- a/Core/NosSmooth.Cryptography/CryptographyManager.cs +++ b/Core/NosSmooth.Cryptography/CryptographyManager.cs @@ -4,6 +4,9 @@ // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Buffers; +using System.Text; + namespace NosSmooth.Cryptography; /// @@ -54,4 +57,80 @@ public class CryptographyManager ((ClientWorldCryptography)ClientWorld).EncryptionKey = value; } } + + /// + /// Attempts to decrypt a packet that was received by the client. May be login or world packet. + /// Encryption key is not needed. + /// + /// + /// Expects only failc or NsTeST for login packets. + /// + /// The received data. + /// The encoding. + /// Decrypted packet or empty string in case of fail. + public string DecryptUnknownClientPacket(in ReadOnlySpan data, Encoding encoding) + { + if (data.Length < 6) + { + return ClientWorld.Decrypt(data, encoding); + } + + var firstCharDecrypted = ClientLogin.Decrypt(data.Slice(0, 1), encoding); + + if (firstCharDecrypted.StartsWith("f") || + firstCharDecrypted.StartsWith("N")) + { + var beginning = data.Slice(0, 6); + var beginningLoginDecrypted = ClientLogin.Decrypt(beginning, encoding); + + if (beginningLoginDecrypted.StartsWith("failc") || + beginningLoginDecrypted.StartsWith("NsTeST")) + { + return ClientLogin.Decrypt(data, encoding); + } + } + + return ClientWorld.Decrypt(data, encoding); + } + + /// + /// Attempts to decrypt a packet that was received by the server. May be login or world packet. + /// Encryption key is needed for world packets. If the packet contains session id, + /// it will be saved to . + /// + /// + /// Expects only failc or NsTeST for login packets. + /// + /// The received data. + /// The encoding. + /// Decrypted packet or empty string in case of fail. + public string DecryptUnknownServerPacket(in ReadOnlySpan data, Encoding encoding) + { + var firstCharDecrypted = ClientLogin.Decrypt(data.Slice(0, 1), encoding); + + if (firstCharDecrypted.StartsWith("N")) + { + var beginning = data.Slice(0, 4); + var beginningLoginDecrypted = ClientLogin.Decrypt(beginning, encoding); + + if (beginningLoginDecrypted.StartsWith("NoS ")) + { + return ServerLogin.Decrypt(data, encoding); + } + } + + var encryptionKey = EncryptionKey; + var decrypted = ServerWorld.Decrypt(data, encoding); + + if (EncryptionKey == 0) + { // we are not in a session, so the packet may be the session id. + // or we are in an initialized session and won't know the encryption key... + if (int.TryParse(decrypted, out var obtainedEncryptionKey)) + { + EncryptionKey = obtainedEncryptionKey; + } + } + + return decrypted; + } } \ No newline at end of file -- 2.48.1