111 lines
3.9 KiB
C#
111 lines
3.9 KiB
C#
|
using System.IO.Compression;
|
|||
|
using System.Net;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Numerics;
|
|||
|
using System.Security.Cryptography;
|
|||
|
using System.Text;
|
|||
|
|
|||
|
await Task.WhenAll(ServerTask(), ClientTask());
|
|||
|
await Task.Delay(-1);
|
|||
|
return;
|
|||
|
|
|||
|
static async Task ClientTask()
|
|||
|
{
|
|||
|
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|||
|
await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 1234));
|
|||
|
|
|||
|
using var aes = Aes.Create();
|
|||
|
aes.GenerateKey();
|
|||
|
aes.GenerateIV();
|
|||
|
|
|||
|
await using var stream = new NetworkStream(socket);
|
|||
|
|
|||
|
SendAesKey(stream, aes);
|
|||
|
|
|||
|
const string message = "Hello";
|
|||
|
Console.WriteLine($"Client sending message: {message}");
|
|||
|
SendEncryptedMessage(Encoding.UTF8.GetBytes(message), stream, aes);
|
|||
|
|
|||
|
await Task.Delay(-1);
|
|||
|
}
|
|||
|
|
|||
|
static async Task ServerTask()
|
|||
|
{
|
|||
|
using var listener = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|||
|
listener.Bind(new IPEndPoint(IPAddress.Any, 1234));
|
|||
|
listener.Listen(1);
|
|||
|
|
|||
|
using Socket client = await listener.AcceptAsync();
|
|||
|
await using var stream = new NetworkStream(client);
|
|||
|
using var aes = Aes.Create();
|
|||
|
|
|||
|
ReadAesKey(stream, aes);
|
|||
|
Console.WriteLine($"Server received message: {Encoding.UTF8.GetString(ReadEncryptedMessage(stream, aes))}");
|
|||
|
|
|||
|
await Task.Delay(-1);
|
|||
|
}
|
|||
|
|
|||
|
static void ReadAesKey(Stream stream, SymmetricAlgorithm aes)
|
|||
|
{
|
|||
|
using var reader = new BinaryReader(stream, Encoding.UTF8, true);
|
|||
|
aes.Key = reader.ReadBytes(IPAddress.NetworkToHostOrder(reader.ReadInt32()));
|
|||
|
aes.IV = reader.ReadBytes(IPAddress.NetworkToHostOrder(reader.ReadInt32()));
|
|||
|
}
|
|||
|
|
|||
|
static void SendAesKey(Stream stream, SymmetricAlgorithm aes)
|
|||
|
{
|
|||
|
using var writer = new BinaryWriter(stream, Encoding.UTF8, true);
|
|||
|
writer.Write(IPAddress.HostToNetworkOrder(aes.Key.Length));
|
|||
|
writer.Write(aes.Key);
|
|||
|
writer.Write(IPAddress.HostToNetworkOrder(aes.IV.Length));
|
|||
|
writer.Write(aes.IV);
|
|||
|
}
|
|||
|
|
|||
|
static byte[] ReadEncryptedMessage(Stream inputStream, SymmetricAlgorithm aes)
|
|||
|
{
|
|||
|
using var inputReader = new BinaryReader(inputStream, Encoding.UTF8, true);
|
|||
|
using ICryptoTransform cryptoTransform = aes.CreateDecryptor();
|
|||
|
|
|||
|
// read unencrypted length header
|
|||
|
using var buffer = new MemoryStream();
|
|||
|
int length = IPAddress.NetworkToHostOrder(inputReader.ReadInt32());
|
|||
|
Console.WriteLine($"Reading {length} bytes");
|
|||
|
buffer.Write(inputReader.ReadBytes(length));
|
|||
|
|
|||
|
// read encrypted data
|
|||
|
Console.WriteLine($"Read {buffer.Length} bytes");
|
|||
|
Console.WriteLine("Decrypting...");
|
|||
|
buffer.Position = 0;
|
|||
|
using var cryptoStream = new CryptoStream(buffer, cryptoTransform, CryptoStreamMode.Read);
|
|||
|
using var gzip = new GZipStream(cryptoStream, CompressionMode.Decompress);
|
|||
|
using var cryptoReader = new BinaryReader(gzip, Encoding.UTF8);
|
|||
|
length = IPAddress.NetworkToHostOrder(cryptoReader.ReadInt32());
|
|||
|
Console.WriteLine($"Need to read {length} bytes");
|
|||
|
return cryptoReader.ReadBytes(length);
|
|||
|
}
|
|||
|
|
|||
|
static void SendEncryptedMessage(byte[] message, Stream outputStream, SymmetricAlgorithm aes)
|
|||
|
{
|
|||
|
using var outputWriter = new BinaryWriter(outputStream, Encoding.UTF8, true);
|
|||
|
using ICryptoTransform cryptoTransform = aes.CreateEncryptor();
|
|||
|
|
|||
|
// encrypt data
|
|||
|
using var buffer = new MemoryStream();
|
|||
|
using var cryptoStream = new CryptoStream(buffer, cryptoTransform, CryptoStreamMode.Write);
|
|||
|
using var gzip = new GZipStream(cryptoStream, CompressionMode.Compress);
|
|||
|
using var cryptoWriter = new BinaryWriter(gzip, Encoding.UTF8);
|
|||
|
cryptoWriter.Write(IPAddress.HostToNetworkOrder(message.Length));
|
|||
|
cryptoWriter.Write(message);
|
|||
|
cryptoWriter.Flush();
|
|||
|
cryptoStream.FlushFinalBlock();
|
|||
|
|
|||
|
buffer.Position = 0;
|
|||
|
|
|||
|
// sent encrypted data with unencrypted length header
|
|||
|
Console.WriteLine($"Writing {buffer.Length} bytes");
|
|||
|
outputWriter.Write(IPAddress.HostToNetworkOrder((int)BitOperations.RoundUpToPowerOf2((uint)buffer.Length)));
|
|||
|
buffer.CopyTo(outputStream);
|
|||
|
outputStream.Flush();
|
|||
|
Console.WriteLine("Message sent");
|
|||
|
}
|