~ruther/NosSmooth

3e36db92abd6019147109141c637d27b462f9fbd — Rutherther 2 years ago bb8e2c1
feat(crypto): make less allocations where possible
M Core/NosSmooth.Cryptography/ClientLoginCryptography.cs => Core/NosSmooth.Cryptography/ClientLoginCryptography.cs +1 -1
@@ 20,7 20,7 @@ public class ClientLoginCryptography : ICryptography
    {
        try
        {
            var output = new StringBuilder();
            var output = new StringBuilder(bytes.Length);
            foreach (var c in bytes)
            {
                output.Append(Convert.ToChar(c - 0xF));

M Core/NosSmooth.Cryptography/Extensions/StringExtensions.cs => Core/NosSmooth.Cryptography/Extensions/StringExtensions.cs +69 -0
@@ 23,6 23,75 @@ public static class StringExtensions
    }

    /// <summary>
    /// Split a string without any allocation.
    /// </summary>
    /// <param name="str">The string to split.</param>
    /// <param name="split">The char to split with.</param>
    /// <returns>The split enumerator.</returns>
    public static SplitEnumerator SplitAllocationless(this string str, char split)
    {
        return new SplitEnumerator(str.AsSpan(), split);
    }

    /// <summary>
    /// An enumerator of a string split.
    /// </summary>
    public ref struct SplitEnumerator
    {
        private readonly char _split;
        private ReadOnlySpan<char> _str;

        /// <summary>
        /// Initializes a new instance of the <see cref="SplitEnumerator"/> struct.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <param name="split">The split char.</param>
        public SplitEnumerator(ReadOnlySpan<char> str, char split)
        {
            _str = str;
            _split = split;
            Current = default;
        }

        /// <summary>
        /// Gets this enumerator.
        /// </summary>
        /// <returns>This.</returns>
        public SplitEnumerator GetEnumerator()
            => this;

        /// <summary>
        /// Move to next line.
        /// </summary>
        /// <returns>Whether move was successful.</returns>
        public bool MoveNext()
        {
            var span = _str;
            if (span.Length == 0)
            {
                return false;
            }

            var index = span.IndexOf(_split);
            if (index == -1)
            {
                _str = ReadOnlySpan<char>.Empty;
                Current = span;
                return true;
            }

            Current = span.Slice(0, index);
            _str = span.Slice(index + 1);
            return true;
        }

        /// <summary>
        /// Current line.
        /// </summary>
        public ReadOnlySpan<char> Current { get; private set; }
    }

    /// <summary>
    /// An enumerator of a string lines.
    /// </summary>
    public ref struct LineSplitEnumerator

M Core/NosSmooth.Cryptography/ServerLoginCryptography.cs => Core/NosSmooth.Cryptography/ServerLoginCryptography.cs +5 -5
@@ 18,21 18,21 @@ public class ServerLoginCryptography : ICryptography
    {
        try
        {
            string decryptedPacket = string.Empty;
            StringBuilder decryptedPacket = new StringBuilder(str.Length);

            foreach (byte character in str)
            {
                if (character > 14)
                {
                    decryptedPacket += Convert.ToChar((character - 15) ^ 195);
                    decryptedPacket.Append(Convert.ToChar((character - 15) ^ 195));
                }
                else
                {
                    decryptedPacket += Convert.ToChar((256 - (15 - character)) ^ 195);
                    decryptedPacket.Append(Convert.ToChar((256 - (15 - character)) ^ 195));
                }
            }

            return decryptedPacket;
            return decryptedPacket.ToString();
        }
        catch
        {


@@ 46,7 46,7 @@ public class ServerLoginCryptography : ICryptography
        try
        {
            packet += " ";
            byte[] tmp = Encoding.Default.GetBytes(packet);
            byte[] tmp = encoding.GetBytes(packet);
            for (int i = 0; i < packet.Length; i++)
            {
                tmp[i] = Convert.ToByte(tmp[i] + 15);

M Core/NosSmooth.Cryptography/ServerWorldCryptography.cs => Core/NosSmooth.Cryptography/ServerWorldCryptography.cs +10 -36
@@ 5,6 5,7 @@
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Text;
using NosSmooth.Cryptography.Extensions;

namespace NosSmooth.Cryptography;



@@ 63,71 64,47 @@ public class ServerWorldCryptography : ICryptography

    private static string DecryptAuthed(in ReadOnlySpan<byte> str, int encryptionKey, Encoding encoding)
    {
        var encryptedString = new StringBuilder();
        var encryptedString = new StringBuilder(str.Length);

        int sessionKey = encryptionKey & 0xFF;
        byte sessionNumber = unchecked((byte)(encryptionKey >> 6));
        sessionNumber &= 0xFF;
        sessionNumber &= 3;

        byte firstbyte = unchecked((byte)(sessionKey + 0x40));

        switch (sessionNumber)
        {
            case 0:
                foreach (byte character in str)
                {
                    byte firstbyte = unchecked((byte)(sessionKey + 0x40));
                    byte highbyte = unchecked((byte)(character - firstbyte));
                    encryptedString.Append((char)highbyte);
                }

                break;

            case 1:
                foreach (byte character in str)
                {
                    byte firstbyte = unchecked((byte)(sessionKey + 0x40));
                    byte highbyte = unchecked((byte)(character + firstbyte));
                    encryptedString.Append((char)highbyte);
                }

                break;

            case 2:
                foreach (byte character in str)
                {
                    byte firstbyte = unchecked((byte)(sessionKey + 0x40));
                    byte highbyte = unchecked((byte)(character - firstbyte ^ 0xC3));
                    encryptedString.Append((char)highbyte);
                }

                break;

            case 3:
                foreach (byte character in str)
                {
                    byte firstbyte = unchecked((byte)(sessionKey + 0x40));
                    byte highbyte = unchecked((byte)(character + firstbyte ^ 0xC3));
                    encryptedString.Append((char)highbyte);
                }

                break;

            default:
                encryptedString.Append((char)0xF);
                break;
        }

        string[] temp = encryptedString.ToString().Split((char)0xFF);

        var save = new StringBuilder();
        var temp = encryptedString.ToString().SplitAllocationless((char)0xFF);
        var save = new StringBuilder(encryptedString.Length);

        for (int i = 0; i < temp.Length; i++)
        foreach (var packet in temp)
        {
            save.Append(DecryptPrivate(temp[i].AsSpan(), encoding));
            if (i < temp.Length - 2)
            {
                save.Append((char)'\n');
            }
            save.Append(DecryptPrivate(packet, encoding));
            save.Append((char)'\n');
        }

        return save.ToString();


@@ 212,7 189,7 @@ public class ServerWorldCryptography : ICryptography
    {
        try
        {
            var encryptedStringBuilder = new StringBuilder();
            var encryptedStringBuilder = new StringBuilder(str.Length);
            for (int i = 1; i < str.Length; i++)
            {
                if (Convert.ToChar(str[i]) == 0xE)


@@ 250,9 227,6 @@ public class ServerWorldCryptography : ICryptography
                switch (firstbyte)
                {
                    case 0:
                        encryptedStringBuilder.Append(' ');
                        break;

                    case 1:
                        encryptedStringBuilder.Append(' ');
                        break;

Do not follow this link