static void Main(string[] args) { byte[] msg; IPEndPoint listenEndPoint; TcpListener server = null; TcpClient client = null; NetworkStream netStream = null; ProtocolSI protocol = null; AesCryptoServiceProvider aes = null; SymmetricsSI symmetricsSI = null; RSACryptoServiceProvider rsaClient = null; RSACryptoServiceProvider rsaServer = null; try { Console.WriteLine("SERVER"); #region Defenitions // algortimos assimétricos rsaClient = new RSACryptoServiceProvider(); rsaServer = new RSACryptoServiceProvider(); // algoritmos simétrico a usar... aes = new AesCryptoServiceProvider(); symmetricsSI = new SymmetricsSI(aes); // Binding IP/port listenEndPoint = new IPEndPoint(IPAddress.Any, 13000); // Client/Server Protocol to SI protocol = new ProtocolSI(); #endregion Console.WriteLine(SEPARATOR); #region TCP Listner // Start TcpListener server = new TcpListener(listenEndPoint); server.Start(); // Waits for a client connection (bloqueant wait) Console.Write("waiting for a connection... "); client = server.AcceptTcpClient(); netStream = client.GetStream(); Console.WriteLine("ok"); #endregion Console.WriteLine(SEPARATOR); #region Exhange Public Keys // Receive client public key Console.Write("waiting for client public key..."); netStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); rsaClient.FromXmlString(protocol.GetStringFromData()); Console.WriteLine("ok"); // Send public key... Console.Write("Sending public key... "); msg = protocol.Make(ProtocolSICmdType.PUBLIC_KEY, rsaServer.ToXmlString(false)); netStream.Write(msg, 0, msg.Length); Console.WriteLine("ok"); #endregion Console.WriteLine(SEPARATOR); #region Exchange Secret Key // Receive key Console.Write("waiting for key..."); netStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); aes.Key = rsaServer.Decrypt(protocol.GetData(), true); Console.WriteLine("ok"); Console.WriteLine(" Received: {0} ", ProtocolSI.ToHexString(aes.Key)); // Answer with a ACK Console.Write("Sending a ACK... "); msg = protocol.Make(ProtocolSICmdType.ACK); netStream.Write(msg, 0, msg.Length); Console.WriteLine("ok"); // Receive iv Console.Write("waiting for iv..."); netStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); aes.IV = rsaServer.Decrypt(protocol.GetData(), true); Console.WriteLine("ok"); Console.WriteLine(" Received: {0} ", ProtocolSI.ToHexString(aes.IV)); // Answer with a ACK Console.Write("Sending a ACK... "); msg = protocol.Make(ProtocolSICmdType.ACK); netStream.Write(msg, 0, msg.Length); Console.WriteLine("ok"); #endregion Console.WriteLine(SEPARATOR); #region Exchange Data (Secure channel) // Receive the cipher Console.Write("waiting for data..."); netStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); byte[] encryptedData = protocol.GetData(); //byte[] data = symmetricsSI.Decrypt(encryptedData); Console.WriteLine("ok"); //Console.WriteLine(" Encrypted: {0}", ProtocolSI.ToHexString(encryptedData)); //Console.WriteLine(" Data: {0} = {1}", ProtocolSI.ToString(data), ProtocolSI.ToHexString(data)); // Answer with a ACK Console.Write("Sending a ACK... "); msg = protocol.Make(ProtocolSICmdType.ACK); netStream.Write(msg, 0, msg.Length); Console.WriteLine("ok"); #endregion Console.WriteLine(SEPARATOR); #region Verify Digital Signature Console.Write("waiting for digital signature..."); netStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); var signature = protocol.GetData(); //encryptedData[0] = 0; bool status = rsaClient.VerifyData(encryptedData, new SHA256CryptoServiceProvider(), signature); Console.WriteLine("OK"); Console.WriteLine("STATUS SIGNATURE = " + status); Console.Write("Sending (N)ACK..."); if (status) { msg = protocol.Make(ProtocolSICmdType.ACK); } else { msg = protocol.Make(ProtocolSICmdType.NACK); } netStream.Write(msg, 0, msg.Length); Console.WriteLine("OK"); if (status) { byte[] data = symmetricsSI.Decrypt(encryptedData); Console.WriteLine("ok"); Console.WriteLine(" Encrypted: {0}", ProtocolSI.ToHexString(encryptedData)); Console.WriteLine(" Data: {0} = {1}", ProtocolSI.ToString(data), ProtocolSI.ToHexString(data)); } #endregion } catch (Exception ex) { Console.WriteLine(SEPARATOR); Console.WriteLine("Exception: {0}", ex.ToString()); } finally { // Close connections if (netStream != null) { netStream.Dispose(); } if (client != null) { client.Close(); } if (server != null) { server.Stop(); } Console.WriteLine(SEPARATOR); Console.WriteLine("Connection with client was closed."); } Console.WriteLine(SEPARATOR); Console.Write("End: Press a key..."); Console.ReadKey(); }
ClientWithProtocolSI() { try { Console.Write("<-> Starting client... "); clientRsaProvider = new RSACryptoServiceProvider(); aes = new AesCryptoServiceProvider(); ssInstance = new SymmetricsSI(aes); Console.WriteLine("done"); Console.Write("==> Connecting to the server... "); tcpClient = new TcpClient(SERVER_HOSTNAME, SERVER_PORT); networkStream = tcpClient.GetStream(); Console.WriteLine("done"); protocol = new ProtocolSI(); // Exchanging RSA public keys Console.Write("--> Sending RSA client public key... "); messageBytes = protocol.Make(ProtocolSICmdType.PUBLIC_KEY, clientRsaProvider.ToXmlString(false)); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.Write("<-- Receiving RSA server public key... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); serverRsaProvider = new RSACryptoServiceProvider(); serverRsaProvider.FromXmlString(protocol.GetStringFromData()); Console.WriteLine("done"); // Sending AES secrets Console.Write("--> Sending AES key... "); messageBytes = protocol.Make(ProtocolSICmdType.SECRET_KEY, serverRsaProvider.Encrypt(aes.Key, true)); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.WriteLine("-- Sent: {0} .", ProtocolSI.ToHexString(aes.Key)); Console.Write("<-- Waiting for an ACK command... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); Console.WriteLine("done"); Console.Write("--> Sending AES IV... "); messageBytes = protocol.Make(ProtocolSICmdType.IV, serverRsaProvider.Encrypt(aes.IV, true)); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.WriteLine("-- Sent: {0} .", ProtocolSI.ToHexString(aes.IV)); Console.Write("<-- Waiting for an ACK command... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); Console.WriteLine("done"); Console.Write("--> Requesting account balance... "); byte[] clearData = BitConverter.GetBytes(CLIENT_ACCOUNT_ID); byte[] encryptedData = ssInstance.Encrypt(clearData); messageBytes = protocol.Make(ProtocolSICmdType.SYM_CIPHER_DATA, encryptedData); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.WriteLine("-- Account ID: {0} = {1} .", BitConverter.ToInt32(clearData, 0).ToString(), ProtocolSI.ToHexString(clearData)); Console.WriteLine("-- Sent Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.Write("<-- Waiting for the account balance... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); encryptedData = protocol.GetData(); clearData = ssInstance.Decrypt(encryptedData); double balance = BitConverter.ToDouble(clearData, 0); Console.WriteLine("done"); Console.WriteLine(" -- Received Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.WriteLine(" -- Account Balance: {0} = {1} .", balance.ToString(), ProtocolSI.ToHexString(clearData)); Console.Write("--> Requesting digital signature... "); // missing something like ProtocolSICmdType.REQUEST_DIGITAL_SIGNATURE // due to that, I used ProtocolSICmdType.DIGITAL_SIGNATURE as a REQUEST_DIGITAL_SIGNATURE // and the received digital signature is actually ProtocolSICmdType.SYM_CIPHER_DATA // because its encrypted with a symmetric algorithm. messageBytes = protocol.Make(ProtocolSICmdType.DIGITAL_SIGNATURE); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.Write("<-- Receiving encrypted digital signature... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); encryptedData = protocol.GetData(); byte[] signature = ssInstance.Decrypt(encryptedData); Console.WriteLine("done"); Console.WriteLine(" -- Received Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.WriteLine(" -- Signature: {0} .", Convert.ToBase64String(signature)); Console.Write("<-> Verify digital signature... "); // use previous clearData which is the balance converted to bytes bool signatureStatus = serverRsaProvider.VerifyData(clearData, new SHA256CryptoServiceProvider(), signature); Console.WriteLine(signatureStatus ? "verified" : "failed"); Console.Write("--> Sending digital signature status... "); messageBytes = protocol.Make(signatureStatus ? ProtocolSICmdType.ACK : ProtocolSICmdType.NACK); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.Write("<-- Waiting for an EOT command... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); Console.WriteLine("done"); } catch (Exception ex) when( ex is SocketException || ex is CryptographicException ) { Console.WriteLine("\n===\nException: {0}\nStackTrace:\n{1}\n", ex.Message, ex.StackTrace); } finally { Console.Write("<-> Closing all the connections and streams... "); networkStream?.Dispose(); tcpClient?.Close(); Console.WriteLine("done"); } }
ServerWithProtocolSI() { CreateAccounts(); try { Console.Write("<-> Starting server... "); serverRsaProvider = new RSACryptoServiceProvider(); tcpListener = new TcpListener(IPAddress.Any, SERVER_PORT); tcpListener.Start(); Console.WriteLine("done"); // client scope: this could be wrapped into a loop { Console.Write("<== Waiting for the client to connect... "); tcpClient = tcpListener.AcceptTcpClient(); networkStream = tcpClient.GetStream(); Console.WriteLine("done"); protocol = new ProtocolSI(); // Exchanging RSA public keys Console.Write("<-- Receiving RSA client public key... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); clientRsaProvider = new RSACryptoServiceProvider(); clientRsaProvider.FromXmlString(protocol.GetStringFromData()); Console.WriteLine("done"); Console.Write("--> Sending RSA server public key... "); messageBytes = protocol.Make(ProtocolSICmdType.PUBLIC_KEY, serverRsaProvider.ToXmlString(false)); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); // Receiving AES secrets Console.Write("<-- Receiving AES key... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); aes = new AesCryptoServiceProvider(); ssInstance = new SymmetricsSI(aes); aes.Key = serverRsaProvider.Decrypt(protocol.GetData(), true); Console.WriteLine("done"); Console.WriteLine(" -- Received: {0} .", ProtocolSI.ToHexString(aes.Key)); Console.Write("--> Sending an ACK command... "); messageBytes = protocol.Make(ProtocolSICmdType.ACK); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.Write("<-- Receiving AES IV... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); aes.IV = serverRsaProvider.Decrypt(protocol.GetData(), true); Console.WriteLine("done"); Console.WriteLine(" -- Received: {0} .", ProtocolSI.ToHexString(aes.IV)); Console.Write("--> Sending an ACK command... "); messageBytes = protocol.Make(ProtocolSICmdType.ACK); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.Write("<-- Waiting for an account balance request... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); byte[] encryptedData = protocol.GetData(); byte[] clearData = ssInstance.Decrypt(encryptedData); int accountId = BitConverter.ToInt32(clearData, 0); Console.WriteLine("done"); Console.WriteLine(" -- Received Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.WriteLine(" -- Account ID: {0} = {1} .", accountId.ToString(), ProtocolSI.ToHexString(clearData)); Console.Write("--> Sending the account balance... "); clearData = BitConverter.GetBytes(accounts[accountId]); encryptedData = ssInstance.Encrypt(clearData); messageBytes = protocol.Make(ProtocolSICmdType.SYM_CIPHER_DATA, encryptedData); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.WriteLine("-- Account Balance: {0} = {1} .", BitConverter.ToDouble(clearData, 0).ToString(), ProtocolSI.ToHexString(clearData)); Console.WriteLine("-- Sent Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.Write("<-- Waiting for a digital signature request... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); Console.WriteLine("done"); Console.Write("--> Sending digital signature... "); // use previous clearData which is the balance converted to bytes byte[] signature = serverRsaProvider.SignData(clearData, new SHA256CryptoServiceProvider()); encryptedData = ssInstance.Encrypt(signature); messageBytes = protocol.Make(ProtocolSICmdType.SYM_CIPHER_DATA, encryptedData); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); Console.WriteLine("-- Signature: {0} .", Convert.ToBase64String(signature)); Console.WriteLine("-- Sent Data: {0} .", ProtocolSI.ToHexString(encryptedData)); Console.Write("<-- Receiving digital signature status... "); networkStream.Read(protocol.Buffer, 0, protocol.Buffer.Length); Console.WriteLine(protocol.GetCmdType() == ProtocolSICmdType.ACK ? "verified" : "failed"); Console.Write("--> Sending EOT... "); messageBytes = protocol.Make(ProtocolSICmdType.EOT); networkStream.Write(messageBytes, 0, messageBytes.Length); Console.WriteLine("done"); } } catch (Exception ex) when( ex is SocketException || ex is CryptographicException ) { Console.WriteLine("\n===\nException: {0}\nStackTrace:\n{1}\n", ex.Message, ex.StackTrace); } finally { Console.Write("<-> Closing all the connections and streams... "); networkStream?.Dispose(); tcpClient?.Close(); tcpListener?.Stop(); Console.WriteLine("done"); } }