JacobTech
69168acd22
Server class can't have an API class property, or a loop will prevent building.
357 lines
16 KiB
C#
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;
|
|
}
|
|
} |