Skip to content

Commit

Permalink
feat: update UDP architecture but, I do not test current
Browse files Browse the repository at this point in the history
  • Loading branch information
elecbug committed Sep 21, 2024
1 parent dba4bd2 commit 09de9a6
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using SecSess.Key;
using SecSess.Secure.Algorithm;

namespace SecSess.Interface
namespace SecSess.Interface.Key
{
/// <summary>
/// Interface that defines saves and loads in file
/// </summary>
public interface IKeyPair<T> where T : AsymmetricKeyBase
public interface IAsymmetricKey<T> where T : AsymmetricKeyBase
{
public abstract void Save(string path);
public abstract static T Load(Asymmetric algorithm, string path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using SecSess.Secure.Wrapper;
using SecSess.Tcp;
using SecSess.Util;
using System.Net.Sockets;
using System.Security.Authentication;

namespace SecSess.Interface
namespace SecSess.Interface.Tcp
{
/// <summary>
/// The interface that manages the stream (mainly on the client side)
Expand Down Expand Up @@ -175,6 +174,7 @@ internal static byte[] InternalRead(Symmetric symmetric, byte[] hmacKey, Secure.

public abstract void Write(byte[] data);
public abstract byte[] Read();

public abstract bool CanUseStream(StreamType type = StreamType.All);
public abstract void FlushStream();
}
Expand Down
154 changes: 154 additions & 0 deletions SecSess/Interface/Udp/IStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using SecSess.Secure.Wrapper;
using System.Net;
using System.Net.Sockets;
using System.Security.Authentication;

namespace SecSess.Interface.Udp
{
internal interface IStream
{

/// <summary>
/// Internal real implementation of a Write method
/// </summary>
/// <param name="data">Data that write</param>
/// <param name="symmetric">Symmetric secure algorithm</param>
/// <param name="hmacKey">HMAC key for auth</param>
/// <param name="hash">Hash algorithm to use</param>
/// <param name="client">A UDP client that actually works</param>
/// <param name="remoteEP">Remote IP end point to write or read</param>
internal static void InternalWrite(byte[] data, Symmetric symmetric, byte[] hmacKey, Secure.Algorithm.Hash hash, UdpClient client, IPEndPoint remoteEP)
{
if (symmetric.Algorithm != Secure.Algorithm.Symmetric.None)
{
byte[] iv = new byte[Symmetric.BlockSize(symmetric.Algorithm)];
new Random().NextBytes(iv);

byte[] lenBit = BitConverter.GetBytes(data.Length);
byte[] msg = new byte[data.Length + 4];

Buffer.BlockCopy(lenBit, 0, msg, 0, lenBit.Length);
Buffer.BlockCopy(data, 0, msg, lenBit.Length, data.Length);

byte[] enc = symmetric.Encrypt(msg, iv);
byte[] packet = new byte[iv.Length + enc.Length];

Buffer.BlockCopy(iv, 0, packet, 0, iv.Length);
Buffer.BlockCopy(enc, 0, packet, iv.Length, enc.Length);

if (hmacKey.Length == 0)
{
client.Send(packet, packet.Length, remoteEP);
}
else
{
byte[] hmacs = new byte[packet.Length + Hash.HashDataSize(hash)];

Buffer.BlockCopy(packet, 0, hmacs, 0, packet.Length);
Buffer.BlockCopy(Hash.HMacData(hash, hmacKey, packet), 0, hmacs, packet.Length, Hash.HashDataSize(hash));

client.Send(hmacs, hmacs.Length, remoteEP);
}
}
else
{
byte[] lenBit = BitConverter.GetBytes(data.Length);
byte[] msg = new byte[4 + data.Length];

Buffer.BlockCopy(lenBit, 0, msg, 0, lenBit.Length);
Buffer.BlockCopy(data, 0, msg, lenBit.Length, data.Length);

client.Send(msg, msg.Length, remoteEP);
}
}

/// <summary>
/// Internal real implementation of a Read method
/// </summary>
/// <param name="symmetric">Symmetric secure algorithm</param>
/// <param name="hmacKey">HMAC key for auth</param>
/// <param name="hash">Hash algorithm to use</param>
/// <param name="client">A UDP client that actually works</param>
/// <param name="remoteEP">Remote IP end point to write or read</param>
/// <returns>Data that read</returns>
internal static byte[] InternalRead(Symmetric symmetric, byte[] hmacKey, Secure.Algorithm.Hash hash, UdpClient client, ref IPEndPoint remoteEP)
{
if (symmetric.Algorithm != Secure.Algorithm.Symmetric.None)
{
byte[] fullData = client.Receive(ref remoteEP);

byte[] iv = fullData[0..Symmetric.BlockSize(symmetric.Algorithm)];
byte[] enc1 = fullData[iv.Length..(iv.Length + Symmetric.BlockSize(symmetric.Algorithm))];

byte[] msg1 = symmetric.Decrypt(enc1, iv);

int len = BitConverter.ToInt32(msg1[0..4]);
int blockCount = (len + 4) / enc1.Length + ((len + 4) % enc1.Length == 0 ? 0 : 1);

if ((blockCount - 1) * enc1.Length != 0)
{
byte[] enc2 = fullData[(iv.Length + enc1.Length)..(iv.Length + blockCount * enc1.Length)];

byte[] msg2 = symmetric.Decrypt(enc2, enc1);
byte[] data = new byte[len];

Buffer.BlockCopy(msg1, 4, data, 0, msg1.Length - 4);
Buffer.BlockCopy(msg2, 0, data, msg1.Length - 4, len - (msg1.Length - 4));

if (hmacKey.Length != 0)
{
byte[] concat = new byte[iv.Length + enc1.Length + enc2.Length];

Buffer.BlockCopy(iv, 0, concat, 0, iv.Length);
Buffer.BlockCopy(enc1, 0, concat, iv.Length, enc1.Length);
Buffer.BlockCopy(enc2, 0, concat, iv.Length + enc1.Length, enc2.Length);

byte[] hmacs = fullData[(iv.Length + enc1.Length + enc2.Length)
..(iv.Length + enc1.Length + enc2.Length + Hash.HashDataSize(hash))];

byte[] compare = Hash.HMacData(hash, hmacKey, concat);

if (compare.SequenceEqual(hmacs) == false)
{
throw new AuthenticationException("HMAC authentication is failed.");
}
}

return data;
}
else
{
byte[] concat = new byte[iv.Length + enc1.Length];

Buffer.BlockCopy(iv, 0, concat, 0, iv.Length);
Buffer.BlockCopy(enc1, 0, concat, iv.Length, enc1.Length);

byte[] hmacs = fullData[(iv.Length + enc1.Length)
..(iv.Length + enc1.Length + Hash.HashDataSize(hash))];

byte[] compare = Hash.HMacData(hash, hmacKey, concat);

if (compare.SequenceEqual(hmacs) == false)
{
throw new AuthenticationException("HMAC authentication is failed.");
}

return msg1[4..(len + 4)];
}
}
else
{
byte[] fullData = client.Receive(ref remoteEP);
byte[] lenBit = fullData[0..4];

int len = BitConverter.ToInt32(lenBit);
byte[] msg = fullData[lenBit.Length..(4 + len)];

return msg;
}
}

public abstract void Write(byte[] data, IPEndPoint remoteEP);
public abstract byte[] Read(ref IPEndPoint remoteEP);
}
}
4 changes: 2 additions & 2 deletions SecSess/Key/PrivateKey.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using System.Security.Cryptography;
using SecSess.Interface;
using SecSess.Interface.Key;
using SecSess.Secure.Algorithm;

namespace SecSess.Key
{
/// <summary>
/// Private key warpper type
/// </summary>
public class PrivateKey : AsymmetricKeyBase, IKeyPair<PrivateKey>
public class PrivateKey : AsymmetricKeyBase, IAsymmetricKey<PrivateKey>
{
/// <summary>
/// Create a private key
Expand Down
4 changes: 2 additions & 2 deletions SecSess/Key/PublicKey.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using System.Security.Cryptography;
using SecSess.Interface;
using SecSess.Interface.Key;
using SecSess.Secure.Algorithm;

namespace SecSess.Key
{
/// <summary>
/// Public key warpper type
/// </summary>
public class PublicKey : AsymmetricKeyBase, IKeyPair<PublicKey>
public class PublicKey : AsymmetricKeyBase, IAsymmetricKey<PublicKey>
{
/// <summary>
/// Create a public key
Expand Down
42 changes: 21 additions & 21 deletions SecSess/Tcp/Client.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using SecSess.Interface;
using SecSess.Interface.Tcp;
using SecSess.Key;
using SecSess.Secure.Wrapper;
using SecSess.Util;
using System.Net;
using System.Net.Sockets;
using System.Security.Authentication;
Expand All @@ -14,6 +13,15 @@ namespace SecSess.Tcp
/// </summary>
public class Client : IStream
{
/// <summary>
/// The symmetric key used to communicate with this server
/// </summary>
public byte[] SymmetricKey { get; private set; }
/// <summary>
/// The HMAC key used to communicate with this server
/// </summary>
public byte[] HMacKey { get; private set; }

/// <summary>
/// A TCP client that actually works
/// </summary>
Expand All @@ -27,14 +35,6 @@ public class Client : IStream
/// </summary>
private Symmetric _symmetric { get; set; }
/// <summary>
/// The symmetric key used to communicate with this server
/// </summary>
private byte[] _symmetricKey;
/// <summary>
/// The HMAC key used to communicate with this server
/// </summary>
private byte[] _hmacKey;
/// <summary>
/// Algorithm set to use
/// </summary>
private Secure.Algorithm.Set _set;
Expand All @@ -46,15 +46,15 @@ public class Client : IStream
/// <param name="set">Algorithm set to use</param>
private Client(AsymmetricKeyBase? parameter, Secure.Algorithm.Set set)
{
_symmetricKey = new byte[Symmetric.KeySize(set.Symmetric)];
_hmacKey = new byte[Hash.HMacKeySize(set.Hash)];
SymmetricKey = new byte[Symmetric.KeySize(set.Symmetric)];
HMacKey = new byte[Hash.HMacKeySize(set.Hash)];

RandomNumberGenerator.Fill(_symmetricKey);
RandomNumberGenerator.Fill(_hmacKey);
RandomNumberGenerator.Fill(SymmetricKey);
RandomNumberGenerator.Fill(HMacKey);

_client = new TcpClient();
_asymmetric = new Asymmetric(parameter, set.Asymmetric);
_symmetric = new Symmetric(_symmetricKey, set.Symmetric);
_symmetric = new Symmetric(SymmetricKey, set.Symmetric);
_set = set;
}

Expand Down Expand Up @@ -101,18 +101,18 @@ public void Connect(IPEndPoint serverEP, int retry = 0)

if (_asymmetric.AsymmetricAlgorithm != null && _symmetric.Algorithm != Secure.Algorithm.Symmetric.None)
{
byte[] buffer = new byte[_symmetricKey.Length + _hmacKey.Length];
byte[] buffer = new byte[SymmetricKey.Length + HMacKey.Length];

Buffer.BlockCopy(_symmetricKey, 0, buffer, 0, _symmetricKey.Length);
Buffer.BlockCopy(_hmacKey, 0, buffer, _symmetricKey.Length, _hmacKey.Length);
Buffer.BlockCopy(SymmetricKey, 0, buffer, 0, SymmetricKey.Length);
Buffer.BlockCopy(HMacKey, 0, buffer, SymmetricKey.Length, HMacKey.Length);

byte[] enc = _asymmetric.Encrypt(buffer);
_client.GetStream().Write(enc, 0, enc.Length);

byte[] response = Read();
byte[] compare = Hash.HashData(_set.Hash, buffer);

_symmetric = new Symmetric(_symmetricKey, _set.Symmetric);
_symmetric = new Symmetric(SymmetricKey, _set.Symmetric);

if (compare.SequenceEqual(response) == false)
{
Expand Down Expand Up @@ -144,7 +144,7 @@ public void Close()
/// <param name="data">Data that write to server</param>
public void Write(byte[] data)
{
IStream.InternalWrite(data, _symmetric, _hmacKey, _set.Hash, _client);
IStream.InternalWrite(data, _symmetric, HMacKey, _set.Hash, _client);
}

/// <summary>
Expand All @@ -153,7 +153,7 @@ public void Write(byte[] data)
/// <returns>Data that read from server</returns>
public byte[] Read()
{
return IStream.InternalRead(_symmetric, _hmacKey, _set.Hash, _client);
return IStream.InternalRead(_symmetric, HMacKey, _set.Hash, _client);
}

/// <summary>
Expand Down
17 changes: 8 additions & 9 deletions SecSess/Tcp/Server.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using SecSess.Interface;
using SecSess.Interface.Tcp;
using SecSess.Key;
using SecSess.Secure.Wrapper;
using SecSess.Util;
using System.Net;
using System.Net.Sockets;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace SecSess.Tcp
{
Expand All @@ -18,18 +16,19 @@ public class Server
/// </summary>
public class Client : IStream
{
/// <summary>
/// Client that actually works
/// </summary>
internal TcpClient InnerClient { get; set; }
/// <summary>
/// The symmetric key used to communicate with this client
/// </summary>
internal byte[] SymmetricKey { get; set; }
public byte[] SymmetricKey { get; private set; }
/// <summary>
/// The HMAC key used to communicate with this client
/// </summary>
internal byte[] HMacKey { get; set; }
public byte[] HMacKey { get; private set; }

/// <summary>
/// Client that actually works
/// </summary>
internal TcpClient InnerClient { get; set; }
/// <summary>
/// Symmetric algorithm supporter
/// </summary>
Expand Down
Loading

0 comments on commit 09de9a6

Please sign in to comment.