php.de

Zurück   php.de > Webentwicklung > PHP Einsteiger

PHP Einsteiger PHP Problemlösungen für Spracheinsteiger
Archive: 2004, 2004/2, 2005, 2005/2, 2006, 2007, 2008, 2009, 2010,

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 14.12.2011, 17:52  
sph
Neuer Benutzer
 
Registriert seit: 14.12.2011
Beiträge: 16
PHP-Kenntnisse:
Anfänger
sph befindet sich auf einem aufstrebenden Ast
Standard [Erledigt] mcrypt: Decrypt-Problem bei wiederholtem Aufruf

Hallo Community,

mich plagt ein PHP-Problem das ich mir nicht erklären kann, darum meine Registrierung hier. Ich hoffe hier finden sich ein paar mcrypt-kundige Personen die mir auf die Sprünge helfen können. Da ich meine Frage nicht wirklich als Anfänger- oder Expertenproblem einordnen kann hab ich mal dieses Forum gewählt.


Vorhaben:
Ich möchte in zwei Einzelschritten Informationen (= Daten, Strings) verschlüsseln und entschlüsseln, da es sich dabei um sehr wenige Daten handelt dient mir eine generierte Datei als Speicher für die verschlüsselten Infos. Also:

1: Anwendung_A verschlüsselt angegebene Daten, erzeugt eine Datei und schreibt den verschlüsselten String in diese.

2: Anwendung_B liest diese Datei, entschlüsselt die Daten und zeigt sie an.

Mit meinen PHP-Kenntnissen hab ich das soweit auch umsetzen können, php.net, O'Reillys "PHP in a nutshell" und nicht zuletzt Google sei dank


Ergänzende Informationen:
Mein Vorhaben findet offline statt - ganz ohne Server oder installiertes PHP, als Stichworte sollten "bamcompile" und "winbinder" genügen. Ich hab großen Gefallen dran gefunden Standalone-Win32-Anwendungen in PHP zu schreiben, die hier genannten Anwendungen sind also zwei kleine EXE-Dateien.

Leider sieht es nicht so aus als würde bamcompile noch weiterentwickelt werden, ich muss mich also mit der PHP-Version 4.4.4 begnügen. Laut phpinfo() kommt bei mir mcrypt >= 2.4.x zum Einsatz.


Das Problem:
Meine Anwendung_A generiert die Datei mit den verschlüsselten Informationen reibungslos.

Anwendung_B erlaubt es mir eine Datei auszuwählen und sofern der grobe Aufbau der Datei meinen Vorgaben entspricht (es müssen 12 einzelne "Strings" vorhanden sein) wird der Inhalt entschlüsselt und dargestellt - auch das funktioniert.

Das wirklich merkwürdige und mir völlig unerklärliche Verhalten tritt dann auf wenn ich die bereits ausgewählte Datei nochmals erneut auswähle - ohne meine Anwendung_B zu beenden. Dann werden nämlich nur 9 von 12 vorhandenen Datenteilen korrekt entschlüsselt - die verbleibenden 3 Einträge bleiben verschlüsselt, jedenfalls werden mir nur kryptische Zeichen angezeigt.

Wenn ich meine Anwendung_B schließe, sie erneut starte und dann - erstmalig - wieder meine verschlüsselte Datei auswähle, so klappt auch das Entschlüsseln wieder anstandslos.



Ich verstehe dass eine sichere Ver- und Entschlüsselung nicht gerade ein einfaches Thema ist. Ich verstehe auch dass beim Erzeugen eines mcrypt-objekts u. a. zufallsgenerierte Werte eine Rolle spielen und es daher bei unsachgemäßer Verwendung zu Problemen kommen kann (die ich anfangs auch zuhauf hatte...). Ich verstehe auch dass ein Fehler in der Methode dazu führen kann dass weder brauchbar Ver- noch Entschlüsselt werden kann.

