Using X509Certificate for TLS degrading performance considerably - c#

I'm using C# .NET to upload numerous, large, files from client to server using SslStream.
It's twice as slow as un-encrypted upload. How much delay is normal?
Any suggestions on how to improve the performance of encryption framework? Would lowering the encryption strength of pfx/pvk help? If so how to do it? All tips are welcome.
Edit:
In each client session 1 or multiple files are uploaded. In my test there were 1250. Client uses same SslStream for a session...
Server code:
private void OnAcceptTcpClient(IAsyncResult result)
{
var client = _listener.EndAcceptTcpClient(result);
Stream stream = client.GetStream();
if (_cert != null)
{
var ssl = new SslStream(stream, false);
ssl.AuthenticateAsServer(_cert, false, SslProtocols.Tls, false);
stream = ssl;
}
// Processing block
...
}
Client Code:
public IAsyncResult BeginSend(string host, int port, bool bTls, AsyncCallback callback, object state)
{
_client = new TcpClient(host, port) { NoDelay = NoDelay };
Stream stream = _client.GetStream();
if (bTls)
{
var ssl = new SslStream(stream, false, new RemoteCertificateValidationCallback((o, c, ch, er) => true));
ssl.AuthenticateAsClient(host);
stream = ssl;
}
// Send all files
return BeginSend(stream, callback, state);
}
Thank you very much.

Are you using the X509 Certificate to cryptography all files sent to server? I think one solution could be using the X509 Certificate just in the beginning in order to exchange a random generated symmetric cryptography key and then use it to cryptography the files to be sent. Just like https does.
Another tip is to see if the cryptographed data is getting too much bigger.

Related

How to Capture Websocket in Realtime with Wireshark or custom decode functions

