added ClientServerLib Project (not tested)
This commit is contained in:
1 parent
036cc3b4bd
commit
a1084d2bea
11 files changed
+3884
No files matched your search
@@ -39,3 +39,5 @@ Output/Songs
|
||||
*.Cache
|
||||
/GstreamerHelper/bin/*
|
||||
/VocaluxeLib/bin
|
||||
/ClientServerLib\ClientServerLib/ClientServerLib.csproj.user
|
||||
/ClientServerLib\ClientServerLib\bin\Debug/ClientServerLib.dll
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C# Express 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientServerLib", "ClientServerLib\ClientServerLib.csproj", "{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,257 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public class CClient
|
||||
{
|
||||
private bool doConnect;
|
||||
private bool connected;
|
||||
private bool running;
|
||||
private int bufferLength = 8192;
|
||||
|
||||
private Thread clientThread;
|
||||
private IPEndPoint serverEndPoint;
|
||||
private string ip;
|
||||
private int port;
|
||||
|
||||
private CConnection connection;
|
||||
private List<SRequest> requests;
|
||||
private List<SRequest> responses;
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return connected; }
|
||||
}
|
||||
|
||||
public bool LoggedIn
|
||||
{
|
||||
get { return connection.LoggedIn; }
|
||||
set { connection.LoggedIn = value; }
|
||||
}
|
||||
|
||||
public CClient()
|
||||
{
|
||||
doConnect = false;
|
||||
connected = false;
|
||||
running = true;
|
||||
requests = new List<SRequest>();
|
||||
responses = new List<SRequest>();
|
||||
|
||||
connection = new CConnection(new TcpClient(), -1);
|
||||
|
||||
clientThread = new Thread(new ThreadStart(Runner));
|
||||
clientThread.Start();
|
||||
}
|
||||
|
||||
public void Connect(string IP = "127.0.0.1", int Port = 3000)
|
||||
{
|
||||
if (!doConnect)
|
||||
{
|
||||
ip = IP;
|
||||
port = Port;
|
||||
doConnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
if (doConnect)
|
||||
{
|
||||
doConnect = false;
|
||||
|
||||
lock (requests)
|
||||
{
|
||||
requests.Clear();
|
||||
}
|
||||
|
||||
lock (responses)
|
||||
{
|
||||
responses.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Disconnect();
|
||||
running = false;
|
||||
clientThread.Join(100);
|
||||
}
|
||||
|
||||
public void SendMessage(byte[] Message, ResponseCallback Callback)
|
||||
{
|
||||
SRequest req = new SRequest();
|
||||
req.Command = Message;
|
||||
req.Callback = Callback;
|
||||
req.Response = null;
|
||||
|
||||
lock (requests)
|
||||
{
|
||||
requests.Add(req);
|
||||
}
|
||||
}
|
||||
|
||||
private void Runner()
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
if (!connected && doConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||
connection.TcpClient.Connect(serverEndPoint);
|
||||
connected = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
connected = false;
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
if (doConnect)
|
||||
Thread.Sleep(10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (connected && !doConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.TcpClient.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
connected = false;
|
||||
}
|
||||
|
||||
if (doConnect && connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
Communicate();
|
||||
}
|
||||
catch
|
||||
{
|
||||
connected = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Communicate()
|
||||
{
|
||||
NetworkStream clientStream = connection.TcpClient.GetStream();
|
||||
|
||||
byte[] data = new byte[bufferLength];
|
||||
int bytesRead;
|
||||
|
||||
if (!connection.KeySet)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
return;
|
||||
|
||||
byte[] serverParam = new byte[bytesRead];
|
||||
Array.Copy(data, serverParam, bytesRead);
|
||||
byte[] clientResponse = connection.CreateClientKey(serverParam);
|
||||
clientStream.Write(clientResponse, 0, clientResponse.Length);
|
||||
clientStream.Flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (requests)
|
||||
{
|
||||
while (requests.Count > 0)
|
||||
{
|
||||
SRequest res = HandleRequest(requests[0]);
|
||||
responses.Add(res);
|
||||
requests.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
lock (responses)
|
||||
{
|
||||
while (responses.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
responses[0].Callback(responses[0].Response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
responses.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private SRequest HandleRequest(SRequest request)
|
||||
{
|
||||
SRequest response = new SRequest();
|
||||
response.Command = request.Command;
|
||||
response.Callback = request.Callback;
|
||||
response.Response = null;
|
||||
|
||||
NetworkStream clientStream = connection.TcpClient.GetStream();
|
||||
|
||||
byte[] encrypted = connection.Encrypt(request.Command);
|
||||
|
||||
clientStream.Write(encrypted, 0, encrypted.Length);
|
||||
clientStream.Flush();
|
||||
|
||||
byte[] data = new byte[bufferLength];
|
||||
int bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
return response;
|
||||
|
||||
int messageLength = BitConverter.ToInt32(data, 0);
|
||||
while (messageLength > bytesRead)
|
||||
{
|
||||
Array.Resize<byte>(ref data, data.Length + bufferLength);
|
||||
bytesRead += clientStream.Read(data, data.Length - bufferLength, bufferLength);
|
||||
}
|
||||
|
||||
encrypted = new byte[bytesRead];
|
||||
Array.Copy(data, encrypted, bytesRead);
|
||||
response.Response = connection.Decrypt(encrypted);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using DiffieHellman;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
internal class CConnection
|
||||
{
|
||||
private bool keySet;
|
||||
private CDiffieHellman dh;
|
||||
private UTF8Encoding encoder;
|
||||
private int connectionID;
|
||||
|
||||
public TcpClient TcpClient;
|
||||
public bool LoggedIn;
|
||||
|
||||
public bool KeySet
|
||||
{
|
||||
get { return keySet; }
|
||||
}
|
||||
|
||||
public int ConnectionID
|
||||
{
|
||||
get { return connectionID; }
|
||||
}
|
||||
|
||||
public CConnection(TcpClient client, int ConnectionID)
|
||||
{
|
||||
TcpClient = client;
|
||||
keySet = false;
|
||||
LoggedIn = false;
|
||||
connectionID = ConnectionID;
|
||||
encoder = new UTF8Encoding();
|
||||
}
|
||||
|
||||
public byte[] GetKeyParams()
|
||||
{
|
||||
if (dh == null)
|
||||
dh = new CDiffieHellman(256).GenerateRequest();
|
||||
|
||||
return encoder.GetBytes(dh.ToString());
|
||||
}
|
||||
|
||||
public byte[] CreateClientKey(byte[] serverParam)
|
||||
{
|
||||
if (serverParam == null)
|
||||
return null;
|
||||
|
||||
dh = new CDiffieHellman(256).GenerateResponse(
|
||||
encoder.GetString(serverParam, 0, serverParam.Length));
|
||||
|
||||
keySet = true;
|
||||
return encoder.GetBytes(dh.ToString());
|
||||
}
|
||||
|
||||
public void CreateServerKey(byte[] clientResponse)
|
||||
{
|
||||
if (dh == null)
|
||||
return;
|
||||
|
||||
dh.HandleResponse(encoder.GetString(clientResponse, 0, clientResponse.Length));
|
||||
keySet = true;
|
||||
}
|
||||
|
||||
public byte[] Encrypt(byte[] Data)
|
||||
{
|
||||
if (Data == null || !keySet)
|
||||
return Data;
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = dh.Key;
|
||||
aes.GenerateIV();
|
||||
|
||||
byte[] dataLength = BitConverter.GetBytes(Data.Length);
|
||||
|
||||
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(Data, 0, Data.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
|
||||
byte[] encrypted = memoryStream.ToArray();
|
||||
|
||||
int len = 4 + aes.IV.Length + dataLength.Length + encrypted.Length;
|
||||
byte[] messageLength = BitConverter.GetBytes(len);
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
stream.Write(messageLength, 0, messageLength.Length);
|
||||
stream.Write(aes.IV, 0, aes.IV.Length);
|
||||
stream.Write(dataLength, 0, dataLength.Length);
|
||||
stream.Write(encrypted, 0, encrypted.Length);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Decrypt(byte[] Data)
|
||||
{
|
||||
if (Data == null || !keySet)
|
||||
return Data;
|
||||
|
||||
if (Data.Length < 25)
|
||||
return null;
|
||||
|
||||
int messageLength = BitConverter.ToInt32(Data, 0);
|
||||
if (messageLength > Data.Length)
|
||||
return null;
|
||||
|
||||
byte[] IV = new byte[16];
|
||||
Array.Copy(Data, 4, IV, 0, 16);
|
||||
int dataLength = BitConverter.ToInt32(Data, 20);
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = dh.Key;
|
||||
aes.IV = IV;
|
||||
|
||||
byte[] encrypted = new byte[messageLength - 24];
|
||||
Array.Copy(Data, 24, encrypted, 0, encrypted.Length);
|
||||
|
||||
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(encrypted, 0, encrypted.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
cryptoStream.Close();
|
||||
byte[] decrypted = memoryStream.ToArray();
|
||||
byte[] message = new byte[dataLength];
|
||||
Array.Copy(decrypted, message, dataLength);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public class CServer
|
||||
{
|
||||
private TcpListener tcpListener;
|
||||
private Thread listenThread;
|
||||
private int port;
|
||||
private int bufferLength = 8192;
|
||||
private bool running;
|
||||
|
||||
private HandleRequest requestCallback;
|
||||
|
||||
private Dictionary<int, CConnection> clients;
|
||||
private Queue<int> ids;
|
||||
|
||||
public CServer(HandleRequest RequestCallback, int Port = 3000)
|
||||
{
|
||||
port = Port;
|
||||
running = false;
|
||||
requestCallback = RequestCallback;
|
||||
|
||||
clients = new Dictionary<int, CConnection>();
|
||||
ids = new Queue<int>(1000);
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
ids.Enqueue(i);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!running)
|
||||
{
|
||||
running = true;
|
||||
|
||||
tcpListener = new TcpListener(IPAddress.Any, port);
|
||||
|
||||
listenThread = new Thread(new ThreadStart(ListenForClients));
|
||||
listenThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
running = false;
|
||||
tcpListener.Stop();
|
||||
Thread.Sleep(100);
|
||||
listenThread.Join();
|
||||
|
||||
lock (clients)
|
||||
{
|
||||
int[] cIDs = new int[clients.Count];
|
||||
clients.Keys.CopyTo(cIDs, 0);
|
||||
|
||||
foreach (int id in cIDs)
|
||||
{
|
||||
clients.Remove(id);
|
||||
ids.Enqueue(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenForClients()
|
||||
{
|
||||
tcpListener.Start();
|
||||
|
||||
while (running)
|
||||
{
|
||||
//wait for new client
|
||||
TcpClient client = tcpListener.AcceptTcpClient();
|
||||
|
||||
int id = ids.Dequeue();
|
||||
CConnection connection = new CConnection(client, id);
|
||||
|
||||
lock (clients)
|
||||
{
|
||||
clients.Add(id, connection);
|
||||
}
|
||||
|
||||
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCom));
|
||||
|
||||
NetworkStream clientStream = client.GetStream();
|
||||
byte[] serverParams = connection.GetKeyParams();
|
||||
clientStream.Write(serverParams, 0, serverParams.Length);
|
||||
clientStream.Flush();
|
||||
|
||||
clientThread.Start(connection);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleClientCom(object client)
|
||||
{
|
||||
CConnection connection = (CConnection)client;
|
||||
TcpClient tcpClient = (TcpClient)connection.TcpClient;
|
||||
NetworkStream clientStream = tcpClient.GetStream();
|
||||
|
||||
byte[] data = new byte[bufferLength];
|
||||
int bytesRead;
|
||||
|
||||
while (running)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
|
||||
if (!connection.KeySet)
|
||||
{
|
||||
byte[] clientResponse = new byte[bytesRead];
|
||||
Array.Copy(data, clientResponse, bytesRead);
|
||||
connection.CreateServerKey(clientResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
//receive message
|
||||
int messageLength = BitConverter.ToInt32(data, 0);
|
||||
while (messageLength > bytesRead)
|
||||
{
|
||||
Array.Resize<byte>(ref data, data.Length + bufferLength);
|
||||
bytesRead += clientStream.Read(data, data.Length - bufferLength, bufferLength);
|
||||
}
|
||||
|
||||
byte[] message = new byte[bytesRead];
|
||||
Array.Copy(data, message, bytesRead);
|
||||
byte[] decrypted = connection.Decrypt(message);
|
||||
|
||||
byte[] answer = HandleClientMessage(decrypted, connection);
|
||||
|
||||
//send message
|
||||
byte[] encrypted = connection.Encrypt(answer);
|
||||
|
||||
clientStream.Write(encrypted, 0, encrypted.Length);
|
||||
clientStream.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] HandleClientMessage(byte[] Message, CConnection connection)
|
||||
{
|
||||
return requestCallback(connection.ConnectionID, Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ClientServerLib</RootNamespace>
|
||||
<AssemblyName>ClientServerLib</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CClient.cs" />
|
||||
<Compile Include="CConnection.cs" />
|
||||
<Compile Include="CServer.cs" />
|
||||
<Compile Include="DeffieHellman\BigInt.cs" />
|
||||
<Compile Include="DeffieHellman\DeffieHellman.cs" />
|
||||
<Compile Include="DeffieHellman\StrongNumberProvider.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Structs.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DiffieHellman
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Diffie-Hellman algorithm.
|
||||
/// </summary>
|
||||
public class CDiffieHellman : IDisposable
|
||||
{
|
||||
#region - Util -
|
||||
static StrongNumberProvider _strongRng = new StrongNumberProvider();
|
||||
#endregion
|
||||
|
||||
#region - Fields -
|
||||
/// <summary>
|
||||
/// The number of bits to generate.
|
||||
/// </summary>
|
||||
private int bits = 256;
|
||||
|
||||
/// <summary>
|
||||
/// The shared prime.
|
||||
/// </summary>
|
||||
BigInteger prime;
|
||||
/// <summary>
|
||||
/// The shared base.
|
||||
/// </summary>
|
||||
BigInteger g;
|
||||
/// <summary>
|
||||
/// The private prime.
|
||||
/// </summary>
|
||||
BigInteger mine;
|
||||
|
||||
/// <summary>
|
||||
/// The final key.
|
||||
/// </summary>
|
||||
byte[] key;
|
||||
/// <summary>
|
||||
/// The string representation/packet.
|
||||
/// </summary>
|
||||
string representation;
|
||||
#endregion
|
||||
|
||||
#region - Properties -
|
||||
/// <summary>
|
||||
/// Gets the final key to use for encryption.
|
||||
/// </summary>
|
||||
public byte[] Key
|
||||
{
|
||||
get { return key; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region - Ctor -
|
||||
public CDiffieHellman()
|
||||
{
|
||||
}
|
||||
|
||||
public CDiffieHellman(int bits)
|
||||
{
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
~CDiffieHellman()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region - Implementation Methods -
|
||||
#region Flow
|
||||
/// <summary>
|
||||
/// Generates a request packet.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public CDiffieHellman GenerateRequest()
|
||||
{
|
||||
// Generate the parameters.
|
||||
prime = BigInteger.GenPseudoPrime(bits, 30, _strongRng);
|
||||
mine = BigInteger.GenPseudoPrime(bits, 30, _strongRng);
|
||||
g = (BigInteger)5;
|
||||
|
||||
// Gemerate the string.
|
||||
StringBuilder rep = new StringBuilder();
|
||||
rep.Append(prime.ToString(36));
|
||||
rep.Append("|");
|
||||
rep.Append(g.ToString(36));
|
||||
rep.Append("|");
|
||||
|
||||
// Generate the send BigInt.
|
||||
using (BigInteger send = g.ModPow(mine, prime))
|
||||
{
|
||||
rep.Append(send.ToString(36));
|
||||
}
|
||||
|
||||
representation = rep.ToString();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a response packet.
|
||||
/// </summary>
|
||||
/// <param name="request">The string representation of the request.</param>
|
||||
/// <returns></returns>
|
||||
public CDiffieHellman GenerateResponse(string request)
|
||||
{
|
||||
string[] parts = request.Split('|');
|
||||
|
||||
// Generate the would-be fields.
|
||||
using (BigInteger prime = new BigInteger(parts[0], 36))
|
||||
using (BigInteger g = new BigInteger(parts[1], 36))
|
||||
using (BigInteger mine = BigInteger.GenPseudoPrime(bits, 30, _strongRng))
|
||||
{
|
||||
// Generate the key.
|
||||
using (BigInteger given = new BigInteger(parts[2], 36))
|
||||
using (BigInteger key = given.ModPow(mine, prime))
|
||||
{
|
||||
this.key = key.GetBytes();
|
||||
}
|
||||
// Generate the response.
|
||||
using (BigInteger send = g.ModPow(mine, prime))
|
||||
{
|
||||
this.representation = send.ToString(36);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the key after a response is received.
|
||||
/// </summary>
|
||||
/// <param name="response">The string representation of the response.</param>
|
||||
public void HandleResponse(string response)
|
||||
{
|
||||
// Get the response and modpow it with the stored prime.
|
||||
using (BigInteger given = new BigInteger(response, 36))
|
||||
using (BigInteger key = given.ModPow(mine, prime))
|
||||
{
|
||||
this.key = key.GetBytes();
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return representation;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
/// <summary>
|
||||
/// Ends the calculation. The key will still be available.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Object.ReferenceEquals(prime, null))
|
||||
prime.Dispose();
|
||||
if (!Object.ReferenceEquals(mine, null))
|
||||
mine.Dispose();
|
||||
if (!Object.ReferenceEquals(g, null))
|
||||
g.Dispose();
|
||||
|
||||
prime = null;
|
||||
mine = null;
|
||||
g = null;
|
||||
|
||||
representation = null;
|
||||
GC.Collect();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DiffieHellman
|
||||
{
|
||||
internal class StrongNumberProvider
|
||||
{
|
||||
private static RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider();
|
||||
|
||||
public uint NextUInt32()
|
||||
{
|
||||
byte[] res = new byte[4];
|
||||
csp.GetBytes(res);
|
||||
return BitConverter.ToUInt32(res, 0);
|
||||
}
|
||||
|
||||
public int NextInt()
|
||||
{
|
||||
byte[] res = new byte[4];
|
||||
csp.GetBytes(res);
|
||||
return BitConverter.ToInt32(res, 0);
|
||||
}
|
||||
|
||||
public Single NextSingle()
|
||||
{
|
||||
float numerator = NextUInt32();
|
||||
float denominator = uint.MaxValue;
|
||||
return numerator / denominator;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die mit einer Assembly verknüpft sind.
|
||||
[assembly: AssemblyTitle("ClientServerLib")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ClientServerLib")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("53f89645-1948-420f-b64a-7dc705ca8820")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public delegate void ResponseCallback(byte[] Response);
|
||||
public delegate byte[] HandleRequest(int ConnectionID, byte[] Message);
|
||||
|
||||
public struct SRequest
|
||||
{
|
||||
public byte[] Command;
|
||||
public byte[] Response;
|
||||
public ResponseCallback Callback;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user