AES Spuckt müll aus

  • C#

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    AES Spuckt müll aus

    Hey leute,

    Ich habe inzwischen eine sichere Verbindung zwischen Server und Client aufgebaut mittels RSA und AES. Wenn ich jedoch nun z.B. einen Lizenzschlüssel "F4FBF-B60FC-6F3ED-1E5A9" durch den CryptoStream jage(RijndaelManaged), bekomme ich am anderen Ende folgendes wieder heraus: "Ü]Þí£ôÉò×â×$¼ÚD-1E5A9"

    wie man sieht stimmen die letzen 7 Buchstaben wieder überein, doch Alles davor schient nach wie vor verschlüsselt zu sein. Woran kann das liegen?
    ach mist... total vergessen die Funktion drum rum... Danke für dne Hinweis, direkt mal ausgebessert. Die Funktion DoTheThing wird bei nem Buttonklick ausgeführt. der eine Schlüssel steht halt derzeit noch als klartext im Quellcode, wird aber später (da ja auch ma landere Schlüssel abgefragt werden sollen) aus der DB abgefragt.
    Gut dann hier mal dat ganze:
    Server

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Net;
    5. using System.Net.Sockets;
    6. using System.Security.Cryptography;
    7. using System.Text;
    8. using MySql.Data.MySqlClient;
    9. using MySql.Data.Common;
    10. namespace ServerLizenz
    11. {
    12. class Program
    13. {
    14. static void Main(string[] args)
    15. {
    16. Encoding bla = Encoding.GetEncoding("ISO-8859-1");
    17. Int32 port = 14000;
    18. IPAddress localAddr = IPAddress.Parse("192.168.1.177");
    19. TcpListener server = new TcpListener(localAddr, port);
    20. server.Start();
    21. while (true)
    22. {
    23. Console.Write("Waiting for a connection... ");
    24. TcpClient client = server.AcceptTcpClient();
    25. Console.WriteLine("Connected!");
    26. NetworkStream stream = client.GetStream();
    27. stream.ReadTimeout = System.Threading.Timeout.Infinite;
    28. stream.WriteTimeout = System.Threading.Timeout.Infinite;
    29. byte[] KeyBuffer = new Byte[1510];
    30. stream.Read(KeyBuffer, 0, KeyBuffer.Length);
    31. stream.Flush();
    32. RSACryptoServiceProvider RSAC = new RSACryptoServiceProvider(4096);
    33. RSAC.FromXmlString(bla.GetString(KeyBuffer));
    34. RijndaelManaged RM = new RijndaelManaged();
    35. byte[] RMKeyBuffer = RSAC.Encrypt(RM.Key, true);
    36. stream.Write(RMKeyBuffer, 0, RMKeyBuffer.Length);
    37. stream.Flush();
    38. CryptoStream cs = new CryptoStream(stream, RM.CreateDecryptor(), CryptoStreamMode.Read);
    39. byte[] licence = new byte[23];
    40. cs.Read(licence, 0, licence.Length);
    41. cs.Dispose();
    42. string myConnectionString = "SERVER=Server;" +
    43. "DATABASE=Database;" +
    44. "UID=UID;" +
    45. "PASSWORD=Password;";
    46. MySqlConnection mysqlConn = new MySqlConnection(myConnectionString);
    47. MySqlCommand myComm = mysqlConn.CreateCommand();
    48. myComm.CommandText = "SELET * From lizenzen WHERE Lizenznummer='"+bla.GetString(licence)+"'";
    49. mysqlConn.Open();
    50. MySqlDataReader Reader = myComm.ExecuteReader();
    51. string Data = string.Empty;
    52. string blargh = string.Empty;
    53. while (Reader.Read())
    54. {
    55. for (int i = 0; i < Reader.FieldCount; i++)
    56. {
    57. blargh += "|"+Reader.GetDataTypeName(i);
    58. if (Reader.GetDataTypeName(i) == "DATE")
    59. {
    60. try
    61. {
    62. DateTime dt = Reader.GetDateTime(i);
    63. Data += dt.ToShortDateString() +",";
    64. }
    65. catch (Exception)
    66. { Data+= "|-|"; }
    67. }
    68. else
    69. { Data += Reader.GetValue(i).ToString() + ","; }
    70. }
    71. }
    72. CryptoStream csW = new CryptoStream(stream, RM.CreateEncryptor(), CryptoStreamMode.Write);
    73. byte[] DataBuffer= bla.GetBytes(Data);
    74. //stream.Write(DataBuffer, 0, DataBuffer.Length);
    75. csW.Write(DataBuffer, 0, DataBuffer.Length);
    76. csW.Flush();
    77. csW.Close();
    78. csW.Dispose();
    79. stream.Close();
    80. client.Close();
    81. }
    82. Console.ReadKey();
    83. }
    84. }
    85. }


    Client

    C#-Quellcode

    1. using System;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.ComponentModel;
    5. using System.Data;
    6. using System.Drawing;
    7. using System.Net;
    8. using System.Net.Sockets;
    9. using System.Security.Cryptography;
    10. using System.Text;
    11. using System.Windows.Forms;
    12. namespace ClientLizenz
    13. {
    14. public partial class Form1 : Form
    15. {
    16. public Form1()
    17. { InitializeComponent(); }
    18. private void button1_Click(object sender, EventArgs e)
    19. { DoTheThing("F4FBF-B60FC-6F3ED-1E5A9"); }
    20. private void DoTheThing(string Lizenz)
    21. {
    22. //try
    23. //{
    24. textBox2.Text = "Passed Beginning";
    25. Encoding bla = Encoding.GetEncoding("ISO-8859-1");
    26. Int32 port = 14000;
    27. TcpClient client = new TcpClient("192.168.1.177", port);
    28. NetworkStream stream = client.GetStream();
    29. stream.ReadTimeout = System.Threading.Timeout.Infinite;
    30. stream.WriteTimeout = System.Threading.Timeout.Infinite;
    31. textBox2.Text = "Passed Socket Creation";
    32. RSACryptoServiceProvider RSAC = new RSACryptoServiceProvider(4096);
    33. byte[] Key = bla.GetBytes(RSAC.ToXmlString(false));
    34. stream.Write(Key, 0, Key.Length);
    35. textBox2.Text = "Passed sending KEy";
    36. byte[] encryAES = new byte[512];
    37. stream.Read(encryAES, 0, encryAES.Length);
    38. textBox2.Text = "Passed receiving Encrypted AES Key";
    39. byte[] decryAES = RSAC.Decrypt(encryAES, true);
    40. string decryAesString = string.Empty;
    41. textBox2.Text = "Passed Decryption";
    42. foreach (byte item in decryAES)
    43. {
    44. decryAesString += ((int)item).ToString();
    45. }
    46. textBox1.Text = decryAesString;
    47. RijndaelManaged RM = new RijndaelManaged();
    48. RM.Key = decryAES;
    49. CryptoStream csS = new CryptoStream(stream, RM.CreateEncryptor(), CryptoStreamMode.Write);
    50. byte[] Licence = bla.GetBytes(Lizenz);
    51. csS.Write(Licence,0,Licence.Length);
    52. csS.Flush();
    53. csS.Dispose();
    54. CryptoStream csR = new CryptoStream(stream, RM.CreateDecryptor(), CryptoStreamMode.Read);
    55. byte[] Data = new byte[4096];
    56. csR.Read(Data, 0, Data.Length);
    57. csR.Flush();
    58. csR.Dispose();
    59. textBox3.Text = bla.GetString(Data);
    60. //}
    61. //catch (Exception e)
    62. //{
    63. // textBox1.Text = e.ToString();
    64. //}
    65. }
    66. }
    67. }


    Setz bei der SQL geschichte nach der Erstellung des CommandTexts einen Breakpoint, und schau dir mal dessen wert an
    also senden tust du eine key der Länge 755, aber beim Empfang wertest du nicht Stream.Read() aus, die Anzahl der gelesenen Bytes, sondern du verwendest den Keybuffer in voller Länge (1510).
    Dassis schoma komisch - k.A., ob das die Ursache ist.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    neuer Fehler: Ich habe die RMs (Rijanmanaged) von Server und Client verglichen, und fand unterschiedliche Werte der IV-Property. Der IV muß zusätzlich zum Key übertragen werden (es sei denn, du setzt ihn hardCodet, wassich aber uncool fände.)

    gugge vlt. Verschlüsseln + Autentifizieren
    gut, das mit dem IV habe ich inzwisachen auch herasugefunden... dass ich da nicht früher drauf gekommen bin...

    Auswerten des Streams... aber wie bekomme ich denn die Anzahl der bytes raus, die der Stream liest, bevor ich überhaupt Lese? Dabei brauch ich doch auch direkt mal einen Puffer?
    und ja, der Puffer hat die Doppelte länge, da zuvor noch eine RSA-Schlüssellänge von 4096 gewählt war, was mir aber beim Testen immer viel zu lange dauerte.

    EaranMaleasi schrieb:

    aber wie bekomme ich denn die Anzahl der bytes raus, die der Stream liest

    gugge im Control.Invoke() vs. .BeginInvoke() den Rückgabewert von Stream.Read()

    gugge auch Stream-Konzepte. Das Zusammenstöpseln betreibst du ja bereits, aber die Read-Schleife mittm Puffer.

    Auch brauchst du vmtl. ein weitergehendes Datenübertragungs-Protokoll, da du verschiedenste Daten überträgst: RSA-Key, AES-Key und Daten, und evtl. sogar verschiedenste Arten von Daten.
    Das sollte glaub jeweils unterschieden werden.
    Mein Grundkonzept für son Protokoll sieht vor, dass eine Dateneinheit immer aus Header und Daten besteht. Wobei der Header die Art der Daten und die Daten-Länge angibt.
    Sodass man immer abwechselnd den Header liest, dann die Daten, dann den nächsten Header, dann die Daten etc.
    Da der Header eine feste Länge hat kann jedes übertragene Byte eindeutig zugeordnet werden, und auch klar ist, wann eine Daten-Einheit abgeschlossen ist.
    was derzeit mein Problem ist, dass auf Serverseite, der erste cryptrostream im Read-modus ewig im Read bleibt und nicht die geschriebenen Daten empfängt oder erkennt ,dass Dateien empfangen wurde. schreibe ich jedenfalls auf der Client Seite hinter den ersten Cryptostream ein Dispose oder Close. so endet auf serverseite das Lesen, jedoch mit den exakten Daten...

    Welche Read schleife meinst ud nochmal?

    Keine Sorge, das mit dem Protokoll etc ist nicht vergessen. ich habe sowieso noch einiges zu tun an dem ganzen, es muss auchnoch in einzelnen Threads laufen... Timeouts haben... Obergrenze an Vebrindungen...etc.

    EaranMaleasi schrieb:

    Welche Read schleife meinst ud nochmal?
    guck doch einfach mal in den verlinkten Code, wie da Read() verwendet wird, insbesondere der Rückgabewert, anhand dessen ausgewertet wird, wieviele Bytes bisher übertragen wurden.
    Musste natürlich auf deine Bedingungen anpassen.


    schreibe ich jedenfalls auf der Client Seite hinter den ersten Cryptostream ein Dispose oder Close. so endet auf serverseite das Lesen, jedoch mit den exakten Daten.
    Jo, das ist wohl halt so: Ein CryptoStream muß geschlossen werden, um den Schreibvorgang abzuschließen.
    Pack ihn in ein Using-Block.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    hmm nun gut, ein Read in eine DoWhile schleife zu packen ist durchaus sinvoll, (auch mal getestet, jeodoch ohne erfolg hinsichtlich meines eigentlichen Problemes), doch bringt mich das kein bisschen weiter mit dem Problem, dass der Crypto Stream nicht mehr mit Lesen aufhören möchte. wenn du mir ein konkretes beispiel hättest, wie man mit dem Cryptostream mehrfach daten hin und her shcickt, wäre ich dir sehr dankbar.
    es geht nicht. Cryptostream (im Grunde AES) verschlüsselt immer den kompletten Text, kann also prinzipiell nicht ein unendlicher Stream sein, im Gegensatz zum Networkstream.
    Aber scheint mir kein Problem, für jeden Lese/Schreib-Vorgang halt einen neuen CryptoStream auf den Networkstream draufzusetzen.
    das meinte ich ja mehr oder minder, weswegen ich ja nicht umsonst den CS mehrfach aufsetze. jedoch ließt auf einer Seiten des Servers der CS unendlich lange, während der client immer schön brav das Lesen beendet. anderst herum, dispose ich nach dem ersten Clientseitigem Schreiben den CryptoStream, erhalte ich die Korrekten Daten auf der Serverseite, kann damit meine DB abfragen durchlaufen lassen und könnte wieder zurückschicken, wäre der NEtworkStream nciht gleich mitvernichtet worden. wasalso kann ich tun um einen CryptoStream zu beenden ohne dabei den darunter liegenden NetworkStream mit ins Nirvana zu reißen?... evtl ein Using?

    Edit: nope ein Using vernichtet den NetworkStream ebenso.
    Eigenen Stream schreiben, der die Daten puffert und ab einer bestimmten Datengröße entschlüsselt und zum lesen/schreiben freigibt. CryptoStream kannst direkt dort integrieren, da du jedesmal einen neuen CryptoStream erstellen müsstest geht es auch über den Umweg msdn.microsoft.com/de-de/libra…phy.icryptotransform.aspx machen. Ohne jedesmal ein neues Objekt erstellen zu müssen.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    so, jetz weiß glaub.
    Problem ist, CryptoStream kannste nicht Flushen. Das liegt an AES, dass da immer ein Block fertig-crypted sein muß, bevor er rausgeht oder reinkommt.

    Also ich hab jetzt im Server einen BinaryReader auf den CS gesetzt, und im Client einen BinaryWriter, und der Client kann beliebig viele Strings an den Server senden, aber der Text kommt erst an, wenn im Client genügend viel hineingeschrieben wurde, dass ein Block rausgeht.
    Und im Client bleibt eiglich immer ein Daten-Rest zurück, sodass auch im Server immer ein Endchen fehlt.

    Aber ansonsten ist das mittm BinaryReader/Writer wirklich nett

    C#-Quellcode

    1. using System;
    2. using System.IO;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Net;
    6. using System.Net.Sockets;
    7. using System.Security.Cryptography;
    8. using System.Text;
    9. using MySql.Data.MySqlClient;
    10. namespace A0Console {
    11. static class Program {
    12. static void Main(string[] args) {
    13. Int32 port = 12345;
    14. IPAddress localAddr = IPAddress.Parse("192.168.1.2");
    15. TcpListener server = new TcpListener(localAddr, port);
    16. server.Start();
    17. while(true) {
    18. Console.Write("Waiting for a connection... ");
    19. TcpClient client = server.AcceptTcpClient();
    20. Console.WriteLine("Connected!");
    21. NetworkStream stream = client.GetStream();
    22. byte[] buf = new Byte[1510];
    23. var l = stream.Read(buf, 0, buf.Length);
    24. RSACryptoServiceProvider RSAC = new RSACryptoServiceProvider(4096);
    25. RSAC.ImportCspBlob(buf.Take( 0, l));
    26. RijndaelManaged RM = new RijndaelManaged();
    27. var aesBlob = RM.Key.Concat(RM.IV).ToArray();
    28. byte[] RMKeyBuffer = RSAC.Encrypt(aesBlob, true);
    29. stream.Write(RMKeyBuffer, 0, RMKeyBuffer.Length);
    30. CryptoStream cs = new CryptoStream(stream, RM.CreateDecryptor(), CryptoStreamMode.Read);
    31. var rd = new BinaryReader(cs, Encoding.UTF7);
    32. string s;
    33. do {
    34. s = rd.ReadString();
    35. Console.WriteLine(s);
    36. } while(s!="end");
    37. var i = 9;
    38. }
    39. Console.ReadKey();
    40. }
    41. }
    42. }
    43. //...
    44. public partial class Form1 : Form {
    45. private BinaryWriter _Writer;
    46. public Form1() { InitializeComponent();
    47. var Lizenz = "0815-0815-007-drölf";
    48. Int32 port = 12345;
    49. TcpClient client = new TcpClient("192.168.1.2", port);
    50. var stream = client.GetStream();
    51. RSACryptoServiceProvider RSAC = new RSACryptoServiceProvider(4096);
    52. var cspBlob = RSAC.ExportCspBlob(false);
    53. stream.Write(cspBlob, 0, cspBlob.Length);
    54. byte[] encryAES = new byte[512];
    55. stream.Read(encryAES, 0, encryAES.Length);
    56. byte[] aesBlob = RSAC.Decrypt(encryAES, true);
    57. RijndaelManaged RM = new RijndaelManaged();
    58. RM.Key = aesBlob.Take(0, 32);
    59. RM.IV = aesBlob.Take(32, 16);
    60. CryptoStream csS = new CryptoStream(stream, RM.CreateEncryptor(), CryptoStreamMode.Write);
    61. _Writer = new BinaryWriter(csS, Encoding.UTF7);
    62. _Writer.Write(Lizenz);
    63. }
    64. private void button1_Click(object sender, System.EventArgs e) {
    65. _Writer.Write(textBox1.Text);
    66. }
    67. }