protocol expansion

build a navy
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-05-19 16:02:39 -05:00
parent c5b50246a7
commit 4e89dcab07
10 changed files with 367 additions and 61 deletions

View file

@ -34,7 +34,7 @@
@media screen and (max-width: 480px) {
.content {
width: 75%;
width: 100%;
}
}

View file

@ -12,7 +12,7 @@
</script>
<script type="notjs" id="loading-frag">
</script>
</head>
<body>

View file

@ -1 +0,0 @@
declare function md5(input: string, key?: string, raw?: boolean);

View file

@ -1,3 +1,12 @@
<style type="text/css">
.right { text-align: right; }
.center { text-align: center; }
.left { text-align: left; }
table { margin-right: 8px; }
td { text-align: center; }
.flex { display: flex; flex-wrap: wrap; }
</style>
# PROTOCOL DEFINITION
Messages communicated between the client and server follow the same format, but have different meanings depending on which end is the recipient. A message's intent is determined by its packet ID, a unique identifier that tells the client or server how it should react to the received message. A message id that incites bidirectional communication between the client and server should typically be associated with the same message id on the client as on the server, so as to avoid confusion.
@ -29,66 +38,227 @@ All numbers, unless otherwise specified, are the string representation of a base
* User IDs: 8 bytes, integer, unsigned
* Co-ordinates: 8 bytes, double-precision float
* Big Int: Hex string, variable size
### Packet IDs
A packet ID may have a specific "direction" of communication, in that an endpoint may either act as a _requester_ or a _responder_. A _requester_ is an endpoint that drives all of the communication on that specific packet ID, while the _responder_ is responsible for providing a timely response to the requests. A _responder_ for a specific packet ID should never send that packet ID unsolicited; either the packet will be ignored or the other endpoint will close the connect. Any packet ID marked as bidirectional may be initiated by either endpoint at any time.
A packet ID may have a specific "direction" of communication, in that an endpoint may either act as a _requester_ or a _responder_. A _requester_ is an endpoint that drives all of the communication on that specific packet ID, while the _responder_ is responsible for providing a timely response to the requests it receives. A _responder_ for a specific packet ID should never send that packet ID unsolicited; either the packet will be ignored or the other endpoint will close the connection. Any packet ID marked as bidirectional may be initiated by either endpoint at any time.
#### Server to Client
<table>
<thead>
<th colspan="100">
<center>
<div class="flex">
<!--
<table class="float">
<thead>
<th colspan="100" class="center">
ID 0: Key Exchange<br />
Requester
</center>
</th>
</thead>
<thead>
<th colspan="2">#</th>
<th>Region</th>
<th>Type</th>
<th>Enum</th>
</thead>
<tr style="text-align: center;">
<td colspan="2">1</td>
<td>Step</td>
<td>Byte</td>
</th>
</thead>
<thead>
<th colspan="2" class="right">#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td><i>s &isin; [0, 2]</i></td>
</tr>
<tr style="text-align: center;">
<td><i>s = 0</i></td>
<td>2</td>
<td>Generator</td>
<td>Byte</td>
<td></td>
</tr>
</table>
<td class="right">1</td>
<td>Step</td>
<td>Uint8</td>
</tr>
<tr>
<td><i>s = 0</i></td>
<td class="right">2</td>
<td>Generator</td>
<td>Big Int</td>
</tr>
<tr>
<td><i>s = 0</i></td>
<td class="right">3</td>
<td>Modulus</td>
<td>Big Int</td>
</tr>
<tr>
<td><i>s = 1</i></td>
<td class="right">2</td>
<td>Server Key</td>
<td>Big Int</td>
</tr>
</table>
-->
<table>
<thead>
<th colspan="100" class="center">
ID 0: Key Exchange<br />
Requester
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td>1</td>
<td>Generator</td>
<td>Big Int</td>
</tr>
<tr>
<td>2</td>
<td>Modulus</td>
<td>Big Int</td>
</tr>
<tr>
<td>3</td>
<td>Server Key</td>
<td>Big Int</td>
</tr>
</table>
<table>
<thead>
<th colspan="100" class="center">
ID 1: Login Attempt<br />
[Encrypted] Responder
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Succeeded</td>
<td>Boolean</td>
</tr>
<tr>
<td class="center">3</td>
<td>Message</td>
<td>String</td>
</tr>
</table>
<table>
<thead>
<th colspan="100" class="center">
ID 2: Registration Attempt<br />
[Encrypted] Responder
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Succeeded</td>
<td>Boolean</td>
</tr>
<tr>
<td class="center">3</td>
<td>Message</td>
<td>String</td>
</tr>
</table>
</div>
#### Client to Server
<table>
<thead>
<th colspan="100">
<center>
ID 0: Key Exchange<br />
Responder
</center>
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th></th>
<th></th>
<th></th>
<th>Type</th>
</thead>
<tr>
<td>1</td>
</tr>
</table>
<div class="flex">
<table>
<thead>
<th colspan="100" class="center">
ID 0: Key Exchange<br />
Responder
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td class="center">1</td>
<td>Client Key</td>
<td>Big Int</td>
</tr>
</table>
<table>
<thead>
<th colspan="100" class="center">
ID 1: Login Attempt<br />
[Encrypted] Requester
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Username</td>
<td>String</td>
</tr>
<tr>
<td class="center">3</td>
<td>Password</td>
<td>String</td>
</tr>
</table>
<table>
<thead>
<th colspan="100" class="center">
ID 2: Registration Attempt<br />
[Encrypted] Requester
</th>
</thead>
<thead>
<th>#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Username</td>
<td>String</td>
</tr>
<tr>
<td class="center">3</td>
<td>Password</td>
<td>String</td>
</tr>
<tr>
<td class="center">4</td>
<td>Email</td>
<td>String</td>
</tr>
</table>
</div>
## Sockstamps

