ASCII Zeichen in lesbaren Text umwandeln?

Ich habe einen Wert nehmen wir z.B.


$string = "0x66 0x6F 0x6F 0x62 0x61 0x72";

diesen möchte ich in einen lesbaren Text umwandeln.

Gibt es da eine fertige PHP Funktion für bzw. hat jemand mal einen Tipp wie das funktioniert?

Ich stelle deine Daten in Frage.
ASCII ist ja lesbarer Text.
Was du da hast ist eine Mischung aus Hexadezimaler Schreibweise und Leerzeichen.
Wie kommen die Daten wirklich rein ?
Bzw. woher hast du diesen String.

Michael

Die ursprünglichen Daten kommen über einen UDP Socket und sind verschlüsselt. Das Packet muss zerlegt werden und dann entschlüsselt. Als Ergebnis der Entschlüsselung kommt das oben raus. Der letzte Schritt wäre jetzt das dann noch so umzuwandeln das es auch lesbar ist.

Je nachdem welche Lib du nutzt, gibt es da Parameter für, dass du die Rohdaten erhalten möchtest.
Die sind dann lesbar.
Sonst… Quellcode zeigen :slight_smile:
Ich nutze ja z.B. auch die PTLS-Lib oder auch openssl und da bekomme ich auch jeden Fall nicht so einen ‚Quark‘. :wink:
Michael

Es wird in dem Fall Argon2i und ChaCha20-Poly1305 benutzt.

Das Problem ist, ich kann zwar den Code zerlegen


$message_raw = '0x66 0x6F 0x6F 0x62 0x61 0x72 0x31 0x30 0x32 0x20 0x20 0x20 0x20 0x20 0x5A 0x12 0xE4 0x13';
$message = explode(" ", $message_raw);

Dann bekomme ich aber einen String im Array.

PHP 5 ist das egal, da kann ich mit


$string_raw = "0x66 0x6F 0x6F 0x62 0x61 0x72";
$string = explode(" ", $string_raw);
 
$result =  fromAscii($string);
var_dump($result);

function fromAscii($string) {
    $result = '';
    foreach ($string as $code) {
        $result .= chr($code);
    };
    return $result;
}

was zurück geben, da kommt dann auch was raus (foobar).

Das Problem ist, dass dies mit PHP 7 nicht mehr funktioniert, da String nicht akzeptiert wird, hier wird Integer erwartet.
Bei exakt der gleichen Vorgehensweise


$string_raw = "0x66 0x6F 0x6F 0x62 0x61 0x72";
$string = explode(" ", $string_raw);
 
$result =  fromAscii($string);
var_dump($result);

function fromAscii($string) {
    $result = '';
	//var_dump($string);
    foreach ($string as $code) {
        $result .= chr($code);
    };
    return $result;
}

kommen also nur lauter Fehlermeldungen
Notice: A non well formed numeric value encountered in
und leider kein Ergebnis.

Die Frage ist also, wie wandele ich einen String „0x66“ so um, das die Funktion chr auch unter PHP 7 funktioniert?
Beziehungsweise es muss doch irgendeine simple Möglichkeit auch unter PHP 7 geben, bei einem String von „0x66“, das passende Zeichen auszugeben?

Welche Lib und Funktionen nutzt du?
Wie gesagt… Dein String ist Müll.
Ja… Man kann das aufwendig zerlegen. Aber warum?
Es gibt 100% einen einfacheren Weg.
Michael

Siehe oben, Argon2i und ChaCha20-Poly1305.

Weil ich momentan nicht weis wie man das sonst lösen soll, wenn es einen einfacheren Weg gibt, bin ich da natürlich für offen.

Ich habe mir jetzt so beholfen:


$string_raw = "0x66 0x6F 0x6F 0x62 0x61 0x72";
$string = explode(" ", $string_raw);
$result =  fromAscii($string);
var_dump($result);


function fromAscii($string) {
    $result = '';
    foreach ($string as $code) {
		$hex = str_replace("0x", "", $code);
		$dec = hexdec($hex);
        $result .= chr($dec);
    };
    return $result;
}

finde ich arg umständlich, aber es funktioniert wenigstes auch unter PHP 7.

Das will ich hoffen, Argon2i läuft momentan auch nicht mit IP-Symcon, aber das ist eine andere Baustelle.

Links wären toll… Habe mehrere gefunden.
Einige als Extension zum selber bauen.
Andere als pure PHP Lib…
Michael
PS: wenn ich das richtig sehe unterstützt libsodium auch ChaCha20/Poly1305*ebenso wie eine reine PHP Umsetzung auf GitHub.

Protecting passwords with Argon2 in PHP 7.2
keine Ahnung ob das dann immer Bestandteil von PHP 7.2 ist oder ob das separat ergänzt werden muss. Zu ChaCha habe ich noch nix richtig gefunden nur für C.

