Mit PHP verschlüsselte TXT-Datei mit Phyton entschlüsseln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mrrockkz
User
Beiträge: 12
Registriert: Donnerstag 2. März 2023, 15:24

Hallo zusammen,

ich bin gerade dabei mithilfe von ChatGPT im Alter noch etwas programmieren zu lernen.

Ich habe einen PHP-Code, welcher drei Daten mit Hilfe eines Keys in OpenSSL AES-256-CBC verschlüsselt und in einer txt-Datei speichert.

Code: Alles auswählen

<?php
// Daten aus dem Formular abrufen
$start = $_POST['start'];
$end = $_POST['end'];
$password = $_POST['password'];

// Festlegen des Verschlüsselungsschlüssels
$key = 'mein-geheimer-schluessel';

// Verschlüsseln der Daten mit OpenSSL
$encrypted_start = openssl_encrypt($start, 'AES-256-CBC', $key, 0, '0123456789012345');
$encrypted_end = openssl_encrypt($end, 'AES-256-CBC', $key, 0, '0123456789012345');
$encrypted_password = openssl_encrypt($passport, 'AES-256-CBC', $key, 0, '0123456789012345');

// Erstellen einer Datei
$file = fopen('key.cck', 'w');

// Schreiben der verschlüsselten Daten in die Datei
fwrite($file, $encrypted_start . "\n");
fwrite($file, $encrypted_end . "\n");
fwrite($file, $encrypted_password . "\n");

// Schließen der Datei
fclose($file);
?>
Welche sich auch mit einer PHP-Datei einfach wieder entschlüsseln und anzeigen lässt.

Code: Alles auswählen

<?php
// Festlegen des Verschlüsselungsschlüssels
$key = 'mein-geheimer-schluessel';

// Lesen der verschlüsselten Daten aus der Datei
$file = fopen('meine_daten.txt', 'r');

$encrypted_start = rtrim(fgets($file), "\n");
$encrypted_end = rtrim(fgets($file), "\n");
$encrypted_password = rtrim(fgets($file), "\n");

// Schließen der Datei
fclose($file);

// Entschlüsseln der Daten mit OpenSSL
$start = openssl_decrypt($encrypted_start, 'AES-256-CBC', $key, 0, '0123456789012345');
$end = openssl_decrypt($encrypted_end, 'AES-256-CBC', $key, 0, '0123456789012345');
$password = openssl_decrypt($encrypted_passport, 'AES-256-CBC', $key, 0, '0123456789012345');

// Ausgabe der entschlüsselten Daten
echo "Startzeit: " . $start . "<br>";
echo "Endzeit: " . $end . "<br>";
echo "Password: " . $password . "<br>";
?>
Ich benötige dieses aber in Python, deshalb habe ich mir etwas von ChatGPT helfen lassen und den mittlerweile mind. 50 Code, welche aber immer konstant Fehler ausspucken. Ich verstehe ja, dass Python und PHP komplett unterschiedliche Programmiersprachen sind, aber irgendwie muss das ganze ja realisierbar sein?

Code: Alles auswählen

import base64
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

# Festlegen des Verschlüsselungsschlüssels
key = b'mein-geheimer-schluessel'

# Lesen der verschlüsselten Daten aus der Datei
with open('meine_daten.txt', 'r') as f:
    encrypted_start = base64.b64decode(f.readline())
    encrypted_end = base64.b64decode(f.readline())
    encrypted_password = base64.b64decode(f.readline())

# Entschlüsseln der Daten mit OpenSSL
cipher = Cipher(algorithms.AES(key), modes.CBC(b'0123456789012345'))
decryptor = cipher.decryptor()

print(decryptor)

start = decryptor.update(encrypted_start)
end = decryptor.update(encrypted_end)
password = decryptor.update(encrypted_passport)

# Ausgabe der entschlüsselten Daten
print("Startzeit: " + start)
print("Endzeit: " + end)
print("Password: " + password)
Fehler dieses Mal:

Code: Alles auswählen

"C:\Users\Chris\PycharmProjects\Enschluessler\venv\Scripts\python.exe" "C:\Users\Chris\PycharmProjects\Enschluessler\main.py" 
<cryptography.hazmat.primitives.ciphers.base._CipherContext object at 0x000002A159A73A90>
Traceback (most recent call last):
  File "C:\Users\Chris\PycharmProjects\Enschluessler\main.py", line 24, in <module>
    print("Startzeit: " + start)
          ~~~~~~~~~~~~~~^~~~~~~
TypeError: can only concatenate str (not "bytes") to str

