I've seen a bunch of these questions on here, but none of the answers have been able to resolve my problem. I wrote a Socket to sit on one of our servers, and using another program to talk with that Socket in order to get an encryption key for decrypting sensitive data. Below is my code.
Socket Server:
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
namespace Netgen_Encryption_Socket
{
class Program
{
private static IPAddress ip = IPAddress.Parse("127.0.0.1");
private static string encryptionKey = "2387429837498279832";
private static byte[] IV = new byte[] { 23, 243, 29, 26, 78, 67, 23, 62, 81, 93, 12, 205, 217, 10, 216, 13 };
private static byte[] salt = new byte[] { 21, 10, 3, 26, 10, 3, 1, 49, 55, 171, 1, 51, 75, 16, 27, 14, 23, 29, 70, 16, 55, 18, 12, 2, 4, 29, 77, 52, 5, 44, 127, 164 };
private static string masterPassword = "SecretPassword";
private static bool connectionAccepted = true;
static void Main(string[] args) => Listen();
static void Listen()
{
TcpListener serverSocket = new TcpListener(IPAddress.Any, 9843);
TcpClient clientSocket = default(TcpClient);
int requestCount = 0;
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
if (((IPEndPoint)clientSocket.Client.RemoteEndPoint).Address.ToString() == ip.ToString())
{
SendMessage(clientSocket, serverSocket, $"Accepted Connection from {((IPEndPoint)clientSocket.Client.RemoteEndPoint).Address}");
connectionAccepted = true;
}
else
{
SendMessage(clientSocket, serverSocket, $"Rejected Connection from {((IPEndPoint)clientSocket.Client.RemoteEndPoint).Address}");
Restart(clientSocket, serverSocket);
}
while (connectionAccepted)
{
try
{
requestCount += 1;
if (requestCount >= 4)
Restart(clientSocket, serverSocket);
string data = GetMessage(clientSocket, serverSocket);
if (data == masterPassword)
{
SendMessage(clientSocket, serverSocket, encryptionKey);
}
else
{
SendMessage(clientSocket, serverSocket, $"Invalid master password. {3 - requestCount} attempts remaining!");
if (3 - requestCount <= 0)
SendMessage(clientSocket, serverSocket, Environment.NewLine + $"Too many incorrect attempts. Connection terminated!");
}
}
catch
{
Restart(clientSocket, serverSocket);
}
}
Stop(clientSocket, serverSocket);
}
static void Restart(TcpClient client, TcpListener listener)
{
client.Close();
listener.Stop();
Listen();
}
static void Stop(TcpClient client, TcpListener listener)
{
client.Close();
listener.Stop();
}
static string GetMessage(TcpClient client, TcpListener listener)
{
NetworkStream networkStream = client.GetStream();
byte[] bytesFrom = new byte[client.ReceiveBufferSize];
networkStream.Read(bytesFrom, 0, (int)client.ReceiveBufferSize);
string data = Decrypt(bytesFrom);
data = data.Substring(0, data.IndexOf("$"));
return data;
}
static void SendMessage(TcpClient client, TcpListener listener, string message)
{
NetworkStream networkStream = client.GetStream();
byte[] sendBytes = Encrypt(message);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
static byte[] Encrypt(string stringToEncrypt)
{
byte[] encryptedBytes;
using(Aes AES = Aes.Create())
{
AES.Key = salt;
AES.IV = IV;
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
var encryptor = AES.CreateEncryptor(AES.Key, AES.IV);
using(MemoryStream ms = new MemoryStream())
{
using(CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using(StreamWriter sw = new StreamWriter(cs))
{
sw.Write(stringToEncrypt);
}
encryptedBytes = ms.ToArray();
if (!cs.HasFlushedFinalBlock)
cs.FlushFinalBlock();
}
}
}
var combined = new byte[IV.Length + encryptedBytes.Length];
Array.Copy(IV, 0, combined, 0, IV.Length);
Array.Copy(encryptedBytes, 0, combined, IV.Length, encryptedBytes.Length);
return combined;
}
static string Decrypt(byte[] bytesToDecrypt)
{
string decryptedString = null;
using(Aes AES = Aes.Create())
{
AES.Key = salt;
byte[] cipherText = new byte[bytesToDecrypt.Length - IV.Length];
Array.Copy(bytesToDecrypt, IV, IV.Length);
Array.Copy(bytesToDecrypt, IV.Length, cipherText, 0, cipherText.Length);
AES.IV = IV;
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
var decryptor = AES.CreateDecryptor(AES.Key, AES.IV);
using(MemoryStream ms = new MemoryStream(cipherText))
{
using(CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using(StreamReader sr = new StreamReader(cs))
{
decryptedString = sr.ReadToEnd();
}
}
}
}
return decryptedString;
}
}
}
Socket Client:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security.Cryptography;
namespace Client_Socket_Tester
{
public partial class Form1 : Form
{
TcpClient clientSocket = new TcpClient();
private static byte[] IV = new byte[] { 23, 243, 29, 26, 78, 67, 23, 62, 81, 93, 12, 205, 217, 10, 216, 13 };
private static byte[] salt = new byte[] { 21, 10, 3, 26, 10, 3, 1, 49, 55, 171, 1, 51, 75, 16, 27, 14, 23, 29, 70, 16, 55, 18, 12, 2, 4, 29, 77, 52, 5, 44, 127, 164 };
public Form1() => InitializeComponent();
private void Form1_Load(object sender, EventArgs ev)
{
try
{
clientSocket.Connect(IPAddress.Parse("127.0.0.1"), 9843);
AppendClientMessage(" >> Connection established");
}
catch (Exception e)
{
AppendClientMessage($" >> Client Error: {e.Message}");
}
}
private void AppendClientMessage(string msg)
{
richTextBox1.Text += Environment.NewLine + msg;
}
private void SendMessage(string msg)
{
try
{
byte[] outStream = Encrypt($"{msg}$");
NetworkStream serverStream = clientSocket.GetStream();
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string returnData = Decrypt(inStream);
AppendClientMessage(returnData);
richTextBox2.Text = "";
richTextBox2.Focus();
}
catch (Exception e)
{
AppendClientMessage($" >> Client Error: {e.Message}");
}
}
private void button1_Click(object sender, EventArgs ev)
{
try
{
SendMessage(richTextBox2.Text);
}
catch (Exception e)
{
AppendClientMessage($" >> Client Error: {e.Message}");
}
}
static byte[] Encrypt(string stringToEncrypt)
{
byte[] encryptedBytes;
using (Aes AES = Aes.Create())
{
AES.Key = salt;
AES.IV = IV;
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
var encryptor = AES.CreateEncryptor(AES.Key, AES.IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(stringToEncrypt);
}
encryptedBytes = ms.ToArray();
if (!cs.HasFlushedFinalBlock)
cs.FlushFinalBlock();
}
}
}
var combined = new byte[IV.Length + encryptedBytes.Length];
Array.Copy(IV, 0, combined, 0, IV.Length);
Array.Copy(encryptedBytes, 0, combined, IV.Length, encryptedBytes.Length);
return combined;
}
static string Decrypt(byte[] bytesToDecrypt)
{
string decryptedString = null;
using (Aes AES = Aes.Create())
{
AES.Key = salt;
byte[] cipherText = new byte[bytesToDecrypt.Length - IV.Length];
Array.Copy(bytesToDecrypt, IV, IV.Length);
Array.Copy(bytesToDecrypt, IV.Length, cipherText, 0, cipherText.Length);
AES.IV = IV;
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
var decryptor = AES.CreateDecryptor(AES.Key, AES.IV);
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decryptedString = sr.ReadToEnd();
}
}
}
}
return decryptedString;
}
}
}
I have tried most of the suggestions in other, similar posts. Including changing the padding mode, and/or converting to Base64. The end results is always either the encoding is messed up and spits out a series of random characters, or it gives me a "Padding is invalid and cannot be removed." error when decrypting (Client Side).
Any help would be greatly appreciated!
Thanks.