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.BaseTypes; using Luski.net.JsonTypes.WSS; using Luski.net.Structures.Public; using WebSocketSharp; using DataType = Luski.net.Enums.Public.DataType; namespace Luski.net; public partial class PublicServer { public async Task Login(string Username, string Password, CancellationToken CancellationToken) { return await Both(Username, Password, CancellationToken); } public async Task CreateAccount(string Username, string Password, string Displayname, string PFP, CancellationToken CancellationToken) { return await Both(Username, Password, CancellationToken, Displayname, PFP); } internal async Task LoginViaToken(string t) { CancellationToken CancellationToken = CancellationToken.None; if (!EncryptionHandler.Generating) { EncryptionHandler.GenerateKeys(); } while (!EncryptionHandler.Generated) { } login = true; Login json; List> heads = new() { new("key", EncryptionHandler.MyPublicKey), new("token", Convert.ToBase64String(Encryption.RSA.Encrypt(t, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))), }; json = await GetFromServer( "SocketAccount/AccessToken", LoginContext.Default.Login, CancellationToken, heads.ToArray()); if (json.Error is not null) 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.EmitOnPing = true; ServerOut.WaitTime = new TimeSpan(0, 0, 5); ServerOut.OnError += ServerOut_OnError; ServerOut.Connect(); SendServer(DataType.Token, new WSSLogin() { Token = json.Token! }); while (Token is null && Error is null) { Thread.Sleep(500); } if (Error is not null) { throw new Exception(Error); } 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); StorageInfoJSON data; if (Storage.StorageID == 0) { EncryptionHandler.Hash = Storage.GenerateStorage(); data = await SendServer("OfflineData/Info", new StorageInfoJSON() { id = 0, update = false, password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoJSONContext.Default.StorageInfoJSON, StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); Storage.setid(data.id); } else { data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); } if (data.update) { EncryptionHandler.Hash = Storage.UpdateStorage(Convert.FromBase64String(data.password)); _ = await SendServerPatch("OfflineData/Info", new StorageInfoJSON() { id = 0, update = false, password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoJSONContext.Default.StorageInfoJSON, StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); } try { _ = EncryptionHandler.GetKey(0); } catch (Exception e) { EncryptionHandler.SetKey(0, new() { EncryptionType = EncryptionType.None, Key = string.Empty }); } _ = await UpdateStatus(UserStatus.Online, CancellationToken); KeyValuePair stor = new("storage_id", Storage.StorageID.ToString()); OfflineData offlinedata = await GetFromServer("OfflineData", OfflineDataContext.Default.OfflineData, CancellationToken, stor); 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.ChannelKeys, okd.channel.ToString(), EncryptionHandler.Hash, Encoding.Unicode.GetString( Encryption.RSA.Decrypt( Convert.FromBase64String(okd.key), pkey ) ) ); } } } Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey); UserKeyGetRequest OfflineKeySetRequest = new() { key_data = Convert.ToBase64String(Encoding.UTF8.GetBytes(EncryptionHandler.OfflinePublicKey)), encryption_type = EncryptionType.RSA }; _ = await SendServer("Keys/SetOfflineKey", OfflineKeySetRequest, UserKeyGetRequestContext.Default.UserKeyGetRequest, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken.None, stor); EncryptionHandler.OfflinePublicKey = null!; EncryptionHandler.OfflinePrivateKey = null!; return true; } else { throw new Exception(json?.ErrorMessage); } return true; } private async Task Both(string Username, string Password, CancellationToken CancellationToken, string? Displayname = null, string? pfp = null) { if (!EncryptionHandler.Generating) { EncryptionHandler.GenerateKeys(); } while (!EncryptionHandler.Generated) { } login = true; Login json; List> heads = new() { new("key", EncryptionHandler.MyPublicKey), new("username", Convert.ToBase64String(Encryption.RSA.Encrypt(Username, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))), 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, LoginContext.Default.Login, CancellationToken, heads.ToArray()); } else { json = await GetFromServer( "SocketAccount", LoginContext.Default.Login, CancellationToken, heads.ToArray()); } if (json.Error is not null) 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(); SendServer(DataType.Token, new WSSLogin() { Token = json.Token! }); while (Token is null && Error is null) { Thread.Sleep(500); } if (Error is not null) { throw new Exception(Error); } 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); StorageInfoJSON data; if (Storage.StorageID == 0) { EncryptionHandler.Hash = Storage.GenerateStorage(); data = await SendServer("OfflineData/Info", new StorageInfoJSON() { id = 0, update = false, password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoJSONContext.Default.StorageInfoJSON, StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); Storage.setid(data.id); } else { data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); } if (data.update) { EncryptionHandler.Hash = Storage.UpdateStorage(Convert.FromBase64String(data.password)); _ = await SendServerPatch("OfflineData/Info", new StorageInfoJSON() { id = 0, update = false, password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk"))) }, StorageInfoJSONContext.Default.StorageInfoJSON, StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair("storage_id", Storage.StorageID.ToString())); } try { _ = EncryptionHandler.GetKey(0); } catch (Exception e) { EncryptionHandler.SetKey(0, new() { EncryptionType = EncryptionType.None, Key = string.Empty }); } _ = await UpdateStatus(UserStatus.Online, CancellationToken); //EncryptionHandler.Hash = EncryptionHandler.LocalPasswordEncrypt(Encoding.Unicode.GetBytes(Username.ToLower() + Password)); KeyValuePair stor = new("storage_id", Storage.StorageID.ToString()); OfflineData offlinedata = await GetFromServer("OfflineData", OfflineDataContext.Default.OfflineData, CancellationToken, stor); 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.ChannelKeys, okd.channel.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); UserKeyGetRequest OfflineKeySetRequest = new() { key_data = Convert.ToBase64String(Encoding.UTF8.GetBytes(EncryptionHandler.OfflinePublicKey)), encryption_type = EncryptionType.RSA }; _ = await SendServer("Keys/SetOfflineKey", OfflineKeySetRequest, UserKeyGetRequestContext.Default.UserKeyGetRequest, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken.None, stor); // using HttpClient setkey = new(); // setkey.DefaultRequestHeaders.Add("token", Token); // _ = await setkey.PostAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/Keys/SetOfflineKey", new StringContent(EncryptionHandler.OfflinePublicKey)); EncryptionHandler.OfflinePublicKey = null!; EncryptionHandler.OfflinePrivateKey = null!; return true; } else throw new Exception(json?.ErrorMessage); return true; } }