Process finished with exit code 1
Ich hoffe hier kann mir jemand etwas Licht ins Dunkle bringen!

Liebe Grüße
Chris
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mrrockkz: Programmieren durch raten funktioniert halt auch nicht wenn man ChatGPT raten lässt. Mein Tipp wäre zu verstehen was da gemacht wird in jedem Schritt in PHP und in Python, und dann nach den Schritten zu schauen welche Daten/Werte vorliegen und das zu vergleichen.

Wobei ich sehr stark vermute, dass das in PHP nicht wirklich funktioniert und Du nur zufällig noch keinen Fall hattest in dem das auf die Nase fällt. Wie sieht denn der Inhalt der verschlüsselten “Text“-Datei aus?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@mrrockkz: die Fehlermeldung hat ja nichts mit der Verschlüsselung zu tun, sondern ist ein ganz simpler Fehler, der sich auflösen läßt, wenn man einmal das Python-Grundlagentutorial durchgearbeitet hat.
mrrockkz
User
Beiträge: 12
Registriert: Donnerstag 2. März 2023, 15:24

__blackjack__ hat geschrieben: Mittwoch 22. März 2023, 17:02 Wie sieht denn der Inhalt der verschlüsselten “Text“-Datei aus?
Wenn ich bei start "13.03.2023", end "19.03.2023" und password "zzgkVv8uC1f71ktx" eintrage sieht die Datei folgendermaßen aus:

Code: Alles auswählen

LWthtOlXBefVJwDS/k5Drg==
TtPdtMEIBo7lzDsP49IWfQ==
OUB9xloprgs4DmU+X/kHuBJbzZ0VU6HwTX6oclZEVxo=
Was meinst du mit damit, dass dies nicht funktioniert?

Sirius3 hat geschrieben: Mittwoch 22. März 2023, 17:16 @mrrockkz: die Fehlermeldung hat ja nichts mit der Verschlüsselung zu tun, sondern ist ein ganz simpler Fehler, der sich auflösen läßt, wenn man einmal das Python-Grundlagentutorial durchgearbeitet hat.
Sorry, ich hatte erwartet, dass dies komplizierter sei, weil ich echt sehr viele Fehler hatte, welche ich selbstständig beheben konnte und mir zum Schluss nur dieser übrig blieb welchen ich vielleicht im WWW auch falsch gesucht hatte!
Benutzeravatar
Dennis89
User
Beiträge: 1125
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

der erste Suchtreffer:
https://stackoverflow.com/questions/550 ... tes-to-str

Da wird in der ersten Antwort das Problem eigentlich beschrieben.

Das Tutorial von dem die Rede war:
https://docs.python.org/3/tutorial/

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mrrockkz: PHP-APIs, ich hätte jetzt nicht damit gerechnet, dass da schon Base64 raus kommt, beim verschlüsseln. Dann hätte man die Zeilen nämlich nicht mehr garantiert voneinander trennen können.

Wobei dieses Beispiel nicht mit dem Code aus dem ersten Beitrag entstanden ist, denn da wird beim Verschlüsseln eine unbekannte Variable $passport verwendet, statt $password.

Das feste IV-Werte verwendet werden, macht das ganze für bestimmte Angriffe anfällig. Warum musst Du denn überhaupt eine eigene Verschlüsselung basteln. Das ist so gut wie nie eine gute Idee.

Beim entschlüsseln verwendest Du nicht den gleichen Algorithmus — Du hast da Glück das der verwendete Schlüssel gerade zufällig eine gültige Länge hat, aber es ist die falsche.

Es fehlt der `finalize()`-Aufruf, und Du wirst am Ende noch das Padding der Daten entfernen müssen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@__blackjack__: ich würde eher sagen, es ist Pech, dass da AES196 verwendet wird, statt AES256. Sonst würde der Fehler schon viel früher auffallen. Da hat PHP auch ein seltsames Verständnis von Kryptographie.

@mrrockkz: man darf niemals zum selben Passwort den selben Initialvektor wiederverwenden.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Meine Güte, PHP scheint ja alles zu fressen. Jedenfalls kann ich ohne Änderung des PHP-Snippets den Inhalt nicht entschlüsseln.
Zu dem Modus muss auch die Schlüssellänge passen und wenn das nicht stimmt, macht PHP irgendwas anderes.
(normalerweise erwartet man dann als Python-Entwickler eine Exception ...)

Code: Alles auswählen

<?php
// Daten aus dem Formular abrufen
$start = 'start';
$end = 'end';
$passport = 'password';

