private void HandleLoginServer(LoginServer payload, PayloadWriter writer)
        {
            byte[] loginCipher = payload.Cipher;

            byte[] result = Crypto.HandleUser(loginCipher, _sharedSecret);
            Program.LogDebug($" User: {Serializer.DumpBytes(result)}");

            MemoryStream stream = new MemoryStream(result);
            BinaryReader reader = new BinaryReader(stream);

            bool invalid = false;

            byte[] nameBytes  = null;
            int    nameLength = reader.ReadByte();

            if (nameLength < 32)
            {
                nameBytes = reader.ReadBytes(nameLength);
            }
            else
            {
                invalid = true;
            }

            byte[] passwordBytes = null;
            if (!invalid)
            {
                int passwordLength = reader.ReadByte();
                if (nameLength < 32)
                {
                    passwordBytes = reader.ReadBytes(passwordLength);
                }
                else
                {
                    invalid = true;
                }
            }

            if (invalid)
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 3;
                resultPayload1.Errormsg  = "Encryption failure";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            string name = Encoding.ASCII.GetString(nameBytes);

            byte[] password = Crypto.HashPassword(passwordBytes);

            Account = Program.Accounts.Get(Database.Connection, name);
            if (Account == null)
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 1;
                resultPayload1.Errormsg  = "Account not found";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            if (!Serializer.CompareArrays(password, Account.Password))
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 1;
                resultPayload1.Errormsg  = "Wrong password";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            byte[] secret = Crypto.HandleSessionKey(Crypto.CreateSecretKey(), _sharedSecret);

            LoginReplyCipher resultPayload = Payloads.CreatePayload <LoginReplyCipher>();

            resultPayload.PermId   = Account.Id;
            resultPayload.Cipher   = secret;
            resultPayload.TicketId = payload.TicketId;
            SendReply(writer, resultPayload);

            Program.Log($"Server logged in for user {name}");
        }
        private void HandleRegisterUser(RegisterUser payload, PayloadWriter writer)
        {
            byte[] loginCipher = payload.Cipher;

            byte[] result = Crypto.HandleUser(loginCipher, _sharedSecret);
            Program.LogDebug($" User: {Serializer.DumpBytes(result)}");

            MemoryStream stream = new MemoryStream(result);
            BinaryReader reader = new BinaryReader(stream);

            bool invalid = false;

            byte[] nameBytes  = null;
            int    nameLength = reader.ReadByte();

            if (nameLength < 32)
            {
                nameBytes = reader.ReadBytes(nameLength);
            }
            else
            {
                invalid = true;
            }

            byte[] passwordBytes = null;
            if (!invalid)
            {
                int passwordLength = reader.ReadByte();
                if (nameLength < 32)
                {
                    passwordBytes = reader.ReadBytes(passwordLength);
                }
                else
                {
                    invalid = true;
                }
            }

            byte[] cdKey = null;
            if (!invalid)
            {
                int keysLength = reader.ReadByte();
                int keyPool    = reader.ReadByte();
                int keyLength  = reader.ReadByte();
                if (keysLength != 1 || keyPool != 1 || keyLength != 16)
                {
                    invalid = true;
                }
                else
                {
                    cdKey = reader.ReadBytes(keyLength);
                }
            }

            if (invalid)
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 3;
                resultPayload1.Errormsg  = "Encryption failure";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            string name = Encoding.ASCII.GetString(nameBytes);

            byte[] password = Crypto.HashPassword(passwordBytes);

            uint id = Program.Accounts.Create(Database.Connection, name, password, cdKey);

            if (id == 0)
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 1;
                resultPayload1.Errormsg  = "Username already in use";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            Account = Program.Accounts.Get(Database.Connection, name);
            if (Account == null)
            {
                StatusMsg resultPayload1 = Payloads.CreatePayload <StatusMsg>();
                resultPayload1.Errorcode = 1;
                resultPayload1.Errormsg  = "Account not created";
                resultPayload1.TicketId  = payload.TicketId;
                SendReply(writer, resultPayload1);
                return;
            }

            byte[] secret = Crypto.HandleSessionKey(Crypto.CreateSecretKey(), _sharedSecret);

            LoginReplyCipher resultPayload2 = Payloads.CreatePayload <LoginReplyCipher>();

            resultPayload2.PermId   = Account.Id;
            resultPayload2.Cipher   = secret;
            resultPayload2.TicketId = payload.TicketId;
            SendReply(writer, resultPayload2);

            Program.Log($"Account created for {name}");
        }