Argon2 ist doch aber nur um einen Hash eines Passworts zu erstellen.
Und ja, aber 7.2 Bestandteil von PHP.

Also so ohne Code ist es echt schwer zu erraten was du da machst :wink:
Das hier eine Alternative?

Michael

Noch mache ich nicht viel, weil ich Argon2i nicht zum Laufen bekomme. Es geht im Prinzip darum die Kommunikation bei Events auf UDP Socket umzustellen, dies ist ab Seite 14 in der API beschrieben. Step 1,2 ist ok, bei Step 3 und 4 hänge ich, und ab Step 5 ist das worüber wir hier gerade reden. Aber dazu muss ja erst mal Step 3 und Step 4 abgeschlossen sein. Wenn man die Daten aus Step 4 dann erst mal hat kann man die auch auswerten.

Es geht ja wahrscheinlich schon bei Step 1 los
momentan mache ich da Test und greife das nicht nicht vom UDP Socket ab sondern versuche erst mal nachzuvollziehen wie die Entschlüsselung geht.


// Step 1: You capture the following packet via UDP:
$payload = '0xDE 0xAD 0xBE 0x01 0x00 0x00 0x00 0x04 0x00 0x00 0x20 0x00 0x77 0x35 0x36 0xDC 0xC3 0x0E 0x2E 0x84 0x7E 0x0E 0x75 0x29 0xE2 0x34 0x60 0xCF 0xE3 0xFF 0xCC 0x52 0x3F 0x37 0xB2 0xF2 0xDC 0x1A 0x71 0x80 0xF2 0x9B 0x2E 0xA0 0x27 0xA9 0x82 0x41 0x9C 0xCE 0x45 0x9D 0x27 0x45 0x2E 0x42 0x14 0xBE 0x9C 0x74 0xE9 0x33 0x3A 0x21 0xDB 0x10 0x78 0xB9 0xF6 0x7B';

Anschließend Step 2


// Step 2: Split it up:
$data = explode(" ", $payload);
$ident = GetIdent($data); // lenght 3 Bytes, 0xDE 0xAD 0xBE
var_dump($ident);
$version = GetVersion($data); // lenght 1 Bytes, 0x01
var_dump($version);
$opslimit = GetOpsLimit($data);// lenght 4 Bytes, Used for password stretching with Argon2i.
var_dump($opslimit);
$memlimit = GetMemLimit($data);// lenght 4 Bytes, Used for password stretching with Argon2i.
var_dump($memlimit);

$salt = GetSalt($data);// lenght 16 Bytes, Used for password stretching with Argon2i.
var_dump($salt);
$nonce = GetNonce($data); // Used for encryption with ChaCha20-Poly1305
var_dump($nonce);
$ciphertext = GetCiphertext($data); // With ChaCha20-Poly1305 encrypted text which contains informations about the Event.
var_dump($ciphertext);

function GetIdent($data)
{
$ident = "";
for ($i = 0; $i <= 2; $i++) {
    $ident .= $data[$i]." ";
}
$ident = trim($ident);
return $ident;
}

function GetVersion($data)
{
$version = $data[3];
return $version;
}

function GetOpsLimit($data)
{
$opslimit = "";
for ($i = 4; $i <= 7; $i++) {
    $opslimit .= $data[$i]." ";
}
$opslimit = trim($opslimit);
return $opslimit;
}

function GetMemLimit($data)
{
$memlimit = "";
for ($i = 8; $i <= 11; $i++) {
    $memlimit .= $data[$i]." ";
}
$memlimit = trim($memlimit);
return $memlimit;
}

function GetSalt($data)
{
$salt = "";
for ($i = 12; $i <= 27; $i++) {
    $salt .= $data[$i]." ";
}
$salt = trim($salt);
return $salt;
}

function GetNonce($data)
{
$nonce = "";
for ($i = 28; $i <= 35; $i++) {
    $nonce .= $data[$i]." ";
}
$nonce = trim($nonce);
return $nonce;
}

function GetCiphertext($data)
{
$ciphertext = "";
for ($i = 36; $i <= 69; $i++) {
    $ciphertext .= $data[$i]." ";
}
$ciphertext = trim($ciphertext);
return $ciphertext;
}

Das wird nix… Das bekommst du doch gar nicht.
Du bekommst Rohdaten! :banghead::banghead:

Wenn du also OHNE Socket testen willst.
Sieht das in PHP so aus:


$payload = "\xDE\xAD\xBE\x01\x00\x00\x00\x04\x00\x00\x20\x00\x77\x35\x36\xDC\xC3\x0E\x2E\x84\x7E\x0E\x75\x29\xE2\x34\x60\xCF\xE3\xFF\xCC\x52\x3F\x37\xB2\xF2\xDC\x1A\x71\x80\xF2\x9B\x2E\xA0\x27\xA9\x82\x41\x9C\xCE\x45\x9D\x27\x45\x2E\x42\x14\xBE\x9C\x74\xE9\x33\x3A\x21\xDB\x10\x78\xB9\xF6\x7B";