I'm able to log all windows traffic by Wireshark and Chrome Inspector thru Network->WS.
Unfortunately I'm writing a web bot to interact with some websites automatically. I really need to go thru the data in websocket, not by HTML and some other methods that I have used before.
Chrome (and most probably Firefox) cannot save data in realtime. Chrome can save .har file with all the traffic, but even if I automate that, the file grows with every new packet, so it will result in performance issue very soon.
Wireshark can do that and even decrypt TLS (https) in realtime. It also supports saving file on every x packets or x seconds. But for some (maybe security) reason it saves encrypted pcap file. I don't know how to decrypt it.
On other hand I'm able to capture traffic with PcapDotNet. I'm also able to log IPs, ports and sequence and rebuild whole TLS frame from 2-3 separate TCP packets.
Till the moment in C# I tried logging the packets and try some decryption without any success:
int index = -1;
foreach (IpV4Datagram IPpack in IPPackets)
{
index += 1;
string src = IPpack.Source.ToString();
string dest = IPpack.Destination.ToString();
string destPort = IPpack.Tcp.DestinationPort.ToString();
string controlBits = IPpack.Tcp.ControlBits.ToString();
int p1 = 0;
if ((controlBits == "Acknowledgment")|(controlBits == "Push, Acknowledgment"))
{
//Add
p1 = TCPCPackets.FindIndex(x => (x.SourceIP == src) & (x.DestinationIP == dest) & (x.DestinationPort == destPort));
if (p1 < 0)
{
TCPCombinedPacket newCP = new TCPCombinedPacket();
newCP.SourceIP = src;
newCP.DestinationIP = dest;
newCP.DestinationPort = destPort;
TCPCPackets.Add(newCP);
p1 = TCPCPackets.Count() - 1;
}
TCPCPackets[p1].Counter += 1;
int totcount = packets[index].Count();
int start = totcount - IPpack.Tcp.PayloadLength;
if (start < totcount)
{
for (int o = start; o < totcount; o++)
{
TCPCPackets[p1].bytedata.Add(packets[index][o]);
}
}
}
if (controlBits == "Push, Acknowledgment")
{
//Finish
TCPWPackets.Add(TCPCPackets[p1]);
TCPCPackets.RemoveAt(p1);
}
}
But I'm not able to find any single TLS decryption function. I tried with the integrated .net decryptor but with no success:
public string DecryptString(byte[] key, byte[] buffer)
{
byte[] iv = new byte[16];
//byte[] buffer = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
aes.Key = key;//Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
It seems TLS uses many types of encryptions and it's generally not exposed to C#, much more likely to driver level. I'm not able to find any TLS decryption code anywhere.
I have many CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET in the ssl.log file from the web browser as I already set SSLKEYLOGFILE environment variable.
My idea was to try with some decrypt function until I find working key and store the key per IP and port. Sorting this "try" list of keys by success rate, while outdated will go last. But obviously with packets in my variable but no TLS decryption function I can do nothing...
The last thing I tried is to run inspector over inspector and run the following Java scrypt. But it seems it's no longer supported. Also I found 1-2 third party extensions to capture WinSocket traffic for Chrome that are no longer available (and I even cannot find them, only history pages). Here is the JS code which I tried on older version chrome with no success (which returns errors, and actually I don't see the used sub-objects - maybe no longer supported):
// https://bgrins.github.io/devtools-snippets/#console-save
(function(console){
console.save = function(data, filename){
if(!data) {
console.error('Console.save: No data')
return;
}
if(!filename) filename = 'console.json'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
// Frame/Socket message counter + filename
var iter = 0;
// This replaces the browser's `webSocketFrameReceived` code with the original code
// and adds two lines, one to save the socket message and one to increment the counter.
SDK.NetworkDispatcher.prototype.webSocketFrameReceived = function (requestId, time, response) {
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest) return;
console.save(JSON.parse(response.payloadData), iter + ".json")
iter++;
networkRequest.addFrame(response, time, false);
networkRequest.responseReceivedTime = time;
this._updateNetworkRequest(networkRequest);
}
The link is this one: How to save websocket frames in Chrome
Any idea how I can capture TLS encrypted WebSocket traffic in realtime with max delay of 1 second?

Able to write in sslstream but unable to read

I am trying to write/read to sslstream on 443 port.
I can able write data to that sslstream but while reading from that sslstream,​ it is waiting to read, forever.
Sample code:
var add= "IPGoesHere";
var port = 443;
var remoteIpAdd= IPaddress.
Parse("IPGoesHere");
var socket = new Socket(remoteIpAdd.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(remoteIpAdd,port));
var netstream = new NetworkStream(
socket);
var sslstream = new SslStream(
netstream, false, callback1,
callback2);
sslstream.AuthenticateAsClient
(add,null, SslProtocols.Tls12, false);
var bytes = Encoding.Ascii.GetBytes("something");
sslstream.write( bytes,0,bytes.Length);
sslstream.Flush();
sslstream.Read(new byte[9],0,9); //Here it is waiting indefinitely..
Callback1 is a RemoteCertificateValidationCallback method and I am returning true here.
Callback2 is a Local certificate selection callback method and returning null here.
I am thinking like, how it can not able to read when it can able to write.
Could someone share some input on this issue.
PS: I typed entire code in mobile app. Regret for alignment.

c# tcpclient program writing to stream but client not receiving data

I have written a TCPClient program to run on my PC. It first initiates a TCP listener to listen on a specific port then reads/writes from/to multiple TCP clients on multiple threads.
I am able to read from the client but whenever I try to send data to it, the program displays that it has sent the data, but the client does not receive anything.
Here's the code:
TcpClient client = listener.AcceptTcpClient();
var childSocketThread = new Thread(() =>
{
if (client.Connected)
{
using (NetworkStream stream = client.GetStream())
{
Console.WriteLine("connected");
byte[] data = new byte[1000];
try
{
if (stream.CanRead)
{
stream.Read(data, 0, 1000);
string dataStr = Encoding.ASCII.GetString(data);
string dataa = dataStr.TrimEnd('\0');
//Console.WriteLine(dataa);
if (dataa.Length > 10)
{
deviceid = ParseRequest(dataa);
byte[] sendnow = Encoding.ASCII.GetBytes(reply[deviceid]);
Array.Clear(data, 0, 1000);
Console.WriteLine("Recieved data: " + dataa);
Console.WriteLine("Sending data");
using (StreamWriter writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
writer.WriteLine(reply[deviceid]);
}
Console.WriteLine(reply[deviceid]);
Console.WriteLine("Sent");
}
Console.WriteLine();
}
}
catch (Exception es)
{
Console.WriteLine(es);
}
}
}
});
childSocketThread.Start();
The server device that I am using is a PLC. Also, things I have already tried:
1) sending directly using Socket.Send method.
2) sending directly using NetworkStream method.
3) accepting the TCP connection as sockets. (Socket device = listener.AcceptSocket).
None of these methods seem to send to the device, even though the program tells me that it had no issues sending data since it displays "Sent" after attempting to send data.
I downloaded another program from this link http://www.codeproject.com/Articles/488668/Csharp-TCP-Server. The test app they provide with it is able to send and receive data on the same port as my program running on the same PC.
I haven't been able to get any direction on how to diagnose and more importantly solve this issue. Any ideas?
Update 2015-08-10 11:18 a.m.:
Output of the Program is as follows:
Update 2015-08-10 11:32 a.m.:
Output of Syslog Console:
Update 2015-08-10 12:07 p.m.:
Output of Wireshark:
We need you to post both sides code. Nevertheless, here is some code that works just fine, you can use it to see if you are doing something wrong.
http://www.codeproject.com/Articles/1415/Introduction-to-TCP-client-server-in-C

.Net isn't deserializing stream when sent from Websockets

I'm making an application in PhoneGap, and I'm using HTML5 Websockets to send some info to another device (read: sending data to another user who has the app). Users are registered with ID and Username.
For this, I read that I have to make an TCP/Socket connection. I've tried to use an old socket-chat I once made in school with C#.
I'm connecting to the socket this way from the app:
var ws = new WebSocket("ws://127.0.0.1:7001");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
ws.send("message");
};
And the server side looks like this (of course isn't the entire code, but the relevant parts)
private NetworkStream stream;
private IFormatter formatter = new BinaryFormatter();
private TcpListener server;
public TcpClient client;
private string username { get; set; }
private void StartServer()
{
int port = Convert.ToInt32(portUser);
server = new TcpListener(IPAddress.Parse(IP), port);
server.Start();
client = server.AcceptTcpClient();
stream = client.GetStream();
username = formatter.Deserialize(stream).ToString();
}
The last deserialize-line writes:
The input stream is not a valid binary format. The starting contents (in bytes) are: 47-45-54-20-2F-20-48-54-54-50-2F-31-2E-31-0D-0A-48 ...
Any other way to deserialize the stream? Or am I using a completely wrong way?
Edit: working C# way I used to send data between clients in the chatter
stream = client.GetStream();
formatter.Serialize(stream, messageobj);
stream.Flush();

Asymmetric cryptography example in C#

I need to send confidential data to a server over a TCP connection. I have done a lot of researching and I understand the theoretical part. Based on what I have researched I want to do the following:
Note there is a server and a client: (we assume that public keys of either the client or server can be obtain by anyone)
client creates his public and private key. He is able to encrypt with his private key and decrypt with his public key.
server creates his public and private keys. private key is used to decrypt messages and public key is used to encrypt messages. (note is the other way around as with the client)
the client get's the server's public key. client then will be able to encrypt messages with that key and the only one that will be able to decrypt that message would be the server's private key.
since the server needs to be certain that the message comes from that specific client then the client will encrypt his name (signature) with his private key.
so the client message will contain: data to be send, client's public key, client name encrypted with the client's private key.
the client will encrypt the message with the public key from the server. client will then send that message to the server.
the server will decrypt the message it just received with his private key.
once the message is decrypted it will contain the data (info), encrypted signature, public key from client.
finally, the server will decrypt the client signature with the public key that was contained on the message to verify that the message is from that client.
OK so this is how asymmetric cryptography works. I have also researched about the classes that enable you to create this key pairs with the .NET framework. The classes that I researched that enable you do create this public and private key pairs are:
System.Security.Cryptography.DES
System.Security.Cryptography.DSACryptoServiceProvider
System.Security.Cryptography.ECDsa
System.Security.Cryptography.ECDsaCng
System.Security.Cryptography.ECDiffieHellman
System.Security.Cryptography.ECDiffieHellmanCng
System.Security.Cryptography.RSA
System.Security.Cryptography.RSACryptoServiceProvider
so now my problems comes on how do I use one of this classes to do it with C#? I understand how the theoretical part works but how do I do what I just described with code. I have researched for some examples but I am having a hard time understanding them.
here is one example that I found that I believe does what I described:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Example
{
class Program
{
static CngKey aliceKey;
static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main()
{
CreateKeys();
byte[] encrytpedData = AliceSendsData("secret message");
BobReceivesData(encrytpedData);
Console.Read();
}
private static void CreateKeys()
{
aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static byte[] AliceSendsData(string message)
{
Console.WriteLine("Alice sends message: {0}", message);
byte[] rawData = Encoding.UTF8.GetBytes(message);
byte[] encryptedData = null;
using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))
using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);
Console.WriteLine("Alice creates this symmetric key with " +
"Bobs public key information: {0}",
Convert.ToBase64String(symmKey));
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = symmKey;
aes.GenerateIV();
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
{
// create CryptoStream and encrypt data to send
var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
// write initialization vector not encrypted
ms.Write(aes.IV, 0, aes.IV.Length);
cs.Write(rawData, 0, rawData.Length);
cs.Close();
encryptedData = ms.ToArray();
}
aes.Clear();
}
}
Console.WriteLine("Alice: message is encrypted: {0}",
Convert.ToBase64String(encryptedData)); ;
Console.WriteLine();
return encryptedData;
}
private static void BobReceivesData(byte[] encryptedData)
{
Console.WriteLine("Bob receives encrypted data");
byte[] rawData = null;
var aes = new AesCryptoServiceProvider();
int nBytes = aes.BlockSize >> 3;
byte[] iv = new byte[nBytes];
for (int i = 0; i < iv.Length; i++)
iv[i] = encryptedData[i];
using (var bobAlgorithm = new ECDiffieHellmanCng(bobKey))
using (CngKey alicePubKey = CngKey.Import(alicePubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = bobAlgorithm.DeriveKeyMaterial(alicePubKey);
Console.WriteLine("Bob creates this symmetric key with " +
"Alices public key information: {0}",
Convert.ToBase64String(symmKey));
aes.Key = symmKey;
aes.IV = iv;
using (ICryptoTransform decryptor = aes.CreateDecryptor())
using (MemoryStream ms = new MemoryStream())
{
var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write);
cs.Write(encryptedData, nBytes, encryptedData.Length - nBytes);
cs.Close();
rawData = ms.ToArray();
Console.WriteLine("Bob decrypts message to: {0}",
Encoding.UTF8.GetString(rawData));
}
aes.Clear();
}
}
}
}
In this program I believe the client is Alice and the server is Bob. I have to split this program into two parts. I am having a hard time understanding it and if I give it a try most likely I will make it work. Anyways how can I split this program into a server side code and client side code. I know how to send bytes between server and client. But I don't want to make it work without understanding what is going on. maybe you guys can show me an easier example.
EDIT
I managed to separate the code: here is the server code (the ip address of my computer happened to be 192.168.0.120) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.IO;
namespace ServerListener
{
class Program
{
static TcpListener server;
//static CngKey aliceKey;
static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main(string[] args)
{
CreateKeys();
IPAddress ipAddress = IPAddress.Parse("192.168.0.120");
server = new TcpListener(ipAddress, 54540);
server.Start();
var client = server.AcceptTcpClient();
var stream = client.GetStream();
alicePubKeyBlob = new byte[bobPubKeyBlob.Length];
stream.Read(alicePubKeyBlob, 0, alicePubKeyBlob.Length);
stream.Write(bobPubKeyBlob, 0, bobPubKeyBlob.Length);
byte[] encrytpedData = new byte[32];
stream.Read(encrytpedData, 0, encrytpedData.Length);
BobReceivesData(encrytpedData);
}
private static void CreateKeys()
{
//aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
//alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static void BobReceivesData(byte[] encryptedData)
{
Console.WriteLine("Bob receives encrypted data");
byte[] rawData = null;
var aes = new AesCryptoServiceProvider();
int nBytes = aes.BlockSize >> 3;
byte[] iv = new byte[nBytes];
for (int i = 0; i < iv.Length; i++)
iv[i] = encryptedData[i];
using (var bobAlgorithm = new ECDiffieHellmanCng(bobKey))
using (CngKey alicePubKey = CngKey.Import(alicePubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = bobAlgorithm.DeriveKeyMaterial(alicePubKey);
Console.WriteLine("Bob creates this symmetric key with " +
"Alices public key information: {0}",
Convert.ToBase64String(symmKey));
aes.Key = symmKey;
aes.IV = iv;
using (ICryptoTransform decryptor = aes.CreateDecryptor())
using (MemoryStream ms = new MemoryStream())
{
var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write);
cs.Write(encryptedData, nBytes, encryptedData.Length - nBytes);
cs.Close();
rawData = ms.ToArray();
Console.WriteLine("Bob decrypts message to: {0}",
Encoding.UTF8.GetString(rawData));
}
aes.Clear();
}
}
}
}
and here is the client code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.IO;
namespace ClientAlice
{
class Program
{
static CngKey aliceKey;
//static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main(string[] args)
{
CreateKeys();
bobPubKeyBlob = new byte[alicePubKeyBlob.Length];
TcpClient alice = new TcpClient("192.168.0.120", 54540);
var stream = alice.GetStream();
stream.Write(alicePubKeyBlob, 0, alicePubKeyBlob.Length);
stream.Read(bobPubKeyBlob, 0, bobPubKeyBlob.Length);
byte[] encrytpedData = AliceSendsData(":)");
stream.Write(encrytpedData, 0, encrytpedData.Length);
}
private static void CreateKeys()
{
aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
//bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
//bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static byte[] AliceSendsData(string message)
{
Console.WriteLine("Alice sends message: {0}", message);
byte[] rawData = Encoding.UTF8.GetBytes(message);
byte[] encryptedData = null;
using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))
using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);
Console.WriteLine("Alice creates this symmetric key with " +
"Bobs public key information: {0}",
Convert.ToBase64String(symmKey));
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = symmKey;
aes.GenerateIV();
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
{
// create CryptoStream and encrypt data to send
var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
// write initialization vector not encrypted
ms.Write(aes.IV, 0, aes.IV.Length);
cs.Write(rawData, 0, rawData.Length);
cs.Close();
encryptedData = ms.ToArray();
}
aes.Clear();
}
}
Console.WriteLine("Alice: message is encrypted: {0}",
Convert.ToBase64String(encryptedData)); ;
Console.WriteLine();
return encryptedData;
}
}
}
I thinks it is pretty secure. Every time it sends a different byte array although sending the same info!
As you note, you are a beginner at crypto. If this is a fun toy project to learn about crypto, great. If this is real production code you are going to implement it insecurely. You should be using off-the-shelf tools like SSL/HTTPS/whatever to solve this problem rather than doing it wrong yourself.
I'll take this opportunity to point out areas where your sketch is fatally weak.
3) the client get's the server's public key.
OK. How? This is the most important step. The security of the entire system relies upon this step, and you have completely glossed over how it works. How does the client obtain the public key of the server? What stops an evil person from calling up the client and saying "hey client, I'm the server. Here's my public key!" And now the client is encrypting messages that can only be decrypted by the evildoer. The evildoer has the real server's public key, so the evildoer re-encrypts the message with the real public key and sends it on. Your whole system is thereby compromised. The public key cryptosystem is only secure if there is a secure key exchange mechanism. (And a reasonable question then is: if you have a secure key exchange mechanism, why not simply use it to exchange the message in the first place?)
4) since the server needs to be certain that the message comes from that specific client then the client will encrypt his name (signature) with his private key.
The client should encrypt a hash of the entire message as the signature, not just a part of the message. That way the server has evidence that the whole message was from the client.
6) the client will encrypt the message with the public key from the server. client will then send that message to the server.
This is extremely inefficient. Better is for the server and client to agree upon a key to a symmetric cryptosystem. The key can be transmitted between the server and the client using the public key cryptosystem. The server and client now have a shared secret key that they can use for this communication session.
9) lastly, the server will decrypt the client signature with the public key that was contained on the message to verify that the message is from that client.
How on earth does that help anything? I want to send you a message. You want to know who it comes from. So I send you a photocopy of my drivers license, so you can compare the signature on the license with the signature on the message. How do you know I sent you my drivers license and not a photocopy of someone else's? This doesn't solve the client authentication problem at all. Again, you need to solve the key distribution problem. The system depends on there being a secure key distribution infrastructure, which you have not specified.
Posting as an answer since it would be too long for a comment - it isn't specifically answering your question though.
As mentionned in the comment by driis, you should really rely on existing solutions which are regarded as being secure. That said, your protocol does have security issues:
Communication is usually two-way, you however only seem to address one-way communication (client to server). This doesn't make much sense, since you say that you're going to use TCP, which is a two-way protocol in itself.
Steps 4 and 5 are buggy: since you send the public key of the client inside the message, anyone could create a pair and encrypt the client identification using this pair. From your description the server has no forward knowledge of the client's keys, which makes this signature do nothing but ensure the integrity of the message - specifically is does not in any way make the client identification trustworthy.
For proper identification, you do have additional prerequisites; the server has to know the client's public key in advance or it has to be able to trust the client's claim to be himself by using a trusted 3rd party. This is what certificates and the certificate trust chains are about: if that client presents a certificate issued by the 3rd party X and the server trusts X, then he can assume that the client is who he pretends to be.
SSL basically supports two modes:
Either only the server identity is verified and any client can communicate with it; the client's identity is not verified, only that (after the connection has been negotiated) it always is the same client which communicates to the server. This is the typical usage for online shopping etc. - you (as the client) trust the server and create a trusted connection, but the server does not know who you are.
Two-way authentification can be done as well by using client certificates. The server has to know and trust either the client certificate directly or the issuer of the client certificate in order to negotiate the connection successfully. In this scenario, the server does indeed know who the client is, but the prerequisite as mentioned above has to be met.

Categories

Resources