diff --git a/RelayCore/E2EeHelper.cs b/RelayClient/Crypto/E2EeHelper.cs
similarity index 98%
rename from RelayCore/E2EeHelper.cs
rename to RelayClient/Crypto/E2EeHelper.cs
index c4d5578..c17a0be 100644
--- a/RelayCore/E2EeHelper.cs
+++ b/RelayClient/Crypto/E2EeHelper.cs
@@ -1,7 +1,7 @@
using System.Security.Cryptography;
using System.Text;
-namespace RelayCore;
+namespace RelayClient.Crypto;
public static class E2EeHelper
{
diff --git a/RelayClient/Crypto/KeyStorage.cs b/RelayClient/Crypto/KeyStorage.cs
new file mode 100644
index 0000000..d55cbc3
--- /dev/null
+++ b/RelayClient/Crypto/KeyStorage.cs
@@ -0,0 +1,20 @@
+namespace RelayClient.Crypto;
+
+public static class KeyStorage
+{
+ public static void SavePrivateKey(string username, string privateKey)
+ {
+ Directory.CreateDirectory("keys");
+ File.WriteAllText(Path.Combine("keys", $"{username}.private.key"), privateKey);
+ }
+
+ public static string LoadPrivateKey(string username)
+ {
+ return File.ReadAllText(Path.Combine("keys", $"{username}.private.key"));
+ }
+
+ public static bool PrivateKeyExists(string username)
+ {
+ return File.Exists(Path.Combine("keys", $"{username}.private.key"));
+ }
+}
\ No newline at end of file
diff --git a/RelayClient/RelayClient.csproj b/RelayClient/RelayClient.csproj
index b536a2d..39a8d37 100644
--- a/RelayClient/RelayClient.csproj
+++ b/RelayClient/RelayClient.csproj
@@ -41,6 +41,7 @@
+
diff --git a/RelayCore/keys/.gitkeep b/RelayClient/keys/.gitkeep
similarity index 100%
rename from RelayCore/keys/.gitkeep
rename to RelayClient/keys/.gitkeep
diff --git a/RelayCore/Models/AuthAudits.cs b/RelayCore/Models/AuthAudits.cs
new file mode 100644
index 0000000..1bdacd2
--- /dev/null
+++ b/RelayCore/Models/AuthAudits.cs
@@ -0,0 +1,14 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class AuthAudits : Record
+{
+ public required string UserId { get; set; }
+ public required int EventType { get; set; }
+ public bool Success { get; set; }
+ public required string IpAddress { get; set; }
+ public required string UserAgent { get; set; }
+ public required string Details { get; set; }
+ public required DateTime CreatedAt { get; set; }
+}
\ No newline at end of file
diff --git a/RelayCore/Models/Licenses.cs b/RelayCore/Models/Licenses.cs
new file mode 100644
index 0000000..47657a4
--- /dev/null
+++ b/RelayCore/Models/Licenses.cs
@@ -0,0 +1,15 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class Licenses : Record
+{
+ public required string UserId { get; set; }
+ public required int LicenseType { get; set; }
+ public required int Status { get; set; }
+ public required DateTime CreatedAt { get; set; }
+ public required DateTime StartsAt { get; set; }
+ public required DateTime UpdatedAt { get; set; }
+ public required DateTime ExpiresAt { get; set; }
+
+}
\ No newline at end of file
diff --git a/RelayCore/Models/PasswordHash.cs b/RelayCore/Models/PasswordHash.cs
new file mode 100644
index 0000000..2e58139
--- /dev/null
+++ b/RelayCore/Models/PasswordHash.cs
@@ -0,0 +1,8 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class PasswordHash : Record
+{
+ public string? Password { get; set; }
+}
\ No newline at end of file
diff --git a/RelayCore/Models/PasswordHasher.cs b/RelayCore/Models/PasswordHasher.cs
index d8fbae5..425d50b 100644
--- a/RelayCore/Models/PasswordHasher.cs
+++ b/RelayCore/Models/PasswordHasher.cs
@@ -1,9 +1,8 @@
-using System;
-using System.Security.Cryptography;
+using System.Security.Cryptography;
using System.Text;
using Konscious.Security.Cryptography;
-namespace PasswordHasher
+namespace RelayCore.Models
{
///
/// Provides secure password hashing functionality using Argon2id algorithm
diff --git a/RelayCore/Models/PasswordReset.cs b/RelayCore/Models/PasswordReset.cs
new file mode 100644
index 0000000..acd03cc
--- /dev/null
+++ b/RelayCore/Models/PasswordReset.cs
@@ -0,0 +1,12 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class PasswordReset : Record
+{
+ public required string UserId { get; set; }
+ public required string TokenHash { get; set; }
+ public required DateTime CreatedAt { get; set; }
+ public required DateTime ExpiresAt { get; set; }
+ public bool Revoked { get; set; }
+}
\ No newline at end of file
diff --git a/RelayCore/Models/Sessions.cs b/RelayCore/Models/Sessions.cs
new file mode 100644
index 0000000..cefd0b8
--- /dev/null
+++ b/RelayCore/Models/Sessions.cs
@@ -0,0 +1,16 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class Sessions : Record
+{
+ public required string UserId { get; set; }
+ public required string TokenHash { get; set; }
+ public required DateTime IssuedAt { get; set; }
+ public required DateTime ExpiresAt { get; set; }
+ public DateTime? LastUsedAt { get; set; }
+ public bool Revoked { get; set; }
+ public required string DeviceName { get; set; }
+ public required string IpAddress { get; set; }
+ public required string UserAgent { get; set; }
+}
\ No newline at end of file
diff --git a/RelayCore/Models/Users.cs b/RelayCore/Models/Users.cs
new file mode 100644
index 0000000..1b3e20b
--- /dev/null
+++ b/RelayCore/Models/Users.cs
@@ -0,0 +1,17 @@
+using SurrealDb.Net.Models;
+
+namespace RelayCore.Models;
+
+public class Users : Record
+{
+ public required string Username { get; set; }
+ public string? Password { get; set; }
+ public required string Email { get; set; }
+ public required DateTime CreatedAt { get; set; }
+ public required DateTime UpdatedAt { get; set; }
+ public required DateTime LastLogin { get; set; }
+ public bool TwoFactorEnabled { get; set; }
+ public bool EmailVerified { get; set; }
+ public required int AccountStatus { get; set; }
+ public required int OnlineStatus { get; set; }
+}
\ No newline at end of file
diff --git a/RelayCore/Program.cs b/RelayCore/Program.cs
index 4b45823..649a2ef 100644
--- a/RelayCore/Program.cs
+++ b/RelayCore/Program.cs
@@ -2,10 +2,11 @@
using SurrealDb.Net.Models;
using SurrealDb.Net.Models.Auth;
using System.Text.Json;
-using PasswordHasher;
using RelayCore;
+using RelayCore.Enums;
+using RelayCore.Models;
-using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc");
+await using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc");
await db.SignIn(new RootAuth { Username = "root", Password = "secret" });
await db.Use("test", "test");
@@ -16,76 +17,6 @@ var kira = await CreateUserAsync(db, "Ru_Kira", "jduesling13@gmail.com", "passwo
Console.WriteLine($"Keeper created: {ToJsonString(keeper)}");
Console.WriteLine($"Kira created: {ToJsonString(kira)}");
-var keeperKeys = E2EeHelper.GenerateRsaKeyPair();
-var kiraKeys = E2EeHelper.GenerateRsaKeyPair();
-
-KeyStorage.SavePrivateKey("Keeper317", keeperKeys.privateKey);
-KeyStorage.SavePrivateKey("Ru_Kira", kiraKeys.privateKey);
-
-await db.Create("user_keys", new UserKeys
-{
- UserId = keeper.Id.ToString(),
- PublicKey = keeperKeys.publicKey,
- CreatedAt = DateTime.UtcNow,
- UpdatedAt = DateTime.UtcNow
-});
-
-await db.Create("user_keys", new UserKeys
-{
- UserId = kira.Id.ToString(),
- PublicKey = kiraKeys.publicKey,
- CreatedAt = DateTime.UtcNow,
- UpdatedAt = DateTime.UtcNow
-});
-
-Console.WriteLine("Public keys stored for both users.");
-
-var conversation = await db.Create("conversations", new Conversations
-{
- CreatedByUserId = keeper.Id.ToString(),
- CreatedAt = DateTime.UtcNow,
- UpdatedAt = DateTime.UtcNow,
- Title = "Keeper317 + Ru_Kira",
- IsDirectMessage = true
-});
-
-Console.WriteLine($"Conversation created: {ToJsonString(conversation)}");
-
-await db.Create("conversation_members", new ConversationMembers
-{
- ConversationId = conversation.Id.ToString(),
- UserId = keeper.Id.ToString(),
- JoinedAt = DateTime.UtcNow
-});
-
-await db.Create("conversation_members", new ConversationMembers
-{
- ConversationId = conversation.Id.ToString(),
- UserId = kira.Id.ToString(),
- JoinedAt = DateTime.UtcNow
-});
-
-Console.WriteLine("Conversation members added.");
-
-var encrypted = E2EeHelper.EncryptForRecipient("hello from Keeper317", kiraKeys.publicKey);
-
-var savedMessage = await db.Create("messages", new Messages
-{
- ConversationId = conversation.Id.ToString(),
- SenderUserId = keeper.Id.ToString(),
- RecipientUserId = kira.Id.ToString(),
- CipherText = encrypted.CipherText,
- Nonce = encrypted.Nonce,
- Tag = encrypted.Tag,
- EncryptedKey = encrypted.EncryptedKey,
- CreatedAt = DateTime.UtcNow
-});
-
-Console.WriteLine($"Encrypted message saved: {ToJsonString(savedMessage)}");
-
-var decrypted = E2EeHelper.DecryptForRecipient(encrypted, kiraKeys.privateKey);
-Console.WriteLine($"Decrypted for Ru_Kira: {decrypted}");
-
return;
static string ToJsonString(object? o)
@@ -112,7 +43,7 @@ static async Task CreateUserAsync(SurrealDbClient db, string username, st
var created = await db.Create("users", user);
- var hasher = new PasswordHasher.PasswordHasher();
+ var hasher = new PasswordHasher();
var passwordHash = hasher.HashPassword(created.Id.ToString() + rawPassword);
var updated = await db.Merge(new PasswordHash
@@ -122,177 +53,4 @@ static async Task CreateUserAsync(SurrealDbClient db, string username, st
});
return updated;
-}
-
-public static class KeyStorage
-{
- public static void SavePrivateKey(string username, string privateKey)
- {
- Directory.CreateDirectory("keys");
- File.WriteAllText(Path.Combine("keys", $"{username}.private.key"), privateKey);
- }
-
- public static string LoadPrivateKey(string username)
- {
- return File.ReadAllText(Path.Combine("keys", $"{username}.private.key"));
- }
-
- public static bool PrivateKeyExists(string username)
- {
- return File.Exists(Path.Combine("keys", $"{username}.private.key"));
- }
-}
-
-public class ResponsibilityMerge : Record
-{
- public bool Marketing { get; set; }
-}
-public class Group
-{
- public bool Marketing { get; set; }
- public int Count { get; set; }
-}
-
-public class Users : Record
-{
- public required string Username { get; set; }
- public string? Password { get; set; }
- public required string Email { get; set; }
- public required DateTime CreatedAt { get; set; }
- public required DateTime UpdatedAt { get; set; }
- public required DateTime LastLogin { get; set; }
- public bool TwoFactorEnabled { get; set; }
- public bool EmailVerified { get; set; }
- public required int AccountStatus { get; set; }
- public required int OnlineStatus { get; set; }
-}
-
-public class PasswordHash : Record
-{
- public string? Password { get; set; }
-}
-
-public class Sessions : Record
-{
- public required string UserId { get; set; }
- public required string TokenHash { get; set; }
- public required DateTime IssuedAt { get; set; }
- public required DateTime ExpiresAt { get; set; }
- public DateTime? LastUsedAt { get; set; }
- public bool Revoked { get; set; }
- public required string DeviceName { get; set; }
- public required string IpAddress { get; set; }
- public required string UserAgent { get; set; }
-}
-
-public class PasswordReset : Record
-{
- public required string UserId { get; set; }
- public required string TokenHash { get; set; }
- public required DateTime CreatedAt { get; set; }
- public required DateTime ExpiresAt { get; set; }
- public bool Revoked { get; set; }
-}
-
-public class Licenses : Record
-{
- public required string UserId { get; set; }
- public required int LicenseType { get; set; }
- public required int Status { get; set; }
- public required DateTime CreatedAt { get; set; }
- public required DateTime StartsAt { get; set; }
- public required DateTime UpdatedAt { get; set; }
- public required DateTime ExpiresAt { get; set; }
-
-}
-
-public class AuthAudits : Record
-{
- public required string UserId { get; set; }
- public required int EventType { get; set; }
- public bool Success { get; set; }
- public required string IpAddress { get; set; }
- public required string UserAgent { get; set; }
- public required string Details { get; set; }
- public required DateTime CreatedAt { get; set; }
-}
-
-public class UserKeys : Record
-{
- public required string UserId { get; set; }
- public required string PublicKey { get; set; }
- public required DateTime CreatedAt { get; set; }
- public required DateTime UpdatedAt { get; set; }
-}
-
-public class Conversations : Record
-{
- public required string CreatedByUserId { get; set; }
- public required DateTime CreatedAt { get; set; }
- public required DateTime UpdatedAt { get; set; }
- public string? Title { get; set; }
- public bool IsDirectMessage { get; set; }
-}
-
-public class ConversationMembers : Record
-{
- public required string ConversationId { get; set; }
- public required string UserId { get; set; }
- public required DateTime JoinedAt { get; set; }
-}
-
-public class Messages : Record
-{
- public required string ConversationId { get; set; }
- public required string SenderUserId { get; set; }
- public required string RecipientUserId { get; set; }
- public required string CipherText { get; set; }
- public required string Nonce { get; set; }
- public required string Tag { get; set; }
- public required string EncryptedKey { get; set; }
- public required DateTime CreatedAt { get; set; }
-}
-
-enum AccountStatuses
-{
- Active,
- Suspended,
- Banned,
- Deleted
-}
-
-enum OnlineStatuses
-{
- Online,
- Busy,
- DND,
- Invisible,
- Offline
-}
-
-enum LicenseStatuses
-{
- Active,
- Expired,
- Renewable,
- Revoked
-}
-
-enum LicenseType
-{
- Free,
- Basic,
- Advanced,
- Pro,
- Enterprise
-}
-
-enum LogEvents
-{
- LoginSuccess,
- LoginFailure,
- LogoutSuccess,
- LogoutFailure,
- PasswordResetSuccess,
- PasswordResetFailure,
}
\ No newline at end of file
diff --git a/RelayServer/Models/ConversationMembers.cs b/RelayServer/Models/ConversationMembers.cs
new file mode 100644
index 0000000..27dd399
--- /dev/null
+++ b/RelayServer/Models/ConversationMembers.cs
@@ -0,0 +1,10 @@
+using SurrealDb.Net.Models;
+
+namespace RelayServer.Models;
+
+public class ConversationMembers : Record
+{
+ public required string ConversationId { get; set; }
+ public required string UserId { get; set; }
+ public required DateTime JoinedAt { get; set; }
+}
\ No newline at end of file
diff --git a/RelayServer/Models/Conversations.cs b/RelayServer/Models/Conversations.cs
new file mode 100644
index 0000000..9788ea2
--- /dev/null
+++ b/RelayServer/Models/Conversations.cs
@@ -0,0 +1,12 @@
+using SurrealDb.Net.Models;
+
+namespace RelayServer.Models;
+
+public class Conversations : Record
+{
+ public required string CreatedByUserId { get; set; }
+ public required DateTime CreatedAt { get; set; }
+ public required DateTime UpdatedAt { get; set; }
+ public string? Title { get; set; }
+ public bool IsDirectMessage { get; set; }
+}
\ No newline at end of file
diff --git a/RelayServer/Models/Messages.cs b/RelayServer/Models/Messages.cs
new file mode 100644
index 0000000..1a91e52
--- /dev/null
+++ b/RelayServer/Models/Messages.cs
@@ -0,0 +1,15 @@
+using SurrealDb.Net.Models;
+
+namespace RelayServer.Models;
+
+public class Messages : Record
+{
+ public required string ConversationId { get; set; }
+ public required string SenderUserId { get; set; }
+ public required string RecipientUserId { get; set; }
+ public required string CipherText { get; set; }
+ public required string Nonce { get; set; }
+ public required string Tag { get; set; }
+ public required string EncryptedKey { get; set; }
+ public required DateTime CreatedAt { get; set; }
+}
\ No newline at end of file
diff --git a/RelayServer/Models/UserKeys.cs b/RelayServer/Models/UserKeys.cs
new file mode 100644
index 0000000..0dbf6fd
--- /dev/null
+++ b/RelayServer/Models/UserKeys.cs
@@ -0,0 +1,11 @@
+using SurrealDb.Net.Models;
+
+namespace RelayServer.Models;
+
+public class UserKeys : Record
+{
+ public required string UserId { get; set; }
+ public required string PublicKey { get; set; }
+ public required DateTime CreatedAt { get; set; }
+ public required DateTime UpdatedAt { get; set; }
+}
\ No newline at end of file
diff --git a/RelayServer/RelayServer.csproj b/RelayServer/RelayServer.csproj
index 6c1dc92..11711eb 100644
--- a/RelayServer/RelayServer.csproj
+++ b/RelayServer/RelayServer.csproj
@@ -7,4 +7,8 @@
enable
+
+
+
+