Luski.Net/Luski.net/PublicServer.Account.cs
JacobTech 69168acd22 Fixed loop.
Server class can't have an API class property, or a loop will prevent building.
2023-10-01 13:12:27 -04:00

357 lines
16 KiB
C#

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<bool> Login(string Username, string Password, CancellationToken CancellationToken)
{
return await Both(Username, Password, CancellationToken);
}
public async Task<bool> CreateAccount(string Username, string Password, string Displayname, string PFP, CancellationToken CancellationToken)
{
return await Both(Username, Password, CancellationToken, Displayname, PFP);
}
internal async Task<bool> LoginViaToken(string t)
{
CancellationToken CancellationToken = CancellationToken.None;
if (!EncryptionHandler.Generating)
{
EncryptionHandler.GenerateKeys();
}
while (!EncryptionHandler.Generated) { }
login = true;
Login json;
List<KeyValuePair<string, string?>> 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<SocketAppUser>(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<string, string?>("storage_id", Storage.StorageID.ToString()));
Storage.setid(data.id);
}
else
{
data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair<string, string?>("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<string, string?>("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<string, string?> 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<KeyExchange>(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!;
//API_Handler.IsAnyServerLoggedin = true;
return true;
}
else
{
throw new Exception(json?.ErrorMessage);
}
//API_Handler.IsAnyServerLoggedin = true;
return true;
}
private async Task<bool> 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<KeyValuePair<string, string?>> 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<SocketAppUser>(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<string, string?>("storage_id", Storage.StorageID.ToString()));
Storage.setid(data.id);
}
else
{
data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair<string, string?>("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<string, string?>("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<string, string?> 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<KeyExchange>(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!;
//API_Handler.IsAnyServerLoggedin = true;
return true;
}
else throw new Exception(json?.ErrorMessage);
//API_Handler.IsAnyServerLoggedin = true;
return true;
}
}