Pyhton Script in PHP portieren

Hallo zusammen,

ich würde gerne dieses Python Script in PHP portieren.
GitHub - hthiery/python-ps4: Python Libray for accessing Sony Playstation 4

Zur Zeit hänge ich an folgender Stelle:
python-ps4/connection.py at master · hthiery/python-ps4 · GitHub

    def _send_hello_request(self):
        fmt = Struct(
            'length' / Const(b'\x1c\x00\x00\x00'),
            'type' / Const(b'\x70\x63\x63\x6f'),
            'version' / Const(b'\x00\x00\x02\x00'),
            'dummy' / Padding(16),
        )

Struct gibt es ja so nicht in PHP, könnte mir evtl. jemand ein Beispiel geben, wie ich diese Funktion in PHP portieren könnte?
Wahrscheinlich ist es wirklich total einfach und ich sehe den Wald vor lauter Bäumen mal wieder nicht. :banghead:

Grüße,
Kai

Hi Kai!

War das nicht „pack“ und „unpack“ :confused:
PHP: pack - Manual

Grüße,
Chris

Hallo Chris,

ja, ist es. Aber ich bin gerade wirklich zu blöd das abzubilden … :banghead:

Grüße,
Kai

Nun klärt mich auf :wink:
Was hat Pack und unpack (Zahl zu bin und bin zu Zahl) mit einem Strukt zu tun?

Egal was die da machen, du brauchst doch eh nur die Strings als Konstanten.
const Name = „\x1c\x00\x00\x00“;
Entweder direkt in deinem Modul, oder als extra Klasse wie hier:
GHoma/GHomaTraits.php at 10a35d42206b90c68fbd1f8721ef1a7d0104cb1f · Nall-chan/GHoma · GitHub

Diese kann dann auch die restlichen Funktionen beinhalten, wie das zusammenstellen des Datenpaketen und versenden per PHP-Socket.
Michael

Okay, ich antworte mir selber mal, da ich die Funktion build in der Doku nicht wirklich gefunden habe :rolleyes:

Das Struct wird bei build tatsächlich in einen Byte-String zusammengesetzt. Dabei werden auch Datentypen von z.B. int konvertiert.

So etwas, auch gleich mit der passenden parse Funktion um wieder eine Datenpaket in ein Struct zu überführen, ist mir in IPS nicht bekannt.

Jedoch ist der Grundsätzliche Aufbau nicht sehr komplex.
Um die Verschlüsselten Pakete (nach dem Seed) zu empfangen wird es wohl nicht reichen. Wobei ich auch nicht sehe, dass das python Script damit irgendwas macht :confused:

Verschlüsseln fehlt auch, habe ich mir nicht weiter angesehen.

So kannst du aber ein empfangenes Paket zerlegen:

/*Struct(
            'length' / Const(b'\x1c\x00\x00\x00'),
            'type' / Const(b'\x70\x63\x63\x6f'),
            'version' / Const(b'\x00\x00\x02\x00'),
            'dummy' / Padding(16),
        )*/

$HelloRequest = "\x1c\x00\x00\x00\x70\x63\x63\x6f\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
// Das versenden


        // Paketaufbau
        // 4 Byte length
        // 4 Byte Typ
        // Rest ist Payload

        //Payload bei
          // Hello Request Typ = \x70\x63\x63\x6f
          // Payload 0-3 = 4 Byte Version
          // 16 nullbytes
        // bei
          // Hello Response
          // Payload 0-3 = 4 Byte Version
          // 4- 11 = 8 Bytes egal
          // 12- 27 = 16 Bytes Seed
          

//Empfangenes Paket parsen, hier habe ich mit unserem Request nur das zerschneiden des Paketes geübt :)
$Packet = $HelloRequest;

$Len = unpack('V',substr($Packet,0,4));
$Type = substr($Packet,4,4);
$Payload = substr($Packet,8);
var_dump($Len);
var_dump($Type);