// Festlegen des Verschlüsselungsschlüssels
$key = 'mein-geheimer-schluessel';

// Verschlüsseln der Daten mit OpenSSL
// LESEN: https://www.php.net/manual/en/function.openssl-encrypt.php
$encrypted_start = openssl_encrypt($start, 'AES-192-CBC', $key, 0, '0123456789012345');
$encrypted_end = openssl_encrypt($end, 'AES-192-CBC', $key, 0, '0123456789012345');
$encrypted_password = openssl_encrypt($passport, 'AES-192-CBC', $key, 0, '0123456789012345');

// Erstellen einer Datei
$file = fopen('key.cck', 'w');

// Schreiben der verschlüsselten Daten in die Datei
fwrite($file, $encrypted_start . "\n");
fwrite($file, $encrypted_end . "\n");
fwrite($file, $encrypted_password . "\n");

// Schließen der Datei
fclose($file);
?>
Gibt es bei PHP keinen Kontextmanager? Dann ist mir noch aufgefallen, dass die Ausgabe base64 encodiert gespeichert wird. Wieso das denn? Was sorgt für die Ausgabe? Kann es sein, dass da auch wieder ein Automatismus hinter steckt?

Zum Entschlüsseln:

Code: Alles auswählen

from base64 import b64decode

# pip install pycryptodome
# https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad


def decrypt(file, key, iv):
    with open(file, "rb") as fd:
        for line in fd:
            decryptor = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
            yield unpad(decryptor.decrypt(b64decode(line)), 16)


values = list(decrypt("key.cck", b"mein-geheimer-schluessel", b"0123456789012345"))
Von Kryptografie weiß ich nicht genug, habe aber mal gelesen, dass AES-CBC angreifbar ist.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Was PHP bei dem Schlüssel macht steht in der Dokumentation: Falls er zu kurz ist, wird mit Null-Bytes aufgefüllt, und falls er zu lang ist, wird der Rest einfach abgeschnitten.

Die Verschlüsselung liefert in PHP eine Base64 kodierte Zeichenkette. Die Entschlüsselung nimmt sowohl eine solche Zeichenkette als auch Zeichenketten direkt mit Binärdaten. PHP-APIs halt. 🙂
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Jetzt habe ich den Satz in der Doku auch gefunden:
Encrypts given data with given method and key, returns a raw or base64 encoded string
Mich stört das nicht weiter, da ich PHP nicht verwende.
Ich habe mal gehört, dass die modernen PHP-Versionen besser sein sollen.
Aber so einen Bruch wie bei Python gab es bei PHP nie.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
mrrockkz
User
Beiträge: 12
Registriert: Donnerstag 2. März 2023, 15:24

Dennis89 hat geschrieben: Mittwoch 22. März 2023, 19:18 Das Tutorial von dem die Rede war:
https://docs.python.org/3/tutorial/
@Dennis83: Danke dir!
__blackjack__ hat geschrieben: Mittwoch 22. März 2023, 19:41 Wobei dieses Beispiel nicht mit dem Code aus dem ersten Beitrag entstanden ist, denn da wird beim Verschlüsseln eine unbekannte Variable $passport verwendet, statt $password.

Das feste IV-Werte verwendet werden, macht das ganze für bestimmte Angriffe anfällig. Warum musst Du denn überhaupt eine eigene Verschlüsselung basteln. Das ist so gut wie nie eine gute Idee.
@__blackjack__: Stimmt, der ist noch mit dem "alten" Script, was identisch war, jedoch den password und passport-Dreher hatte. Gibt es denn schon fertige Scripts bzw. Lösungen für sowas oder wie meinst du das mit der eigenen Verschlüsselung?
Sirius3 hat geschrieben: Mittwoch 22. März 2023, 20:05 @mrrockkz: man darf niemals zum selben Passwort den selben Initialvektor wiederverwenden.
Das habe ich abgeändert, da ich diese Fehlerquelle einfach ausschließen wollte. Hab es versucht zu "vereinfachen" sicher war das dann aber natürlich nicht.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@mrrockkz: Du benutzt in Python doch schon das Paket `cryptography`. Wenn Du dessen Dokumentation durchliest, dann steht da FETT ein Warnhinweis:
Danger hat geschrieben:This is a “Hazardous Materials” module. You should ONLY use it if you’re 100% absolutely sure that you know what you’re doing because this module is full of land mines, dragons, and dinosaurs with laser guns. You may instead be interested in Fernet (symmetric encryption).
Und dort wird auf eine sichere Implementierung verwiesen: https://cryptography.io/en/latest/ferne ... ith-fernet
Antworten