Wie kann man mcrypt_decrypt ersetzen

Hallo,

bei meinen Tests bin auf das Auslesecript der Buderus KM200 gestoßen, wo mcrypt_decrypt benutzt wird.

function km200_Decrypt( $decryptData ) 
{ 
    $decrypt = (
        mcrypt_decrypt( 
            MCRYPT_RIJNDAEL_128, 
            km200_crypt_key_private, 
            base64_decode( $decryptData ), 
            MCRYPT_MODE_ECB, 
            '' 
        ) 
    ); 

Bislang habe ich keinen Weg gefunden dies zu ersetzen. Laut php.net könnte openssl_encrypt funktionieren. Ich scheitere jedoch schon daran, dass ich nicht weiß, welche Parameter einzusetzen sind.

Gruß
Hans

Ich würde das erst mal so lassen und erst mal abwarten und Tee trinken. Wenn irgendwann in Zukunft dann mal IP-Symcon PHP 7 nutzt kannst Du das mit libsodium ersetzten.

Hallo Fonzo,

leider würde dein Vorschlag bedeuten, dass ich meine Bemühungen hinsichtlich der Prüfung der Scripte auf 5.0 Tauglichkeit einstellen müsste, da ich nicht mehr an die Daten meiner Buderus Therme kommen würde :eek:

Da ich logischweise nicht der Einzige bin der mit diesem Problem zu kämpfen hat, habe ich im Netz einige Hinweise gefunden, wobei die schlechte Dokumentierung bemängelt wird.

Eigentlich wollte ich alle meine Skripte und Module auf 5.0 Verträglichkeit testen und hier dokumentieren, was mir dabei so aufgefallen ist. Ich denke mal, dass dein Harmony Modul schon fit ist für 5.0 oder? :smiley:

Gruß
Hans

Wenn du die 5.0 bereits testest kannst du dir bereits die sodium_* Funktionen anschauen. PHP: Sodium - Manual

paresy

Hallo paresy,

danke für den Hinweis :slight_smile: Jetzt verstehe ich auch warum die Doku bemängelt wird :smiley:

Warnung
Diese Funktion ist bis jetzt nicht dokumentiert. Es steht nur die Liste der Argumente zur Verfügung.

Gruß
Hans

Hallo,

nachdem ich gestern viele Stunden damit verbracht habe einen Ersatz für mcrypt_decrypt bzgl. des Auslesescriptes für die Buderus KM200 zu finden, werde ich das Ganze jetzt erst mal beenden.

Mit sodium kann man nichts anfangen da im Moment undokumentiert und man findet auch nichts zu MCRYPT_RIJNDAEL_128.

Daraufhin habe ich aufgrund diverser Beiträge in stackoverflow es mit OpenSSL versucht. Angeblich soll MCRYPT_RIJNDAEL_128 aes_256_ecb entsprechen https://stackoverflow.com/questions/45218465/mcrypt-rijndael-128-to-openssl-aes-128-ecb-conversion. Aber auch das führte in allen möglichen Varianten nicht zum Erfolg zumal an diversen Stellen der Hinweis stand, dass man ecb nicht verwenden soll - warum auch immer :mad:

Letztendlich erhielt ich wie viele andere Nutzer auch als Ergebnis, dass bei decrypt false zurückgegeben wurde.

Damit muss ich den Einsatz der Version 5 wohl erst einmal vergessen und abwarten was da noch so kommt :wink:

Gruß
Hans

Ganz so schlimm würde ich das nicht sehen aber z.b. Broadlink oder auch andere Module nutzten mcrypt_decrypt auch müssen also auch umgestellt werden, ich denke da wird man mit sodium schon zu einer Lösung kommen, beschäftigt habe ich mich damit aber noch nicht.

Poste mal ein Beispiel mit mcrypt und HEX Daten, welche eine korrektest Ergebnis liefern. Dann können alle mal spielen und eine Lösung suchen :slight_smile:

paresy

IPSymconBroadlinkRM/Broadlink.php at master · Wolbolar/IPSymconBroadlinkRM · GitHub

nutzt mcrypt_encrypt und mcrypt_decrypt.

kannst Dir so ein Ding für 10 Euro zum „spielen“ holen oder „Trockenübung“ mit der Funktion
Send_data
machen.

Die ruft send_packet auf und hier muss für $aes dann ein sinnvoller Wert rauskommen mit Sodium so wie jetzt mit mcrypt_encrypt.

Hallo paresy,

schön, wenn auch andere spielen wollen :slight_smile:

Das Problem ist, dass die gesamte Verschlüsselung sich auf das KM200 bezieht, welches abgefragt wird siehe https://www.symcon.de/forum/threads/25103-Buderus-Logamatic-Web-KM200/page4?highlight=bosch

Ich habe jetzt meinen Schlüssel geändert und das Script um die Buderus Abfrage bereinigt so dass dieses übrig bleibt:

https://www.symcon.de/forum/threads/25103-Buderus-Logamatic-Web-KM200/page4?highlight=bosch

define( "km200_crypt_key_private", hex2bin( '123bcb1c6829fc181d29359137a73e188d5e14ed99d48785f16de3ab87b4c826' ), true );

$encryptData = "Dies ist ein Test";
$decryptData = km200_Encrypt( $encryptData );
var_dump($decryptData);
$result = km200_Decrypt( $decryptData );
echo $result;

function km200_Encrypt( $encryptData )
{
	// add PKCS #7 padding
	$blocksize = mcrypt_get_block_size(
		MCRYPT_RIJNDAEL_128,
		MCRYPT_MODE_ECB
	);
	$encrypt_padchar = $blocksize - ( strlen( $encryptData ) % $blocksize );
	$encryptData .= str_repeat( chr( $encrypt_padchar ), $encrypt_padchar );
	// encrypt
	return base64_encode(
		mcrypt_encrypt(
			MCRYPT_RIJNDAEL_128,
			km200_crypt_key_private,
			$encryptData,
			MCRYPT_MODE_ECB,
			''
		)
	);
}

function km200_Decrypt( $decryptData )
{
	$decrypt = (mcrypt_decrypt( MCRYPT_RIJNDAEL_128, km200_crypt_key_private, base64_decode($decryptData), MCRYPT_MODE_ECB, '' ) );
	// remove zero padding
	$decrypt = rtrim( $decrypt, "\x00" );
	// remove PKCS #7 padding
	$decrypt_len = strlen( $decrypt );
	$decrypt_padchar = ord( $decrypt[ $decrypt_len - 1 ] );
	for ( $i = 0; $i < $decrypt_padchar ; $i++ )
	{
		if ( $decrypt_padchar != ord( $decrypt[$decrypt_len - $i - 1] ) )
		break;
	}
	if ( $i != $decrypt_padchar )
		return $decrypt;
	else
		return substr(
			$decrypt,
			0,
			$decrypt_len - $decrypt_padchar
		);
}

Die encrypt Anweisung wird bei dem KM200 benötigt, um neue Daten zu setzen. Ich persönlich könnte darauf verzichten, da das sehr selten vorkommt und über eine App gemacht werden kann.

Wichtig wäre für Tests mit V 5, dass man die Daten aus der Therme zurückbekommt. In meiner Heizungssteuerung für die Homematic HT und WT nutze ich u. a. die Außentemperatur die von der Therme geliefert wird.

Dies ist der Grund dafür, dass die Nutzer dieses Scriptes Ersatz benötigen.

Gruß
Hans

Ich hatte das Problem ja auch aber war es nicht so, das der Autor für die Schlüsselerzeugung auch extern etwas anbot?

Gesendet von iPhone mit Tapatalk

Hallo Boui,

die Schlüsselerzeugung ist nicht das Problem. Jeder der das Script benutzt hat sich ja einen Schlüssel generiert. Hier geht es darum, dass die Befehle mycryp_decrpyt in PHP 7 nicht mehr vorhanden sind. Mit anderen Worten: du kannst deine Therme nicht mehr auslesen :eek:

Gruß
Hans

Schau mal, ob das passt :wink:


<?php


define( "km200_crypt_key_private", hex2bin( '123bcb1c6829fc181d29359137a73e188d5e14ed99d48785f16de3ab87b4c826' ), true ); 


$encryptData = "Dies ist ein Test"; 
$decryptData = km200_Encrypt( $encryptData ); 
var_dump($decryptData); 
$result = km200_Decrypt( $decryptData ); 
echo $result; 


function km200_Encrypt( $encryptData ) 
{ 
    $blocksize = 16;
    $encrypt_padchar = $blocksize - ( strlen( $encryptData ) % $blocksize ); 
    $encryptData .= str_repeat( chr( $encrypt_padchar ), $encrypt_padchar ); 
    
    return base64_encode(
        openssl_encrypt(
            $encryptData,
            "aes-256-ecb",
            km200_crypt_key_private,
            OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
        )
    );


}


function km200_Decrypt( $decryptData ) 
{ 
    $decrypt = openssl_decrypt( 
        base64_decode( $decryptData ),
        "aes-256-ecb",
        km200_crypt_key_private,
        OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
    );
        
    // remove zero padding 
    $decrypt = rtrim( $decrypt, "\x00" ); 
    // remove PKCS #7 padding 
    $decrypt_len = strlen( $decrypt ); 
    $decrypt_padchar = ord( $decrypt[ $decrypt_len - 1 ] ); 
    for ( $i = 0; $i < $decrypt_padchar ; $i++ ) 
    { 
        if ( $decrypt_padchar != ord( $decrypt[$decrypt_len - $i - 1] ) ) 
        break; 
    } 
    if ( $i != $decrypt_padchar ) 
        return $decrypt; 
    else 
        return substr( 
            $decrypt, 
            0, 
            $decrypt_len - $decrypt_padchar 
        ); 
}

paresy

PS: Der Entscheidende Tipp kam von hier: https://stackoverflow.com/a/45991620

Und wie würde man


function aes128_cbc_encrypt($key, $data, $iv) {
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
}
function aes128_cbc_decrypt($key, $data, $iv) {
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
}


ersetzten? Macht den openssl_encrypt im Prinzip das Gleiche? Dann könnte man das ja jetzt schon ersetzten wenn das ein Ersatz ist und dann sowohl in der jetzigen IP-Symcon Version also auch ab IPS 5 weiterhin verwenden.

Hallo paresy,

ja, das passt :slight_smile: Ich konnte allerdings nur das Auslesen testen (decrypt), da das Programm für die Schaltzeiten mit zahlreichen Fehlermeldungen crasht mit deprecated, Array to string conversion usw. Da diese Scripte sehr umfangreich sind werde ich davon erst mal die Finger lassen und meine weiteren Scripte auf php 7 Verträglichkeit testen.

Durch den Link bin ich ja auf den Trip gekommen, dass MCRYPT_RIJNDAEL_128 aes_256_ecb entspricht. Nur dann habe ich irgendwelche Formfehler in den Openssl Anweisungen begangen :banghead: Knapp daneben ist eben auch vorbei :slight_smile:

Vielen Dank für die Unterstützung.

Gruß
Hans

Danke für den Hinweis und die schnelle Lösung von paresy.

Mir ist das gar nicht augefallen, dass da Fehler kamen, weil ich das so nicht in der Überwachung habe.
Lesen funktioniert jedenfalls.

Nachtrag: Schreiben funktioniert auch. :slight_smile:

Schön das zumindest für ecb eine Lösung da ist. Hat jemand vielleicht noch einen Tipp ob man auch eine alternativen Weg für CBC finden kann?


mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); 