switch ($Type)
{
    case "pcco": // oder "\x70\x63\x63\x6f" => Ist Hello Request
        // War nur zum testen, weil wir ja unseren Request nicht verarbeiten wollen, sondern die Antwort
    break;
    case "?????": // Hello Response, leider nicht dokumentiert. Das pyhton Script prüft auch die Empfangen Daten gar nicht, es schneidet nur den Seed raus.
                  // Wenn das reicht, dann braucht man das hier alles nicht :)
        $Seed = substr($Payload,12,16);
        /*
        def _recv_hello_request(self):
            fmt = Struct(
            'length' / Int32ul,
            'type' / Int32ul,
            'version' / Int32ul,
            'dummy' / Bytes(8),
            'seed' / Bytes(16),
            )*/
    break;
}
return;

Michael

War unterwegs und hatte das irgendwie damit verbunden :smiley: War aber auch mehr ne Frage von mir :smiley:

Immer wieder sehr beeindruckend dieser schlaue Drache :slight_smile: :cool:

Grüße,
Chris

Hallo,

so ich bin dabei mit das nochmal anzuschauen…
Kann mir hier jemand helfen?
python-ps4/connection.py at master · hthiery/python-ps4 · GitHub

    def _send_login_request(self):
        fmt = Struct(
            'length' / Const(b'\x80\x01\x00\x00'),
            'type' / Const(b'\x1e\x00\x00\x00'),
            'pass_code' / Const(b'\x00\x00\x00\x00'),
            'magic_number' / Const(b'\x01\x02\x00\x00'),
            'account_id' / Bytes(64),
            'app_label' / Bytes(256),
            'os_version' / Bytes(16),
            'model' / Bytes(16),
            'pin_code' / Bytes(16),
        )

        config = {
            'app_label': b'PlayStation'.ljust(256, b'\x00'),
            'account_id': self._credential.encode().ljust(64, b'\x00'),
            'os_version': b'4.4'.ljust(16, b'\x00'),
            'model': b'PS4 Waker'.ljust(16, b'\x00'),
            'pin_code': b''.ljust(16, b'\x00'),
        }

        _LOGGER.debug('config %s', config)

        msg = fmt.build(config)
        self._send_msg(msg, encrypted=True)

Wie ist das Bytes() in PHP umzusetzen?

Grüße,
Kai

Bytes ist ein Platzhalter für die Anzahl der Bytes in Klammern.
Was dort reinkommt, musst du entsprechend aus den Funktionen wo dieses Structure benutzt wird anschauen.
Bytes belegt das imho mit Nullbytes vor.

Beispiel bei config
account_id enthält also credential und der Rest wird (wieder) mit \x00 ausgefüllt.

‚model‘ =>‚PS4 Waker‘ und wieder sieben mal „/x00“ um auf 16 Byte zu kommen.

Usw…

Michael

Moin Michael,

und bei dem Build wird zum Beispiel der String direkt in Bytes gewandelt, richtig?

Also zum Beispiel bei ‚model‘: b’PS4 Waker’.ljust(16, b’\x00’),

Durch das build vom Streut wird PS4 Waker dann in Bytes umgewandelt und und mit \x00 aufgefüllt bis 16 Bytes erreicht sind.

Wäre in PHP zum Beispiel so:

$model = pack('N',"PS4 Waker");
str_pad($model, 16,"x00");

Grüße,
Kai

Pack brauchst du nicht.
Das ist ein String in Klartext und das sind nun Mal in PHP auch nur 1 Byte pro 1 Zeichen (Char). Also einfach zuweisen.
Und „x00“ funktioniert nicht.
Es muss schon „\x00“ sein.
Oder einfach chr(0);
$model = ‚PS4 Waker‘;

$model = str_pad($model, 16, chr(0));

Michael

Hallo Michael,

danke, ich werde es nun weiter versuchen. :slight_smile:

Grüße,
Kai

Hallo,

jetzt hänge ich beim Handshake fest.
Jemand da noch Tipps, was ich in PHP nutzen muss?