View file

@ -99,6 +99,7 @@
</Compile>
<Compile Include="Encryption\KeyExchange.cs" />
<Compile Include="Encryption\Cipher.cs" />
<Compile Include="Socks\Packet.cs" />
<Compile Include="Socks\ActiveConnection.cs" />
<Compile Include="Entrypoint.cs" />
<Compile Include="Socks\PendingConnection.cs" />

View file

@ -18,6 +18,9 @@ namespace CircleScape.Encryption {
Modulus = RNG.NextPrime(512 / 8);
}
public Packet GenerateInitialPacket() {
return
}
}
}

View file

@ -11,9 +11,6 @@ using Square;
namespace CircleScape {
class Entrypoint {
static void Main(string[] args) {
var a = Square.RNG.NextPrime(512 / 8);
Console.WriteLine(a.ToString("X"));
var server = new Kneesocks.Server<PendingConnection>(6770, PoolManager.Pending);
server.Start();

View file

@ -69,12 +69,12 @@ namespace Kneesocks {
var headerLengthFirstByte = (byte)Content.Length;
if(bodySize >= 0x7E && bodySize <= 0xFFFF) {
headerSize += 2;
headerLengthFirstByte = 126;
headerLengthFirstByte = 0x7e;
} else if(bodySize > 0xFFFF) {
headerSize += 8;
headerLengthFirstByte = 127;
headerLengthFirstByte = 0x7f;
}
var headerLengthSize = (int)headerSize - 1;
var headerLengthSize = headerSize - 1;
if(IsMasked)
headerSize += 4;
@ -105,9 +105,9 @@ namespace Kneesocks {
var lengthByte = raw[1] & 0x7F;
return 2
+ ((raw[1] & 0x80) != 0 ? 4: 0)
+ (lengthByte == 0x7E ? 2 : 0)
+ (lengthByte == 0x7F ? 8 : 0);
+ ((raw[1] & 0x80) != 0 ? 4 : 0)
+ (lengthByte == 0x7E ? 2 : 0)
+ (lengthByte == 0x7F ? 8 : 0);
}
public static Frame HeaderFromBytes(byte[] raw) {

View file

@ -7,7 +7,7 @@ using System.Numerics;
namespace Square {
public static class RNG {
private static System.Random RandCtx = new System.Random();
private static Random RandCtx = new Random();
public static int Next() {
lock(RandCtx) {

136
server/Socks/Packet.cs Normal file
View file

@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Square;
namespace CircleScape {
class Packet {
public enum kId {
KeyExchange = 0,
LoginAttempt,
RegistrationAttempt
}
private static Packet ErrorPacket {
get {
return new Packet { IsLegal = false };
}
}
public static Packet FromRaw(byte[] raw) {
if(raw.Length < 3)
return ErrorPacket;
Packet packet = new Packet();
if(!Enum.IsDefined(typeof(kId), raw[0]))
return ErrorPacket;
packet.Id = (kId)raw[0];
var regionCount = raw[1];
var regionLengths = new List<uint>();
var headerPtr = 2;
for(var i = 0; i < regionCount; ++i) {
var first = raw[headerPtr];
if(first < 254) {
regionLengths[i] = first;
++headerPtr;
} else if(first == 254) {
if(headerPtr + 3 < raw.Length)
return ErrorPacket;
regionLengths[i] = raw.Subset(headerPtr + 1, 2).UnpackUInt16();
headerPtr += 3;
} else {
if(headerPtr + 5 < raw.Length)
return ErrorPacket;
regionLengths[i] = raw.Subset(headerPtr + 1, 4).UnpackUInt32();
headerPtr += 5;
}
if(headerPtr > raw.Length)
return ErrorPacket;
}
if(headerPtr + regionLengths.Sum(x => x) < raw.Length)
return ErrorPacket;
long bodyPtr = headerPtr;
foreach(var regionLength in regionLengths) {
// FLAG this could fail if one region exceeds 2^31-1 in size, check later
packet.Regions.Add(raw.Subset((int)bodyPtr, (int)regionLength));
bodyPtr += regionLength;
}
return packet;
}
private List<byte[]> Regions = new List<byte[]>();
public kId Id { get; private set; } = kId.KeyExchange;
public bool IsLegal { get; private set; } = true;
public int RegionCount {
get {
return Regions.Count;
}
}
public Packet(kId id, params object[] regions) {
Id = id;
foreach(var region in regions) {
if(region.GetType() == typeof(byte[]))
Regions.Add((byte[])region);
else if(region.GetType() == typeof(string))
Regions.Add(((string)region).GetBytes());
}
}
public Region this[int i] {
get {
return new Region(Regions[i]);
}
}
public byte[] GetBytes() {
if(!IsLegal)
return null;
var header = new List<byte>();
IEnumerable<byte> body = new byte[0];
foreach(var region in Regions) {
if(region.Length < 254)
header.Add((byte)region.Length);
else if(region.Length <= 0xFFFF) {
header.Add(254);
header.AddRange(((UInt16)region.Length).Pack());
} else {
header.Add(255);
header.AddRange(region.Length.Pack());
}
body = body.Concat(region);
}
return header.Concat(body).ToArray();
}
}
class Region {
public byte[] Data { get; private set; }
public Region(byte[] data) {
Data = data;
}
public static implicit operator byte[](Region region) {
return region.Data;
}
public static implicit operator string(Region region) {
try {
return Encoding.UTF8.GetString(region.Data);
} catch {
return Encoding.ASCII.GetString(region.Data);
}
}
}
}