diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..67dd9f8
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,26 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Use IntelliSense to find out which attributes exist for C# debugging
+ // Use hover for the description of the existing attributes
+ // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // If you have changed target frameworks, make sure to update the program path.
+ "program": "${workspaceFolder}/client/bin/Debug/net8.0/client.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/client",
+ // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..c2e2b15
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/online_security_project.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/online_security_project.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/online_security_project.sln"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/Program.cs b/client/Program.cs
index 3751555..8381c75 100644
--- a/client/Program.cs
+++ b/client/Program.cs
@@ -1,2 +1,50 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
+using System;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Client;
+
+public class Program
+{
+ static void Main(string[] args)
+ {
+ using TcpClient client = new("127.0.0.1", 12345);
+
+ byte[] toSend = Encoding.ASCII.GetBytes("hello server");
+
+ var stream = client.GetStream();
+
+ var inputTask = Task.Run(async () => await HandleUserInput(client, stream));
+ var serverInput = Task.Run(async () => await HandleServerInput(client, stream));
+
+ _ = Task.WaitAny(inputTask, serverInput);
+
+ }
+
+ static async Task HandleUserInput(TcpClient client, NetworkStream stream) {
+ while(client.Connected) {
+ string? input = Console.ReadLine();
+ if(input == null) {
+ await Task.Delay(100);
+ continue;
+ }
+ else {
+ stream.Write(Encoding.ASCII.GetBytes(input));
+ Console.WriteLine($"[{DateTime.Now}]Sent to server: {input}");
+ }
+ }
+ }
+
+ static async Task HandleServerInput(TcpClient client, NetworkStream stream) {
+ byte[] buffer = new byte[1024];
+ while(client.Connected) {
+ int readLen = await stream.ReadAsync(buffer);
+ if(readLen != 0) {
+ string fromServer = Encoding.ASCII.GetString(buffer[..readLen]);
+ Console.WriteLine($"[{DateTime.Now}]\t\tFrom server: {fromServer}");
+
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/client.csproj b/client/client.csproj
index 47ba6e4..84912b2 100644
--- a/client/client.csproj
+++ b/client/client.csproj
@@ -7,7 +7,7 @@
Exe
net8.0
- enable
+ disable
enable
diff --git a/lib/Class1.cs b/lib/Class1.cs
deleted file mode 100644
index 34def2d..0000000
--- a/lib/Class1.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace lib;
-
-public class Class1
-{
-
-}
diff --git a/lib/Request.cs b/lib/Request.cs
new file mode 100644
index 0000000..e954151
--- /dev/null
+++ b/lib/Request.cs
@@ -0,0 +1,10 @@
+namespace lib;
+
+public enum RequestType {
+ Register = 1,
+ ConfirmRegister = 2,
+ GetMessages = 3,
+ GetUserKey = 4,
+ SendMessage = 5,
+ SendAck = 6
+}
\ No newline at end of file
diff --git a/lib/Utils.cs b/lib/Utils.cs
new file mode 100644
index 0000000..8139470
--- /dev/null
+++ b/lib/Utils.cs
@@ -0,0 +1,53 @@
+using System.Text;
+using System.Linq;
+
+namespace lib;
+
+public static class Utils {
+ public static byte[] NumberToBytes(string Number) {
+ if(Number.Any(c => !char.IsDigit(c)) || Number.Length > 16) {
+ throw new Exception("Invalid arguments!");
+ }
+ byte[] res = Enumerable.Repeat((byte)0b1111_1111, 8).ToArray();
+ // Pad Number if needed to be of even length (because each 2 digits are turned into 1 byte)
+ Number = Number.Length % 2 == 0 ? Number : Number + '-';
+
+ for(int i = 0; i < Number.Length - 1; i += 2) {
+ char c1 = Number[i];
+ char c2 = Number[i + 1];
+ res[i / 2] = (byte)((DigitToByte(c1) << 4) | DigitToByte(c2));
+ }
+ return res;
+ }
+
+ public static string BytesToNumber(byte[] Bytes) {
+ string s = "";
+ foreach(byte b in Bytes) {
+ byte b1 = (byte)((b >> 4) & 0b1111);
+ byte b2 = (byte)(b & 0b1111);
+ s = s + ByteToDigit(b1) + ByteToDigit(b2);
+ }
+ return new string(s.Where(c => char.IsDigit(c)).ToArray());
+ }
+
+
+ public static byte DigitToByte(char c) {
+ if (int.TryParse(c.ToString(), out int d)) {
+ return (byte)d;
+ }
+ else {
+ return 0b1111; // empty, turned into '-' later to be discarded
+ }
+ }
+
+ public static char ByteToDigit(byte b) {
+ byte offset = Encoding.ASCII.GetBytes("0")[0];
+
+ if(b == 0b1111) {
+ return '-';
+ }
+ else {
+ return Encoding.ASCII.GetChars([(byte)(b + offset)])[0];
+ }
+ }
+}
\ No newline at end of file
diff --git a/online_security_project.sln b/online_security_project.sln
index 704057d..6e29e6d 100644
--- a/online_security_project.sln
+++ b/online_security_project.sln
@@ -5,6 +5,10 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client\client.csproj", "{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server", "server\server.csproj", "{36C3F9FE-FA02-4AC0-89A2-65B377767C8F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lib", "lib\lib.csproj", "{8E625330-2219-4E74-8524-A947D783B3BB}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +22,13 @@ Global
{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}.Release|Any CPU.Build.0 = Release|Any CPU
+ {36C3F9FE-FA02-4AC0-89A2-65B377767C8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {36C3F9FE-FA02-4AC0-89A2-65B377767C8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {36C3F9FE-FA02-4AC0-89A2-65B377767C8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {36C3F9FE-FA02-4AC0-89A2-65B377767C8F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8E625330-2219-4E74-8524-A947D783B3BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8E625330-2219-4E74-8524-A947D783B3BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8E625330-2219-4E74-8524-A947D783B3BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8E625330-2219-4E74-8524-A947D783B3BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/protocol.md b/protocol.md
index f999141..26b32d8 100644
--- a/protocol.md
+++ b/protocol.md
@@ -3,11 +3,29 @@
All encryptions are made using RSA (key size to be determined), no symmetric encryptions
are used due to messages being short.
+a. Encryption will be a-symmetric because we can assume messages are short
+b. See "Registration" below
+c. Server keeps public keys for everyone, and gives them to a user when they want to
+send a message to someone (only the relevant key)
+d. Every e2e message is both signed and encrypted aka, message M from A to B
+`EM = E_Bpub(E_Apriv(N))`
+e. message is sent to the server in a `E_server(E_Apriv(metadata + EM from d))`,
+message ack is sent to the server as a `MessageAck(msg_id)`, which will be retrieved
+by the user when it pulls for messages.
+f. TODO: properly explain the different api structs
+g. TODO: properly explain how the server handles data
+
+### Key Derivation Function
+
+as there is no use of symmetric keys (at least for this scope), I dont believe there
+is a need to use KDF, it will reduce the keyspace and we already have the public key
+of the server in the clients
+
## Registration:
- User sends a register request to server `(phone number, RSA public key)`,
giving them a public key and encrypting using the server's public key
-- Server sends the user a `Confirm` message & a 6-digit code
+- Server sends the user a `VerificationRequired` message & a 6-digit code (Secure channel)
- User sends the server the 6-digit code, signed using the key provided at stage 1
(this message is very short and funny, because its a 6-digit code, signed using the
user's private key, and encrypted using the server's public key)
@@ -27,3 +45,41 @@ request and ultimately signed by A and encrypted using the server's key.
The server will hold on to the message until B will send a `GetMessages` request
to the server.
+
+## "Control" requests
+
+- Register `(phone, pub RSA key)`
+ extra data: RSA key size (payload length)
+- ConfirmRegister (signed & encrypted 6 digit code)
+ extra data: 6 bytes for the 6 digit code (can use less but it will be padding otherwise)
+- GetMessages (signed & encrypted to not allow someone to "flush" someone else's msgs)
+ extra data: EMPTY
+- GetUserKey (dont think it needs any signing or encryption technically, as it is very
+ simple registering and "stealing" a key outside the system, keys are assumed to be
+ unbreakable)
+ extra data: 8 bytes (4 bits per digit) of whoever we want to get the key of
+- SendMessage `(to_user, msg_id, EM from d above)`
+ extra data: 8 bytes (4 bits per digit) of who to send the data, 4 bytes (32bit) for length
+- SendAck `(to_user, msg_id - signed and encrypted)`
+ - server doesnt know if the msg itself is indeed valid and not tempered with
+ extra data: 8 bytes (4 bits per digit) of who to send the data, 4 bytes (32bit) for length
+
+I think it all can go into a:
+```
+{
+ Version byte (0) - 1 byte
+ RequestType - 1 byte,
+ Phone number - 8 bytes (every 4 bits is a number, so we have 16 numbers),
+ UTC timestamp - 8 bytes (long),
+ extra data (based on the request given) - up to 18 bytes
+} = 32 bytes = 256 bits
+```
+and we can just append encrypted payloads to it (in SendMessage and SendAck)
+
+To each message we also append a sha3-256 signed hash
+
+enc_server( request - 256 bits, signed sha3-256 )
+
+which means:
+ Keys: RSA-512
+ Hashes: SHA3-256
\ No newline at end of file
diff --git a/server/Program.cs b/server/Program.cs
index 3751555..e361765 100644
--- a/server/Program.cs
+++ b/server/Program.cs
@@ -1,2 +1,44 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Server;
+
+public class Program
+{
+ static void Main(string[] args)
+ {
+ int port = 12345;
+ TcpListener server = new(IPAddress.Parse("0.0.0.0"), port);
+ try {
+ server.Start();
+ byte[] buffer = new byte[256];
+
+ while(true) {
+ // Currently, every time it gets a block, it will simply send it back but ToUpper
+ using TcpClient client = server.AcceptTcpClient();
+ Console.WriteLine("Got a client!");
+
+ var stream = client.GetStream();
+ int readLen;
+ while((readLen = stream.Read(buffer, 0, buffer.Length)) != 0) {
+ // for now, lets just read it as an ascii string
+ string input = System.Text.Encoding.ASCII.GetString(buffer, 0, readLen);
+ Console.WriteLine($"Got block: {input}");
+
+ byte[] ret = System.Text.Encoding.ASCII.GetBytes(input.ToUpper());
+ stream.Write(ret, 0, ret.Length);
+ }
+
+
+ }
+ }
+ catch(Exception ex) {
+ Console.WriteLine($"Server error: {ex.Message}");
+ Console.WriteLine("Trace: " + ex.StackTrace);
+ }
+ finally {
+ server.Stop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/server.csproj b/server/server.csproj
index 47ba6e4..84912b2 100644
--- a/server/server.csproj
+++ b/server/server.csproj
@@ -7,7 +7,7 @@
Exe
net8.0
- enable
+ disable
enable