Guten Morgen Fonzo und Boui,

bei meinen Recherchen vorgestern fand ich u. a. dies https://www.php.de/forum/webentwicklung/php-fortgeschrittene/1501615-openssl-|-mcrypt-rijndael_128-aus-mcrypt-in-openssl-entschlüsseln Vielleicht löst das dein Problem Fonzo :wink:

Dann kann ich mir für das Schreiben ja ein Testscript ersparen :slight_smile:

Gruß
Hans

Danke für den Link da muss man ja erst mal drauf kommen. Ich habe damit getestet mir ist aber immer noch unklar wie man was verschlüsselt ganz geht aus dem Link leider nicht so hervor, hat da jemand eine Idee?

Also Entschlüsseln habe ich mal entsprechend dem Link probiert


$key = 'vGbPVqMFLeFPyFZqcxWeK2C65ANDG884'; // Nur Testkeys ;)
$iv = 'wC7xjdTG8hKy9uXx'; // ............... Nur Testkeys ;)
$plain = 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern';
$plain64 = base64_encode($plain);

/* ~-- ENCRYPT -----------~ */

$cipher = @mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
@mcrypt_generic_init($cipher, $key, $iv);
$encrypted = @mcrypt_generic($cipher, $plain64);
@mcrypt_generic_deinit($cipher);
@mcrypt_module_close($cipher);