Was ich allerdings nicht verstehe ist wie es dazu kommen kann dass nur 3/4 meiner verschlüsselten Daten korrekt entschlüsselt werden - und der Rest nicht...?!

-> alle Daten befinden sich in der selben Datei
-> alle Daten werden mit der selben Cipher ver- und entschlüsselt
-> alle Daten werden mit dem selben Passwort ver- und entschlüsselt
-> beim Entschlüsseln der Daten werden keinerlei Änderungen an der Datei vorgenommen


...also falls irgendjemand meinen Denkfehler sieht, weiß was da schiefläuft oder mir sonstwie weiterhelfen kann - danke bereits im vorraus!

Anschließend folgt noch der verwendete Code und Screenshots der Ausgabe, danke fürs lesen, happy coding,

greets,


sph




Code:
Nachdem ich in Anwendung_B eine Datei ausgewählt habe wird diese einer Funktion übergeben, die dann die restliche Arbeit erledigt. Rückgabewert der Funktion ist ein array mit meinen 12 entschlüsselten Datenwerten. Bei einer erneuten Dateiauswahl wird also auch lediglich diese Funktion ein zweites mal ausgeführt, was dann zum beschriebenen Problem führt.

-> hier wird ein Dateiauswahl-Dialog gestartet (winbinder), Rückgabewert ist die gewählte Datei einschließlich kompletter Pfadangabe. Anschließend folgt der Funktionsaufruf.
PHP-Code:
$file wb_sys_dlg_open($window$title$file_filter$startpath);

