started working o nstuff yay

This commit is contained in:
Rusty Striker 2024-12-14 17:17:58 +02:00
parent 2df8de0a3e
commit 65f5a95dac
Signed by: RustyStriker
GPG key ID: 87E4D691632DFF15
11 changed files with 295 additions and 13 deletions

26
.vscode/launch.json vendored Normal file
View file

@ -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"
}
]
}

41
.vscode/tasks.json vendored Normal file
View file

@ -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"
}
]
}

View file

@ -1,2 +1,50 @@
// See https://aka.ms/new-console-template for more information using System;
Console.WriteLine("Hello, World!"); 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}");
}
}
}
}

View file

@ -7,7 +7,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>

View file

@ -1,6 +0,0 @@
namespace lib;
public class Class1
{
}

10
lib/Request.cs Normal file
View file

@ -0,0 +1,10 @@
namespace lib;
public enum RequestType {
Register = 1,
ConfirmRegister = 2,
GetMessages = 3,
GetUserKey = 4,
SendMessage = 5,
SendAck = 6
}

53
lib/Utils.cs Normal file
View file

@ -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];
}
}
}

View file

@ -5,6 +5,10 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client\client.csproj", "{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client\client.csproj", "{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}"
EndProject 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{F38E98E8-4FE8-4F34-B5A7-004444ED1F50}.Release|Any CPU.Build.0 = 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 EndGlobalSection
EndGlobal EndGlobal

View file

@ -3,11 +3,29 @@
All encryptions are made using RSA (key size to be determined), no symmetric encryptions All encryptions are made using RSA (key size to be determined), no symmetric encryptions
are used due to messages being short. 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: ## Registration:
- User sends a register request to server `(phone number, RSA public key)`, - 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 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 - 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 (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) 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 The server will hold on to the message until B will send a `GetMessages` request
to the server. 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

View file

@ -1,2 +1,44 @@
// See https://aka.ms/new-console-template for more information using System;
Console.WriteLine("Hello, World!"); 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();
}
}
}

View file

@ -7,7 +7,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>