/* ~-- DECRYPT -----------~ */
$decrypted = openssl_decrypt(
    base64_encode($encrypted),
    'AES-256-CBC',
    $key,
    OPENSSL_ZERO_PADDING,
    $iv
);

var_dump(base64_decode($decrypted));

Jetzt habe ich das mit dem Verschlüsseln mal so probiert da kommt aber leider nur Murks raus, für Vorschläge bin ich offen


$key = 'vGbPVqMFLeFPyFZqcxWeK2C65ANDG884'; // Nur Testkeys ;)
$iv = 'wC7xjdTG8hKy9uXx'; // ............... Nur Testkeys ;)
$plain = 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern';
$plain64 = base64_encode($plain);
$data = $plain64;
/* ~-- ENCRYPT -----------~ */
$encrypted = base64_encode(
        openssl_encrypt(
            $data,
            'AES-256-CBC',
            $key,
            OPENSSL_ZERO_PADDING,
            $iv
        )
    );


/* ~-- DECRYPT -----------~ */
$decrypted = openssl_decrypt(
    base64_encode($encrypted),
    'AES-256-CBC',
    $key,
    OPENSSL_ZERO_PADDING,
    $iv
);

var_dump(base64_decode($decrypted));

Habe das jetzt hier erfolgreich umgesetzt.
Xiaomi Smart Home Gateway - Seite 16
Allerdings mit Rawdaten.
Keine Ahnung wie wo du bei deinen Daten da was mit base64 noch machst.
Michael