mcrypt: Problem mit Kompatibilität PHP und Microsoft .NET
markus7611
- php
Hallo zusammen,
wir haben folgendes Problem:
Der Datenaustausch, der mittels einer Schnittstelle zwischen einem Linux-System (PHP) und einem Windows-System (.NET) abläuft, soll verschlüsselt werden. Genauer gesagt: Der Stream mit den inhaltlichen Daten soll verschlüsselt transportiert werden.
In PHP haben wir mit der Funktion mcrypt Tests für die Verschlüsselung und Entschlüsselung mittels AES (256 bit) gemacht.
Solange wir mit PHP verschlüsseln, können wir das Ergebnis auch mit PHP wieder entschlüsseln.
Wenn der .NET-Techniker aber etwas verschlüsselt, kann er es mit unserer PHP-Lösung aber nicht entschlüsseln. Umgekehrt das gleiche Problem.
Und dies trotz gleichem Verfahren (AES-256) und natürlich gleichem Key!
Anscheinend gibt es Kompatibilitätsprobleme zwischen der Art und Weise, wie PHP verschlüsselt und wie .NET verschlüsselt.
Was kann man da machen? Gibt es Lösungen, es kompatibel zu machen?
Oder gibt es eine andere Verschlüsselungsmethode, bei der diese Probleme nicht auftreten?
Bin für jeden Ratschlag dankbar.
Viele Grüße,
Markus
Hallo,
also bei mir klappt das Zusammenspiel zwischen .Net und PHP (mit mcrypt) und AES problemlos.
Also, nur weil man AES nutzt, heißt dies nicht, dass zwei Anwendungen damit kompatibel sind.
Man muss viele Sachen noch bedenken, dass fängt an, dass beide unbedingt die gleiche Block- und Key Größe verwenden müssen (empfehle für beides 128 Bit), den gleichen Betriebsmodi (z.B. CBC), bei z.B. CBC dann den gleichen IV, das gleiche Padding Verfahren und wenn man einen String als Key nutzt unbedingt das gleiche 'String to key' Verfahren. Ebenso kommt es darauf an, wie die Ausgabe erfolgt. Wird diese bei euch in PHP nochmal mit base64 Kodiert? Oder wie löst ihr das?
Ich vermute mal es liegt an den Betriebsmodi. Praktisch wäre es, wenn du beide im CBC Modus betreibst, dann müssen aber beide den IV kennen. Dies geschieht nicht automatisch, sondern dies muss _du_ übernehmen.
Wenn es zu kompliziert ist, kannst du den weniger sicheren ECB Modus nutzen, da brauchst du dich um den IV nicht kümmern.
Wie gesagt, man bekommt es relativ schnell zum laufen ohne da irgendwelche großen Änderungen vornehmen zu müssen. Die Rahmenbedinungen müssen aber stimmen.
Grüße
Andavos
PS:
Ohne PHP und C# Code kann man dir nur schlecht helfen.
Hallo,
ansonsten hier mal mein Code:
$hash = md5("Mein Key"); //md5 damit man immer ein 128 Bit key erhält.
//Key in Binaerstring umwandeln
$key = pack("H*", $hash);
//$text mit $key verschluesseln
$td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $text);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
echo "IV: ".base64_encode($iv)."<br>
Cipher: ".base64_encode($cipher)."<br>
Key: ".base64_encode($key);
Wichtig! Im C# / .Net Code muss sowohl $iv als auch $encrypted_data bekannt sein.
Dann der C# Code:
byte[] iv = Convert.FromBase64String("mein IV der mit base64 Codiert wurde");
byte[] cipher = Convert.FromBase64String("meine Verschlüsselten Daten mit base64 Kodierung");
byte[] key = Convert.FromBase64String("mein Key der mit base64 kodiert wurde");
Rijndael aes = new RijndaelManaged();
aes.Padding = PaddingMode.Zeros;
MemoryStream stream = new MemoryStream(cipher);
CryptoStream decrypt = new CryptoStream(stream, aes.CreateDecryptor(key, iv), CryptoStreamMode.Read);
StreamReader reader = new StreamReader(decrypt);
string text = reader.ReadToEnd();
reader.Close();
decrypt.Close();
stream.Close();
aes.Clear();
Achja, das ist nun ungetestet. In meinen Fall war der Einsatz noch etwas komplexer und der Austausch des Keys zwischen den Applikationen hat anderes stattgefunden. Auch wurden in C# noch andere Rijndael Klassen genutzt.
Grüße
Andavos - www.php-einfach.de