C# - Rijndael-algoritmussal titkosított adatok küldése Tcp porton

forráskód letöltése
Az alkalmazások többféleképpen kommunikálhatnak egymással, azonban a kommunikáció biztonsága szempontjából van egy közös vonás mindegyikben: az alkalmazások közötti adatforgalmat ajánlatos titkosított formában lebonyolítani. Ennek megoldására a .NET Framework a System.Security.Cryptography névtérben megtalálható számtalan osztályt biztosítja. Cikkünkben bemutatjuk, hogy miként kódolható az alkalmazások között mozgatott adathalmaz – mondjuk egy karakterlánc - Rijndael-féle algoritmussal, a RijndaelManaged osztály felhasználásával.
Áttekintés
A példánkban két projekt található a példa mappájában, melyek egyike a kliens-alkalmazás, másik pedig a szerver. A kliensből küldünk egy karakterláncot titkosítva a szervernek, mely a kódolt információt visszafejti.
A megoldásban a privát-kulcsos titkosítást alkalmaztuk, mely azt jelenti, hogy mindkét, a kommunikációban résztvevő programnak ugyanazzal a kulccsal kell rendelkeznie, mely kulcsot csak a kommunikációban résztvevő felek ismerhetik. A kulcsokat a RijndaelManaged osztály metódusaiban használjuk fel, az algoritmus leprogramozása nem a mi feladatunk, ezt elvégzi az osztály helyettünk.
A programok TCP porton keresztül kommunikálnak, így el kell érnünk a System.Net.Socket névteret:
using System.Net.Sockets;
Valamint a titkosító osztályokat tartalmazó névteret:
using System.Security.Cryptography;
A kliens projekt
A programban meg kell adni a célszámítógép nevét, melyen a szerver-alkalmazás fut. Azonos gépen futtatva a két alkalmazást itt a LOCALHOST nevet kell megadni. A szövegmezőbe írt karakterláncot a KÜLDÉS gombra kattintva juttathatjuk el a 9999-es számú Tcp port felhasználásával a szerverünkhöz titkosítva.
A kódban először létre kell hoznunk egy TcpClient objektumot:
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(textBox2.Text,9999);
Példányosítanunk kell a hálózati adatfolyam kezelésére hivatott objektumot:
NetworkStream ns = client.GetStream();
Létrehozunk egy példányt a titkosítást végző osztályból:
RijndaelManaged rm = new RijndaelManaged();
Meg kell adnunk a titkosítás kulcsát, és egy inicializáló vektort. Ezek tetszőlegesek lehetnek, lényeg, hogy mindkét alkalmazásban azonosak legyenek:
byte[] key = {2, 55, 86, 23, 2, 21, 111, 132, 222, 182, 72, 132, 12, 3, 231, 12};
byte[] iv = {12, 231, 34, 242, 52, 12, 8, 21, 98, 33, 48, 78, 57, 11, 49, 88};
A titkos adatokat tartalmazó adatfolyamot egy CryptStream típusú objektum reprezentálja, melynek paraméterlistájában meg kell adni a NetworkStream objektumunkat, második paraméterében a RijndaelManaged osztály CreateEncryptor metódusának visszatérési értékét, harmadik paraméterében pedig az adatfolyam elérésének módját, amely kliens-oldalon írás-mód:
CryptoStream cs = new CryptoStream(ns,rm.CreateEncryptor(key,iv),CryptoStreamMode.Write);
Létre kell hoznunk egy StreamWriter objektumot, mely a kódolt információt a küldendő adatfolyamba helyezi, majd meghívjuk a Write metódusát:
StreamWriter writer = new StreamWriter(cs);
writer.WriteLine(textBox1.Text);
A szerver projekt
A szerver alkalmazásunk a 9999-es porton figyel, és várja, hogy megérkezzen a titkosított üzenet. Ennek érdekében itt egy TcpListener objektumra van szükségünk:
private TcpListener listener = new TcpListener(9999);
A program indulásakor meghívjuk az objektum Start metódusát:
listener.Start();
A FOGADÁS gombra kattintva elindítjuk a szoftvercsatorna folyamatos ellenőrzésének műveletét, melynek akkor van vége, ha egy üzenet megérkezik:
while(!listener.Pending())
{
  Thread.Sleep(5000);
}
Amennyiben megérkezett egy üzenet, fogadjuk azt a TcpClient objektum felhasználásával:
TcpClient server = listener.AcceptTcpClient();
Az adathalmaz kezeléséhez, és dekódolásához létrehozzuk az objektumokat:
NetworkStream ns = server.GetStream();
RijndaelManaged rm = new RijndaelManaged();
A CryptoStream osztály létrehozásakor a RijndaelManaged osztály CreateDecryptor metódusát hívjuk meg a kulcs és a vektor értékének megadásával:
CryptoStream cs = new CryptoStream(ns,rm.CreateDecryptor(key, iv),CryptoStreamMode.Read);
Megadjuk, hogy itt olvasási műveletről van szó.
Most már csak ki kell emelnünk az adatfolyamból a titkosított adatokat, és elhelyezni a ListBox kontrol egy sorában:
reader = new StreamReader(cs);
listBox1.Items.Add("A fogadott üzenet dekódolva: " + reader.ReadToEnd());
A Form-on található jelölőnégyzet üresen hagyásával az érkezett üzenetet kódoltan jeleníthetjük meg. Ekkor a StreamReader objektumot a NetworkStream objektummal kell létrehoznunk:
reader = new StreamReader(ns);
A kulcs és vektor adatai természetesen azonosak a kliens-oldalon megadott értékekkel.