Und dann steht da auch… libsodium.

Michael

Ja schon klar war ja auch nur zum testen, aber die Daten gleich so zu nehmen wie sie ankommen macht wohl Sinn.

Und ohne den ganzen Krempel von oben zu machen, wie zerlege ich das dann am besten?

Update:
Hier alles komplett, war jetzt nicht wirklich kompliziert :smiley:
Du musst nur auf den Anfang vom Paket prüfen (die ersten vier Byte) und aus dem Paket die einzelnen Teile mit substr rausscheinden.

Der Rest siehe hier:



$password = 'QzT3j'; // Nur die ersten 5 Byte des User Passwort !!!
$out_len = SODIUM_CRYPTO_SIGN_SEEDBYTES;
$key = sodium_crypto_pwhash(
    SODIUM_CRYPTO_SIGN_SEEDBYTES,
    $password,
    "\x77\x35\x36\xDC\xC3\x0E\x2E\x84\x7E\x0E\x75\x29\xE2\x34\x60\xCF", // SALT
    unpack("N","\x00\x00\x00\x04")[1], //OPSLIMIT
    unpack("N","\x00\x00\x20\x00")[1], //MEMLIMIT
	SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13 
);
echo 'Key für decrypt in HEX:'.PHP_EOL;
var_dump(bin2hex($key));

$ciphertext = "\xDC\x1A\x71\x80\xF2\x9B\x2E\xA0\x27\xA9\x82\x41\x9C\xCE\x45\x9D\x27\x45\x2E\x42\x14\xBE\x9C\x74\xE9\x33\x3A\x21\xDB\x10\x78\xB9\xF6\x7B";
$nonce ="\xE3\xFF\xCC\x52\x3F\x37\xB2\xF2";

$decrypted = sodium_crypto_aead_chacha20poly1305_decrypt ($ciphertext , null , $nonce , $key );
echo 'decrypted Payload in HEX:'.PHP_EOL;
var_dump(bin2hex($decrypted));
echo PHP_EOL;
echo 'decrypted Payload in RAW:'.PHP_EOL;
var_dump($decrypted);
echo PHP_EOL;
$INTERCOM_ID = substr($decrypted,0,6);
$EVENT = (int)trim(substr($decrypted,6,8));
$TIMESTAMP = unpack('N',substr($decrypted,14,4))[1];
echo 'INTERCOM_ID:'.PHP_EOL;
var_dump($INTERCOM_ID);
echo PHP_EOL;
echo 'EVENT:'.PHP_EOL;
var_dump($EVENT);
echo PHP_EOL;
echo 'TIMESTAMP:'.PHP_EOL;
var_dump($TIMESTAMP);
echo PHP_EOL;
echo 'TIMESTAMP to UTC:'.PHP_EOL;
echo gmdate('H:i:s d.m.Y', $TIMESTAMP).PHP_EOL.PHP_EOL;
echo 'TIMESTAMP to local:'.PHP_EOL;
echo date('H:i:s d.m.Y', $TIMESTAMP).PHP_EOL.PHP_EOL;
return;

Michael

PS: PHP 7.2 only !

Vielen herzlichen Dank, ich hätte mir da jetzt erst mal die Zähne ausgebissen.

Mag jetzt banal klingen aber wie mache ich das am dümmsten?
Wenn ich


$ident = substr($payload, 0, 12);
var_dump($ident);

mache bekomme ich


string(12) "ޭ¾

Wie sehe ich jetzt ob das der richtige Code ist bzw. wie vergleiche ich so was? Die var_dump Ausgabe finde ich sehr merkwürdig, gibt es eine Möglichkeit den Inhalt auch so darzustellen wie er eigentlich ist?

Vielen Dank, mir ist aufgefallen, dass es da anscheinend Unterschiede gibt wo man das ausführt. Auf einem Windows Rechner läuft das sauber durch. Bei einem Raspberry kommt
Uncaught SodiumException: maximum memory for the password hashing function is too low

Ist das so, das ein Raspberry da prinzipiell zu wenig Leistung bzw. Memory hat, oder gibt es eventuell eine Chance so was auch auf einem Raspberry zum Laufen zu bekommen?

Das ist so wie er ist… Da sind halt nicht darstellbare Zeichen. Völlig normal.
Wenn du es lesbar als Hex haben willst, nimm zum testen bin2hex (siehe mein Beispiel).
Aber mit diesen Daten nicht effektiv arbeiten. Als IPS-Modul macht die Console die Hex Darstellung bei Verwendung von SendDebug.

Keine Ahnung, Vergleich doch mal das memory limit auf beiden Systemen in der php.ini.
Michael