if (
$file){                        

    if(
$fc udf_validate_file($file)){
    
        
// display decrypted content
        
wb_set_text($data_1_value$fc[0]);
        
wb_set_text($data_2_value$fc[1]);
        
wb_set_text($data_3_value$fc[2]);
        
// ...and so on 

-> die Funktion udf_validate_file($file)
PHP-Code:
function udf_validate_file($file){
    
    
// check if $file really does exist,
    // maybe not really needed...
    
if(file_exists($file)){
        
        
// unset used vars
        
unset($fc);
        unset(
$dc);
        unset(
$value);
        unset(
$pw);
        unset(
$td);
        unset(
$iv);
        unset(
$ks);
        unset(
$key);
        
        
        
// the data was encrypted using RIJNDAEL_256,
        // this means the encrypted data could contain
        // special characters like \r or \n
        //
        // to handle this, i wrote all 12 data parts
        // as one single string to the file, separated 
        // by a defined set of characters
        //
        // now, lets get my 12 data parts back in 
        // an array called $value
        
$fc           file($file);
        
$file_str     implode(""$fc);
        
$separator    CFG_SEPARATOR;     // there is a config-file for such things...
        
$value        explode($separator$file_str);

        
        
// check if we really do have 12 data parts
        
if (count($value) == 12){
        
        
            
// the used password is of course not just 
            // just stored here, it's generated from the file
            //
            // to shorten the code and for testing purposes
            // i'll skip that and just use a fixed $pw,
            // of course for en- and decryption
            
$pw '123';
                        
            
            
// init the crypt module
            // 
            // to be honest, this code is just copied from
            // O'REILLYs book "PHP in a nutshell" and
            // modified to my needs
            
srand((double)microtime()*1000000);
            
$td        mcrypt_module_open(MCRYPT_RIJNDAEL_256''MCRYPT_MODE_CFB'');
            
$iv        mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
            
$ks        mcrypt_enc_get_key_size($td);
            
$key       substr(sha1($pw), 0$ks);
            
            
// decrypt data
            //
            // i promise i'll use better arrays and loops
            // to do this...
            
mcrypt_generic_init($td$key$iv);
            
            
$dc[]             = mdecrypt_generic($td$value[0]);
            
$dc[]             = mdecrypt_generic($td$value[1]);
            
$dc[]             = mdecrypt_generic($td$value[2]);
            
$dc[]             = mdecrypt_generic($td$value[3]);
            
$dc[]             = mdecrypt_generic($td$value[4]);
            
$dc[]             = mdecrypt_generic($td$value[5]);
            
$dc[]             = mdecrypt_generic($td$value[6]);
            
$dc[]             = mdecrypt_generic($td$value[7]);
            
$dc[]             = mdecrypt_generic($td$value[8]);
            
$dc[]             = mdecrypt_generic($td$value[9]);
            
$dc[]             = mdecrypt_generic($td$value[10]);
            
$dc[]             = mdecrypt_generic($td$value[11]);
                        
            
mcrypt_generic_deinit($td);
            
mcrypt_module_close($td);    

            return 
$dc;
        } else {
            return 
FALSE;
        }
    } else {
        return 
FALSE;
    }


Screenshots:
Verschlüsselt wurden die Strings "Teststring 1 - 123abc" bis "Teststring 12 - 123abc". Verschlüsselt sieht das ganze dann so aus:
Code:
�*Õ‰â½FGœgpê"©‡PÀUr'!#-$#$-#pÂéD�*?\Ü]Ù�*2õP‡U@-^»#-$#$-#œÕ¢`P
4h~,_dF\Ê™Yð#-$#$-#§sQÒŸÏy¥‚ý¢Ã°hýýÛÞ#-$#$-#)
(Hinweis: durch Formatierungen des Forums kann es zu Abweichungen mit dem realen Ergebnis kommen)


Werden die Daten das erste mal entschlüsselt erhalte ich die gewünschte, korrekte Ausgabe:




Wähle ich die Datei erneut zum entschlüsseln aus erhalte ich folgendes:

(...der letzte Wert ist bei diesem Beispiel nun auch wieder korrekt entschlüsselt worden - das war bei vorhergehenden Tests nicht der Fall. Ich begreifs nicht...)




Nachtrag:
Das sollte ich vielleicht noch erwähnen: bei den kryptisch dargestellten Zeichen handelt es sich nicht um die original verschlüsselten Daten. Ausserdem ändern sich die dargestellten Zeichen mit jeder Neuauswahl der Datei, was allerdings schonmal korrekt entschlüsselt wurde bleibt scheinbar erhalten.



//EOF

Geändert von sph (14.12.2011 um 18:37 Uhr).
sph ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 14.12.2011, 19:28  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.987
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Mir scheint es relativ naheliegend, dass das Problem hier begründet liegt:

PHP-Code:
$value        explode($separator$file_str); 
Welchen Seperator kannst Du garantieren, der nicht Teil des Encryption-Strings sein kann?
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 14.12.2011, 20:03  
sph
Neuer Benutzer
 
Registriert seit: 14.12.2011
Beiträge: 16
PHP-Kenntnisse:
Anfänger
sph befindet sich auf einem aufstrebenden Ast
Standard

Hi,

danke für deine Antwort!

Zitat:
Zitat von nikosch Beitrag anzeigen
Mir scheint es relativ naheliegend, dass das Problem hier begründet liegt:

PHP-Code:
$value        explode($separator$file_str); 
Welchen Seperator kannst Du garantieren, der nicht Teil des Encryption-Strings sein kann?

Guter Einwand, darüber hab ich mir bereits Gedanken gemacht.

Bei der verwendeten Verschlüsselung werden, wie im Beispiel zu sehen, kaum normale Buchstaben erzeugt - sogesehen könnte sich schon "abcd" als Separator eignen.

Ich hab mal beobachtet was die Verschlüsselung so ausspuckt und verwende aktuell diesen Separator: "#-$#$-#" - siehe Codebeispiel. Der fällt im Zahlengewirr nicht wirklich auf und wurde bislang noch nicht durch die Verschlüsselung generiert.


Aber der Springende Punkt ist - denk jedenfalls ich - ein anderer:
Wäre der Separator ein Problem, dann dürfte meine Methode der Stringzerlegung und die nachfolgende Entschlüsselung garnicht funktionieren. Tut sie aber.

Zwar nur beim erstmaligen Aufruf, aber da klappts perfekt.


Kann ich den Separator als Ursache nun ausschließen, oder gibts da noch was zu berücksichtigen?


Grüße,


sph
sph ist offline   Mit Zitat antworten
Alt 15.12.2011, 01:32  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.267
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Versuch es mal mit base64 und/oder serialize, dann kannst du dir das explode() sparen. Der Code sieht, wenn ich das mit meinem Uraltkodierskript vergleiche, richtig aus. Lass das srand() und sha1() Zeug mal weg, das macht deine Anwendung kein bisschen sicherer und ist nur eine potentielle Fehlerquelle. Was mich vielmehr stutzig macht ist, dass dein 11. String halb-dekodiert worden zu sein scheint. Das kann eigentlich nicht sein. Benutz als Modus auch mal ECB, ist zwar nicht sicher, aber dafuer einfacher und damit wieder etwas besser zu debuggen.

Noch zwei Ansaetze:
- Schau dir das Changelog seit PHP 4.4 mal an, ob da etwas zu mcrypt und Bugs zu finden ist
- Lass das PHP-Skript mal Standalone ueber die php.exe laufen
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Alt 15.12.2011, 01:40  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.987
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Stimmt, ist mir gar nicht aufgefallen. Ich kenn mich in dem Thema nicht aus, aber das bringt mich auf eine andere Fährte:
Zitat:
The decryption handle should always be initialized with mcrypt_generic_init() with a key and an IV before calling this function. Where the encryption is done, you should free the encryption buffers by calling mcrypt_generic_deinit().
Könnte das ein Pufferproblem sein und man muss init() und deinit() bei jedem Lauf ausführen? Nur so ein Gedanke.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 15.12.2011, 01:56  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.267
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Was mir auch aufgefallen ist, du zauberst den Initialisierungsvektor beim Dekodieren scheinbar aus dem Hut, den musst du aber - dachte ich zumindest - eigentlich mit in deinen kodierten String uebergeben.

PHP-Code:
    public function encrypt($plaintext
    { 
        
// ..
        
return base64_encode($iv $crypttext); 
    } 

    public function 
decrypt($crypttext
    { 
        
$crypttext base64_decode($crypttext);
        
// ..
        
$iv substr($crypttext0$ivsize); 
        
$crypttext substr($crypttext$ivsize); 
        
// ..
        
return $plaintext
    } 
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Alt 15.12.2011, 09:36  
sph
Neuer Benutzer
 
Registriert seit: 14.12.2011
Beiträge: 16
PHP-Kenntnisse:
Anfänger
sph befindet sich auf einem aufstrebenden Ast
Standard

Hallo,

ihr seid die besten - habs!


Der Reihe nach:
Zitat:
Zitat von nikosch Beitrag anzeigen
Könnte das ein Pufferproblem sein und man muss init() und deinit() bei jedem Lauf ausführen?
Ich weiß was du meinst und find auch dass man das leicht missverstehen kann, so wie das beschrieben ist. Ich habs so verstanden: zwischen mcrypt() und mdecrypt() muss man init/deinit anwenden - wenn man nur eine der beiden Methoden nutzt (also z. B. nur mcrypt) kann man das auch innerhalb der selben Initialisierung tun. Hab ich jedenfalls so gemacht, hat geklappt - und daran lags auch nicht. Trotzdem danke!



Zitat:
Zitat von Chriz Beitrag anzeigen
Was mir auch aufgefallen ist, du zauberst den Initialisierungsvektor beim Dekodieren scheinbar aus dem Hut, den musst du aber - dachte ich zumindest - eigentlich mit in deinen kodierten String uebergeben.
BINGO - genau das wars, du hast vollkommen richtig gedacht!

Ursprünglich hab ich das auch so gelesen, dass man den IV am besten direkt mit den Daten zum entschlüsseln übergibt. Als ich dann aber damit begonnen hab zu ver- und entschlüsseln hab ich das Anfangs garnicht berücksichtigt - und festgestellt dass es ja trotzdem klappt, daraus folgerte ich dann fälschlicherweise "braucht man wohl nicht so unbedingt". Ich hab ne ganze Zeit lang auch nur das Verhalten nach ner einmaligen Ausführung geprüft, und das hat ja immer gepasst...

Erst später wollte ich dann kodierte Daten mehrmals entschlüsseln - tadaa, Problem.


Ich hab also jetzt den beim verschlüsseln generierten IV mit bei den Daten hinterlegt, von dort les ich ihn beim entschlüsseln ein - und schon klappt das auch mehrmals hintereinander!

Und danke für den base64-Tip, is ne gute Idee - das macht die Sache nicht nur einfacher, sondernd auch "Augenfreundlicher".



So ganz verstanden hab ich das allerdings immer noch nicht. Wenn unbedingt der beim generieren erzeugte IV notwendig ist - warum klappts dann auch ohne? Wenn ohne Übergabe des ursprünglichen IV ein neuer IV generiert wird, warum funktioniert der dann überhaupt? Und warum funktioniert er bei mehrmaligem Aufruf, also bei mehrmaliger neugenerierung, nurnoch "teilweise"..? Bei manchen Dingen denk ich mir auch nur
Zitat:
Zitat von Chriz Beitrag anzeigen
Das kann eigentlich nicht sein.

Danke fürs mitgrübeln,

Grüße!
sph ist offline   Mit Zitat antworten
Alt 15.12.2011, 22:48  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.267
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Klar gern, find das Thema interessant.

Wenn ich damals in Kryptographie richtig aufgepasst habe, ist der Initialvektor ja ein Zufallsstring (MCRYPT_RAND), der als erster Kodierblock herhält. Die nachfolgenden Kodierblöcke (32 Byte?) werden dann je nach Modus (CFB) mit dem Vorgänger "vermanscht" (ECB macht das nicht; selbes PW = selber verschlüsselter String). Wenn der Initialvektor jetzt falsch ist, ist es eigentlich () unmöglich, dass du deinen Crypttext wieder in den (fast) richtigen Plaintext verwandeln kannst, weil ja von Anfang an eine falsche Grundlage benutzt wird.

Was sein könnte ist, dass MCRYPT_RAND buggy ist oder du einen so ungünstigen - da sich wiederholenden und dazu noch kurzen - Kodiertext gewählt hast, dass der Initialvektor fast keinen Einfluss genommen hat. Wäre aber dann kein gutes Zeichen für den Algorithmus.

Wie auch immer, freut mich wenns klappt.
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Problem beim Captcha Aufruf in einem Formular, nur das Bild wird angezeigt litterauspirna PHP Tipps 2009 19 11.05.2009 15:25
[Erledigt] Problem: PHP Selbe Datei mehr als 1 Mal soulan PHP Tipps 2008 13 28.11.2008 22:51
Problem mit swfobjects R4v3r JavaScript, Ajax und mehr 8 21.09.2008 14:17
Problem beim Aufruf einer Funktion elwood PHP Tipps 2008 6 30.08.2007 12:54
MCRYPT Problem solitaer PHP-Fortgeschrittene 2 17.01.2006 10:58
Problem mit Aufruf von mkisofs PHP-Fortgeschrittene 1 21.08.2005 13:04

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
mcrypt_decrypt probleme, php mcrypt_decrypt, mcrypt_decrypt formular, mcrypt verschlüsselt nicht richtig, \mcrypt decrypt\, mcrypt_ decrypt

Alle Zeitangaben in WEZ +2. Es ist jetzt 16:39 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum