Hand in Hand C# und Php

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Hand in Hand C# und Php

    Hallo,

    ich sende einen Stream an PHP und lese diesen aus. Dieser Stream ist verschüsselt. benutzt wurde Rijndael.

    Mein Problem ist, dass ich in PHP nicht wirklich firm bin und ich das De und EnCoding auch auf PHP Seite benötige.

    Meine Frage ist nun: Was mache ich auf PHP Seite falsch, wenn ich den Stream durch das Entschlüsseln jage? Ich denke wennich den Initialsierungsvektor baue, mache ich den Fehler. (GetKeyByKeyString)


    Wäre Super, wenn jemand da mal mit den Augen drüberfliegt. Habe versucht, bestmöglich zu dokumentieren.

    Chris

    ----

    Mein PHP Code:

    PHP-Code:
    class Registrierung
    {
        private 
    $xmlPlain;
        private 
    $xmlValid;
        private 
    $db;
        private 
    $key;
        private 
    $keyIv;
        private 
    $keySize;
        private 
    $blockSize;

        public function 
    Registrierung($sendData)
        {
              
    $this->xmlPlain simplexml_load_string($sendData);
              
    $this->db = new DBAccess(); // Eigene Klasse für DB Zugriff
              
    $this->key "3EisFürHannah";
              
    $this->keyIv "3EisFürHannah";
              
    $this->keySize 256;
              
    $this->blockSize 256;          
            
            
    // Registrieren
            
    $this->ExecuteReg();        
        }

        private Function 
    ExecuteReg()
        {    
            
    $decoded $this->xmlPlain->Registration;    
            
    // Den Initialsierungsvektor bau ich selbst .... 
               //$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
               
    $iv $this->GetKeyByKeyString($this->keyIv);
               
    $key $this->GetKeyByKeyString($this->key);           
               
    $decrypted mcrypt_decrypt(MCRYPT_RIJNDAEL_256, , $decodedMCRYPT_MODE_ECB$iv);
            return    
    $decrypted;
        }
        
        private function 
    GetKeyByKeyString($strKeyString)
        {
            
    // die Schluesselgroesse in Byte entspricht einer Unicodestringlaenge von Keysize / 16
            
    $iKeyLen $this->keySize 16;
        
            
    // Password auf die Schluessellaenge von 256bit bringen
            
    if ($strKeyString.Length iKeyLen$strKeyString substr(strKeyString0iKeyLen); // zu lang, abhacken
            
    if ($strKeyString.Length iKeyLen$strKeyString str_pad(strKeyStringiKeyLen'#'); // zu kurz, auffüllen
            
            
    echo "\r\n KEY: ".$strKeyString;
        
            
    // auf 256bit getrimmtes Password in einen Unicodekonformen Schluessel wandeln  -jedoch kommt hier immer Gülle raus - wieso nur?
            
    echo $strKeyString;
            return 
    $strKeyString;
        }

    Das Gegenstück in C# sieht so aus:

    PHP-Code:
    public class EnviCrypt
        
    {
            private 
    readonly int _keySize 256;
            private 
    readonly int _blockSize 256;
            private 
    string _ipNichtErmittelbar "IP Nicht ermittelbar.";
            private 
    string _medienNichtErmittelbar "Medien nicht ermittelbar.";

            private const 
    string iv "3EisFürHannah";
                    private const 
    string key "3EisFürHannah";
                                                  

            
    /// <summary>
            /// Konstruktor.
            /// </summary>
            
    public EnviCrypt()
            {
                        
    GetIVByKeyString(iv);
                
    GetKeyByKeyString(key);
            }
            
            
    /// <summary>
            /// Passwortaufbereitung
            /// </summary>
            
    private byte[] GetKeyByKeyString(string strKeyString)
            {
                
    // die Schluesselgroesse in Byte entspricht einer Unicodestringlaenge von Keysize / 16
                
    int iKeyLen _keySize 16;

                
    // Password auf die Schluessellaenge von 256bit bringen
                
    if (strKeyString.Length iKeyLenstrKeyString strKeyString.Substring(0iKeyLen); // zu lang, abhacken
                
    if (strKeyString.Length iKeyLenstrKeyString strKeyString.PadRight(iKeyLen'#'); // zu kurz, auffüllen

                // auf 256bit getrimmtes Password in einen Unicodekonformen Schluessel wandeln

                
    return Encoding.Unicode.GetBytes(strKeyString);
            }

            
    /// <summary>
            /// Initialisierungsvektor
            /// </summary>
            
    private byte[] GetIVByKeyString(string strKeyString)
            {
                
    // Initialisierungvektor ist gleich dem Schluessel.
                // RIJANDAL benötigt dies, hier wird nur das Passwort
                // als Bytefolge benutzt, könnte man ausbauen.
                
    return GetKeyByKeyString(strKeyString);
            }

                    
    /// <summary>
            /// verschlusseln
            /// </summary>
            
    public string EncryptString(string strInputString)
                    {
                        return 
    EncryptString(strInputStringkey);
                    }

            
    /// <summary>
            /// verschlusseln
            /// </summary>
            
    public string EncryptString(string strInputStringstring strKeyString)
            {
               try
               {
                  
    // den Schluessel und den Initalisierungsvektor holen
                  
    byte[] abyKey GetKeyByKeyString(strKeyString);
                  
    byte[] abyIV GetIVByKeyString(strKeyString);

                  
    // hier kommt dann der Encryptedte String rein
                  
    string strResult "";

                  
    // erzeugen eines Rijndael-Crypthographieobjektes
                  
    RijndaelManaged rij = new RijndaelManaged();
                  
    rij.BlockSize _blockSize;
                  
    rij.KeySize _keySize;

                  
    // Encodierung funktioniert auf Basis von Streams, d.h....
                  // ...einen Stream fuer die Eingabe erstellen und mit encodierenden String versorgen...
                  
    MemoryStream inStream = new MemoryStream(Encoding.Unicode.GetBytes(strInputString));

                  
    // ...einen Stream fuer die Ausgabe erstellen, da wo der encryptete String rein soll...
                  
    MemoryStream outStream = new MemoryStream();

                  
    // ...sowie der Crypthographistream; der stellt die Verbindung zwischen den beiden Streams
                  // her und erledigt den Encryptvorgang
                  // hier muss jetzt auch das Encryptobjekt uebergeben werden, damit der Stream weiss,
                  // wie er encrypten soll
                  
    CryptoStream csStream = new CryptoStream(outStreamrij.CreateEncryptor(abyKeyabyIV),
                     
    CryptoStreamMode.Write);

                  
    // den Inputstream bis zum Ende auslesen und an den Cryptographistream uebergeben
                  // ACHTUNG: die Methode ReadByte gibt kein Byte sondern ein int zurueck,
                  // da -1 als Rueckgabewert moeglich!
                  
    int iData;
                  while ((
    iData inStream.ReadByte()) != -1csStream.WriteByte((byte)iData);

                  
    // aufraeumen
                  
    csStream.Close();
                  
    outStream.Close();
                  
    inStream.Close();

                  
    // fuer abschliessende Operationen brauchen wir den Stream komplett als Array
                  
    byte[] abyBuffer outStream.ToArray();

                  
    // der gecryptete String enthaelt keine sinnvollen Zeichen mehr,
                  // d.h. wenn man den String als Text in eine Datei schreiben will gibt es Probleme
                  // daher wird hier jedes Byte als seine Hexadezimalzahlentsprechung geschrieben.
                  // z.B. 255 als "FF" in den String geschrieben
                  
    foreach (byte singleByte in abyBufferstrResult += singleByte.ToString("X2");

                  
    // endlich fertig, unsere Funktion hat aus einem sinnvollen String eine
                  // encryptete Zeichenfolge im Format "FFAAEA01..." etc. erzeugt
                  
    return strResult;
               }
               catch (
    Exception ex)
               {
                  throw new 
    Exception("Verschlüsselung fehlgeschlagen " ex.Message);
               }
            }

            
    /// <summary>
            /// Entschlüsseln
            /// </summary>
            
    public string DecryptString(string strInputStringstring strKeyString)
            {
               try
               {
                  
    // den Schluessel und den Initalisierungsvektor holen
                  
    byte[] abyKey GetKeyByKeyString(strKeyString);
                  
    byte[] abyIV GetIVByKeyString(strKeyString);

                  
    // erzeugen eines Rijndael-Crypthographieobjektes
                  
    RijndaelManaged rij = new RijndaelManaged();
                  
    rij.BlockSize _blockSize;
                  
    rij.KeySize _keySize;

                  
    // der Stream in den wir den nicht lesbaren Encrypteten String schreiben...
                  
    MemoryStream inStream = new MemoryStream();

                  
    // ...was genau hier geschieht, die Zeichen des Strings hatten wir als Hexadezimalzahlen,
                  // jetzt muessen daraus wieder die Bytes werden z.B. aus "FF" das Byte mit dem Wert 255
                  
    for (int i 0strInputString.Length+= 2)
                     
    inStream.WriteByte(byte.Parse(strInputString.Substring(i2),
                        
    System.Globalization.NumberStyles.AllowHexSpecifier));

                  
    // nach dem Vollschreiben steht der Lese/Schreibzeiger auf dem Ende des Stream,
                  // fuer weitere Aktionen setzen wir ihn wieder an den Anfang
                  
    inStream.Position 0;

                  
    // jetzt brauchen wir noch einen Ausgabestream und einen Cryptographiestream
                  // der Input und Output ueber den Cryptographiealgorithmus miteinander verbindet
                  
    MemoryStream outStream = new MemoryStream();
                  
    CryptoStream csStream = new CryptoStream(inStreamrij.CreateDecryptor(abyKeyabyIV),
                     
    CryptoStreamMode.Read);

                  
    // hier wird jetzt aus dem Crypthographiestream (der den Inputstream als Quelle hat)
                  // das rueckgewandeltet Byte gelesen
                  // ACHTUNG: die Methode ReadByte gibt kein Byte sondern ein int zurueck,
                  // da -1 als Rueckgabewert moeglich!
                  
    int iData;
                  while ((
    iData csStream.ReadByte()) != -1outStream.WriteByte((byte)iData);

                  
    // aufraeumen
                  
    csStream.Close();
                  
    outStream.Close();
                  
    inStream.Close();

                  
    // wir wohlen am Ende einen String haben, also den Stream als Array abbilden
                  
    byte[] abyBuffer outStream.ToArray();

                  
    // Bytes sollen als Unicodezeichen interpretiert werden
                  
    return Encoding.Unicode.GetString(abyBuffer);
               }
               catch (
    Exception ex)
               {
                  throw new 
    Exception(ex.Message "\n\nGrund: wahrscheinlich falsches Password.");
               }
            }
        }

    www.software-developers-home.de

  • #2
    Noch eine Anmerkung:

    Ich bekomme die Fehlermeldung:

    mcrypt_decrypt() [<a href='function.mcrypt-decrypt'>function.mcrypt-decrypt</a>]: The IV parameter must be as long as the blocksize in
    www.software-developers-home.de

    Kommentar


    • #3
      Hallo

      ich will das Problem noch mal konkretisieren.

      Diese C# Zeile muss ich nach PHP bringen:

      return Encoding.Unicode.GetBytes(strKeyString);

      Es wird aus 3EisFuerHannah:

      "[0]=51 '3', [1]=0 '', [2]=69 'E', [3]=0 '', [4]=105 'i', [5]=0 '', [6]=115 's', [7]=0 '', [8]=70 'F', [9]=0 '', [10]=117 'u', [11]=0 '' , [12]=101 'e', [13]=0 '', [14]=114 'r', [15]=0 '', [16]=72 'H', [17]=0 '', [18]=97 'a', [19]=0 '', [20]=110 'n', [21]=0 '', [22]=110 'n', [23]=0 '', [24]=97 'a', [25]=0 '', [26]=104 'h', [27]=0 '', [28]=35 '#', [29]=0 '', [30]=35 '#', [31]=0 ''";
      Nun ist meine Frage, wie mache ich aus einem String in PHP ein Bytefeld in dieser Form?


      Chris
      www.software-developers-home.de

      Kommentar


      • #4
        hm.... pack könnte dir eventuell helfen, ansonstens selbst eine Funktion dafür schreiben

        Kommentar


        • #5
          den datentyp byte gibt es in php eigentlich nicht. auch sonst hat php es nicht so mit datentypen.

          zum letzten post:
          PHP-Code:
          $str "3EisFuerHannah";
          $arr = array();

          for(
          $i 0$i<strlen($str); $i++)
          {
             
          $arr[$i] = ord($str{$i});

          so kommst du an die dezimalen werte der unicode-schlüssel (51, 69, 105 etc.) der einzelnen symbole. reicht es dir für die weitere arbeit?

          Kommentar


          • #6
            PHP-Code:
            $s '3EisFuerHannah';

            $u mb_convert_encoding($s'UTF-16LE');
            // alternativ:
            // $u = iconv('{aktuelle Kodierung}', 'UTF-16LE', $s);

            $a = array();

            for(
            $i=0$l=mb_strlen($u); $i<$l$i++) {
               
            $a[] = ord($u{$i})." '".$u{$i}."'";
            }

            print_r($a); 
            Die beiden letzten Zeichen/vier Array-Einträge fehlen dabei noch - das dürfte aber daran liegen, dass du uns ein paar Zeichen am Ende deines Teststring verschwiegen hast ...
            I don't believe in rebirth. Actually, I never did in my whole lives.

            Kommentar


            • #7
              Das sieht schon sehr gut aus. Vielen Dank.

              Die Länge sollte mit 32 stimmen. (Ist in C# auch so ....)

              Eigenartigerweise bekomme ich in der Zeile:

              PHP-Code:
              $decrypted mcrypt_decrypt(MCRYPT_RIJNDAEL_256$keyTemp$decodedMCRYPT_MODE_ECB$ivTemp); 
              immer noch die Fehlermeldung:
              mcrypt_decrypt() [<a href='function.mcrypt-decrypt'>function.mcrypt-decrypt</a>]: The IV parameter must be as long as the blocksize in ....
              www.software-developers-home.de

              Kommentar


              • #8
                Nachwievor hänge ich an dieser Zeile.

                Gibt es irgendwen, der dort mal genaud raufschauen könnte? Ich denke, es ist sind nur 1 oder 2 Zeilen die nicht stimmen. Falls jemand sich die Mühe machen möchte, würd ich auch den echten Quellcode zur Verfügung stellen.

                Gute Geister können mich hier erreichen: toXChris@gmx.de


                frustriert von PHP,
                Chris
                www.software-developers-home.de

                Kommentar

                Lädt...
                X