using System; using System.Collections.Generic; using System.IO; using System.Security.Authentication; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JacobTechEncryption; using JacobTechEncryption.Enums; using Luski.net.Enums; using Luski.net.JsonTypes; using Luski.net.JsonTypes.WSS; using Luski.net.Structures.Public; using Luski.Shared.PublicServers.V1.ClientToServer.HTTP; using Luski.Shared.PublicServers.V1.Enums; using Luski.Shared.PublicServers.V1.ServerToClient.HTTP; using WebSocketSharp; using DataType = Luski.Shared.PublicServers.V1.Enums.DataType; namespace Luski.net; public partial class PublicServer { public async Task Login(string Username, string Password, CancellationToken CancellationToken) { return await All(Username, CancellationToken, Password); } public async Task CreateAccount(string Username, string Password, string DisplayName, string PFP, CancellationToken CancellationToken) { return await All(Username, CancellationToken, Password, DisplayName, PFP); } internal async Task LoginViaToken(string t) { Console.WriteLine("Starting Auto Login:"); bool b = await All(t, CancellationToken.None); Console.WriteLine($"Auto Login {(b ? "Successful" : "Failed")}"); return b; } private async Task All(string Username, CancellationToken CancellationToken, string? Password = null, string? Displayname = null, string? pfp = null) { DateTime dt = DateTime.UtcNow; Console.WriteLine("Encryption: " + DateTime.UtcNow.Subtract(dt).ToString("g")); if (!EncryptionHandler.Generating) { EncryptionHandler.GenerateKeys(); } while (!EncryptionHandler.Generated) { } Console.WriteLine("Encryption 2: " + DateTime.UtcNow.Subtract(dt).ToString("g")); List> FailedSystems = new(); login = true; LoginSTC json; List> heads = new() { new("key", EncryptionHandler.MyPublicKey), new((Password is null ? "token" : "username"), Convert.ToBase64String(Encryption.RSA.Encrypt(Username, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))) }; if (Password is not null) { heads.Add(new("password", EncryptionHandler.RemotePasswordEncrypt(Encryption.Generic.Encoders[(int)EncoderType.UTF16].GetBytes(Password)))); } if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < EncryptionHandler.PasswordVersion && lpv >= 0) { heads.Add(new("old_password", EncryptionHandler.RemotePasswordEncrypt(Encoding.Unicode.GetBytes(Password), lpv))); heads.Add(new("old_version", lpv.ToString())); } if (pfp is not null) { heads.Add(new("displayname", Displayname)); json = await SendServer( "SocketAccount", pfp, LoginSTCContext.Default.LoginSTC, CancellationToken, heads.ToArray()); } else { json = await GetFromServer( (Password is null ? "SocketAccount/AccessToken": "SocketAccount"), LoginSTCContext.Default.LoginSTC, CancellationToken, heads.ToArray()); } Console.WriteLine("Account Result: " + DateTime.UtcNow.Subtract(dt).ToString("g")); if (json.Error is not null) { Console.WriteLine(json.ErrorMessage); return false; throw new Exception($"Luski appears to be down at the current moment: {json.ErrorMessage}"); } if (EncryptionHandler.OfflinePrivateKey is null || EncryptionHandler.OfflinePublicKey is null) throw new Exception("Something went wrong generating the offline keys"); login = false; if (json is not null && json.Error is null) { ServerOut = new WebSocket(wssurl); ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12; ServerOut.OnMessage += DataFromServer; ServerOut.WaitTime = new TimeSpan(0, 0, 5); ServerOut.EmitOnPing = true; ServerOut.OnError += ServerOut_OnError; ServerOut.Connect(); Console.WriteLine("WSS Connection: " + DateTime.UtcNow.Subtract(dt).ToString("g")); SendServer(DataType.Token, new WSSLogin() { Token = json.Token! }); while (Token is null && Error is null) { Thread.Sleep(200); } if (Error is not null) { throw new Exception(Error); } Console.WriteLine("WSS Login: " + DateTime.UtcNow.Subtract(dt).ToString("g")); if (Token is null) throw new Exception("Server did not send a token"); CanRequest = true; long id = long.Parse(Encoding.UTF8.GetString(Convert.FromBase64String( Token.Split('.')[0] ))); User = await GetUser(id, CancellationToken); User.Username = Username; Console.WriteLine("Get our info: " + DateTime.UtcNow.Subtract(dt).ToString("g")); #region Extra Systems Task.Run(async () => { #region Data Storage try { StorageInfoSTC data; if (Storage.StorageID == 0) { EncryptionHandler.Hash = Storage.GenerateStorage(); data = await SendServer("OfflineData/Info", new StorageInfoCTS() { Password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoCTSContext.Default.StorageInfoCTS, StorageInfoSTCContext.Default.StorageInfoSTC, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); Storage.setid(data.ID); } else { data = await GetFromServer("OfflineData/Info", StorageInfoSTCContext.Default.StorageInfoSTC, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); } Console.WriteLine("Offline Data Info: " + DateTime.UtcNow.Subtract(dt).ToString("g")); if (data.Update) { EncryptionHandler.Hash = Storage.UpdateStorage(Convert.FromBase64String(data.Password)); _ = await SendServerPatch("OfflineData/Info", new StorageInfoCTS() { Password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoCTSContext.Default.StorageInfoCTS, StorageInfoSTCContext.Default.StorageInfoSTC, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); Console.WriteLine("Data Update: " + DateTime.UtcNow.Subtract(dt).ToString("g")); } } catch (Exception e) { FailedSystems.Add(new("Data Storage", e.Message, e)); } #endregion #region Key Generation try { try { _ = EncryptionHandler.GetKey(0); } catch (Exception e) { EncryptionHandler.SetKey(0, new() { EncryptionType = EncryptionType.None, Key = string.Empty }); Console.WriteLine("Key 0: " + DateTime.UtcNow.Subtract(dt).ToString("g")); } } catch (Exception e) { FailedSystems.Add(new("Key Generation", "Key 0 Failed to generate", e)); } #endregion #region Auto Status try { _ = await UpdateStatus(UserStatus.Online, CancellationToken); Console.WriteLine("Status: " + DateTime.UtcNow.Subtract(dt).ToString("g")); } catch (Exception e) { FailedSystems.Add(new("Auto Status", "Failed to set status on the server", e)); } #endregion #region Local Storage Cleanup try { KeyValuePair stor = new("storage_id", Storage.StorageID.ToString()); OfflineDataBlobSTC offlinedata = await GetFromServer("OfflineData", OfflineDataBlobSTCContext.Default.OfflineDataBlobSTC, CancellationToken, stor); Console.WriteLine("Offline Data: " + DateTime.UtcNow.Subtract(dt).ToString("g")); if (offlinedata is not null && offlinedata.Error is null && offlinedata.Data is not null && offlinedata.Data.Length > 0) { string pkey = Storage.GetResourceKeyRaw( StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash ); foreach (string keyexx in offlinedata.Data) { string keyex = Encoding.UTF8.GetString(Convert.FromBase64String(keyexx)); KeyExchange? okd = JsonSerializer.Deserialize(keyex); if (okd is not null && !string.IsNullOrEmpty(okd.key)) { Storage.SetResourceKey( StorageDirectory.ServerKeys, okd.id.ToString(), EncryptionHandler.Hash, Encoding.Unicode.GetString( Encryption.RSA.Decrypt( Convert.FromBase64String(okd.key), pkey ) ) ); } } } System.IO.File.WriteAllText("LastPassVer.txt", EncryptionHandler.PasswordVersion.ToString()); Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey); KeyPostCTS OfflineKeySetRequest = new() { Data = Convert.ToBase64String(Encoding.UTF8.GetBytes(EncryptionHandler.OfflinePublicKey)), EncryptionType = EncryptionType.RSA }; _ = await SendServer("Keys/SetOfflineKey", OfflineKeySetRequest, KeyPostCTSContext.Default.KeyPostCTS, STCContext.Default.STC, CancellationToken.None, stor); Console.WriteLine("Offline Key: " + DateTime.UtcNow.Subtract(dt).ToString("g")); EncryptionHandler.OfflinePublicKey = null!; EncryptionHandler.OfflinePrivateKey = null!; } catch (Exception e) { FailedSystems.Add(new("Local Storage Cleanup", "Failed to clean the local storage", e)); } #endregion if (FailedSystems.Count > 0) { Console.WriteLine("Some systems have failed:"); foreach (Tuple System in FailedSystems) { Console.WriteLine($"\t{System.Item1}:\n\t\tMessage: {System.Item2}\n\t\tError Details: {System.Item3}"); } } }); #endregion return true; } else throw new Exception(json?.ErrorMessage); return true; } }