~ruther/NosSmooth

8aacf1b21e04b59014940a21a778e04c272971d9 — Rutherther 2 years ago 59aa7eb
feat(crypto): add methods for converting unknown packets
1 files changed, 79 insertions(+), 0 deletions(-)

M Core/NosSmooth.Cryptography/CryptographyManager.cs
M Core/NosSmooth.Cryptography/CryptographyManager.cs => Core/NosSmooth.Cryptography/CryptographyManager.cs +79 -0
@@ 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;

/// <summary>


@@ 54,4 57,80 @@ public class CryptographyManager
            ((ClientWorldCryptography)ClientWorld).EncryptionKey = value;
        }
    }

    /// <summary>
    /// Attempts to decrypt a packet that was received by the client. May be login or world packet.
    /// Encryption key is not needed.
    /// </summary>
    /// <remarks>
    /// Expects only failc or NsTeST for login packets.
    /// </remarks>
    /// <param name="data">The received data.</param>
    /// <param name="encoding">The encoding.</param>
    /// <returns>Decrypted packet or empty string in case of fail.</returns>
    public string DecryptUnknownClientPacket(in ReadOnlySpan<byte> 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);
    }

    /// <summary>
    /// 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 <see cref="EncryptionKey"/>.
    /// </summary>
    /// <remarks>
    /// Expects only failc or NsTeST for login packets.
    /// </remarks>
    /// <param name="data">The received data.</param>
    /// <param name="encoding">The encoding.</param>
    /// <returns>Decrypted packet or empty string in case of fail.</returns>
    public string DecryptUnknownServerPacket(in ReadOnlySpan<byte> 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

Do not follow this link