started working o nstuff yay
This commit is contained in:
parent
2df8de0a3e
commit
65f5a95dac
11 changed files with 295 additions and 13 deletions
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal 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
41
.vscode/tasks.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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}");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
namespace lib;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
10
lib/Request.cs
Normal file
10
lib/Request.cs
Normal 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
53
lib/Utils.cs
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
58
protocol.md
58
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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
Loading…
Reference in a new issue