send_msg mach ich so:

    private function _send_msg($msg, $encrypted=false) {
        $this->SendDebug("TX MSG Length:", strlen($msg), 0);
        $this->SendDebug("TX MSG:", $msg, 0); //evtl. bin2hex($msg)

        if ($encrypted) {
            $cipher = "AES-128-CBC";
            $iv = $this->GetBuffer("IV");
            $msg = openssl_encrypt($msg, $cipher, $this->get_Public_Key_RSA(), $options=0, $iv);


            //openssl_encrypt($msg,$msg,_get_Public_Key_RSA(),OPENSSL_PKCS1_OAEP_PADDING);
        }
        $this->SendDebug("TX MSG crypted Length:", strlen($msg), 0);
        $this->SendDebug("TX MSG crypted:", $msg, 0);


        $JSON['DataID'] = '{79827379-F36E-4ADA-8A95-5F8D1DC92FA9}';
        $JSON['Buffer'] = utf8_encode($msg);
        $SendData = json_encode($JSON);
        //Send Data to Client Socket
        $this->SendDataToParent($SendData);
    }

$IV bekomme ich im ReceiveData und das wäre der Seed aus der Antwort vom HelloRequest.

Aber bei dem Handshake, weiß ich nicht wie ich die Zeilen hier umsetzen soll:

        recipient_key = _get_public_key_rsa()
        cipher_rsa = PKCS1_OAEP.new(recipient_key)
        key = cipher_rsa.encrypt(self._random_seed)

Grüße,
Kai

Kurze „Zwischenanmerkung/-frage“ in die Runde…

 private function _send_msg($msg, [b]$encrypted=false[/b]) 

…war da nicht was, dass man $encrypted=false nicht machen kann/darf in IPS-Modul-functions ?!?

Zu deiner eigentlichen Frage…

Zeile 1 ruft das hier im Python-Code auf:

def _get_public_key_rsa():
    key = RSA.importKey(PUBLIC_KEY)
    return key.publickey()

…wird also nen Public Key importiert/ausgelesen.
Sollte das hier sein >> PHP: openssl_pkey_get_private - Manual

Damit:

 PKCS1_OAEP.new

…wird ein Objekt (heißt das so?) erstellt. Gibts bei PHP auch sowas. Quasi sowas hier >> $mysqli = new mysqli(‚localhost‘, ‚my_user‘, ‚my_password‘, ‚my_db‘);

Und damit wird dann in deiner 3. Zeile:

cipher_rsa.encrypt(self._random_seed)

…der PrivKey entschlüsselt.
Sollte das hier sein >> PHP: openssl_public_encrypt - Manual // OPENSSL_PKCS1_OAEP_PADDING

Grüße,
Chris

Private != Modul-Funktion.
Somit alles erlaubt.
Michael

Aaaaaaaaaahhh… :banghead: Danke :smiley:
-Chris-

Denke ich nicht, denn hier geht es um den Public Key und nicht um den Private, der Public Key ist in einer Konstante vorhanden.

Das dort ein neues Objekt erzeugt wird ist klar.
Aber was willst du dort entschlüsseln, da muss etwas verschlüsselt (encrypt) werden.
Und mit openssl-public-encrypt fehlt mir da iwie die Stelle wo der random_seed hingehört. :frowning:

Grüße,
Kai

Ich lese das so, dass der random_seed verschlüsselt wird.
Er ist quasi die Rohdaten welche verschlüsselt werden sollen ( Parameter Data).

Michael

Encrypt-Decrypt…Private-Public…is doch alles das gleiche :smiley: …weißt doch was ich meinte :stuck_out_tongue:
Immer mal nebenbei in Sachen rein denken, da kann schon mal verwirrt sein :smiley:

-Chris-

Diese Verschlüsselung macht mich echt wahnsinnig … :banghead:
Ich komme da einfach kein Stück weiter. :frowning:

Edit: Es geht erstmal um den Handshake, mit dem Public Key… Da will es einfach nicht so. :frowning:

Grüße,
Kai

Hallo,

ich glaube das mit dem Public Key habe ich am laufen.
Aber die Pakete, die ich senden muss funktionieren anscheinend noch nicht so.
Vielleicht kann ja mal einer drüber schauen:

IPS-PS4/module.php at master · Schnittcher/IPS-PS4 · GitHub

Sobald ich ein Pakete wie zum Beispiel Login abschicke schließt sich die TCP Connection.

Grüße,
Kai