Forum: PC-Programmierung Verschlüsseln in PHP


von Kolja L. (kolja82)


Lesenswert?

Guten Morgen,

ich habe ein PHP Script geschrieben, welches aus den Logindaten eine 
verschlüsselte JSON Date erstellt und wollt emal fragen, ob ich es 
grundsätzlich richtig (oder zumindest nicht gänzlich falsch) mache:


User-Login:
1
if (isset($_POST['u_name']) 
2
       && $_POST['u_name'] != '' 
3
 && isset($_POST['u_password']) 
4
       && $_POST['u_password']) != ''{
5
    $_SESSION['user_ID']   = md5($_POST['u_name'] . $_POST['u_password']);
6
    $_SESSION['user_PW']   = md5($_POST['u_password']);
7
}

Nach dem Login gibt es also eine ID und ein Passwort in der Session, mit 
denen dann die Datei aufgerufen und entschlüsslt wird.

Der Aufruf der secure() Funktion:
1
$db_file = $dir_db . '/' . $user_ID;
2
// load
3
$data = secure('decrypt', $_SESSION['user_PW'], $db_file, '');
4
// save
5
secure('encrypt', $_SESSION['user_PW'], $db_file, $data);


Die secure() Funktion selbst:
1
function secure($action, $key, $file, $string){
2
    $output = false;
3
    $method = 'AES-256-CBC';
4
    $init_vector = 'just some ramdom text';
5
    $key = hash('sha256', $key);
6
    $init_vector = substr(hash('sha256', $init_vector), 0, 16);
7
8
    if ('encrypt' == $action) {
9
        $string = json_encode($string);
10
        $string = openssl_encrypt($string, $method, $key, 0, $init_vector);
11
        $string = base64_encode($string);
12
        if (file_put_contents($file, $string) > 0) {
13
            $output = true;
14
        }
15
    } elseif ('decrypt' == $action) {
16
        $string = file_get_contents($file);
17
        $string = base64_decode($string);
18
        $string = openssl_decrypt($string, $method, $key, 0, $init_vector);
19
        $output = json_decode($string, true);
20
        if (is_string($output)) {
21
            $output = json_decode($output, true);
22
        }
23
    }
24
    return $output;
25
}


Der gezeigte Code ist nur ein Teil des Skriptes, welches ich auf Github 
habe: https://github.com/KoljaL/SecureServices


Gruß Kolja

von Lukas T. (tapy)


Lesenswert?

Generell sollte zumindest bei der Session noch ein nur für diese Session 
gültiger Salt-String mit rein, um erstens das Passwort nicht ganz so 
leichtfertig preis zu geben und zweitens wenigstens etwas gehen 
Replay-Attacken zu tun.

Das ist natürlich schlecht für deinen Ansatz, der die ID aus Namen und 
Passwort generiert, aber da bin ich mir auch ziemlich sicher, dass ich 
das nicht so machen würde.

Das ist natürlich nur meine Meinung und kein "guter Rat", denn sowas ist 
ein heißes Thema. Es kommt immer darauf an, gegen wen Du die Daten 
schützen möchtest.

von Εrnst B. (ernst)


Lesenswert?

Kolja L. schrieb:
    $key = hash('sha256', $key);
    $init_vector = substr(hash('sha256', $init_vector), 0, 16);


du erzeugst den Key (und IV) als hash ohne "raw_output=true". Damit wird 
das Ergebnis als Hexadezimal-Ziffern 0-9a-f kodiert, also sind pro Byte 
im Key nur max. 4 Bit Passwort-Abhängig. ("maximal", weil evtl. vorher 
das MD5 noch was wegnimmt...)

Damit schwächst du die Verschlüsselung extrem, sie ist dadurch 
mindestens um den Faktor
340282366920938463463374607431768211456 schneller zu knacken. Das kann 
den Unterschied zwischen "Nachmittag mit der Grafikkarte" und "Nach dem 
Ende des Universums Gott um neuen Urknall bitten" machen.


Für die Anwendung Passwort -> Encryption-Key gibt's übrigens extra den 
PBKDF2-Algorithmus, bei dem sich Leute mit mehr Ahnung Gedanken gemacht 
haben.
https://de.wikipedia.org/wiki/PBKDF2
https://www.php.net/manual/de/function.hash-pbkdf2.php

Wär schonmal um welten besser als dein einstufiges SHA. Wenn du noch 
Angst vor ASIC-Minern hast, dann evtl. Scrypt. Das verwenden manche 
Crypto-Währungen (Litecoin z.B), um das Minen auf ASIC/FPGA zu 
erschweren.

: Bearbeitet durch User
von Kolja L. (kolja82)


Lesenswert?

Lukas T. schrieb:
> Generell sollte zumindest bei der Session noch ein nur für diese Session
> gültiger Salt-String mit rein, um erstens das Passwort nicht ganz so
> leichtfertig preis zu geben und zweitens wenigstens etwas gehen
> Replay-Attacken zu tun.

Im ersten Ansatz war in dem Passworthash auch noch der Timestamp des 
Logins enthalten, das hielt ich für ne gute Idee und es funktioniert ja 
auch, zumindest bis zum nächsten Login...

Lukas T. schrieb:
> Das ist natürlich nur meine Meinung und kein "guter Rat", denn sowas ist
> ein heißes Thema. Es kommt immer darauf an, gegen wen Du die Daten
> schützen möchtest.

Danke und wie gesagt, den Ansatz "SessionSalt" kann ich nachvollziehen. 
Für mich ist das Script als privater Link- und Passwortmanager gedacht 
und da ich nicht reich&berühmt bin, müsste ich mich von jedem Angrif 
wohl geehrt fühlen.

Εrnst B. schrieb:
> du erzeugst den Key (und IV) als hash ohne "raw_output=true".

Danke, genau solche Hinweise sind für mich wichtig.


Εrnst B. schrieb:
> Für die Anwendung Passwort -> Encryption-Key gibt's übrigens extra den
> PBKDF2-Algorithmus,

Du meinst an den Stellen:
1
$key = hash('sha256', $key);
2
$init_vector = substr(hash('sha256', $init_vector), 0, 16);
besser so:
1
$key = hash_pbkdf2('sha256', $key, $salt, $iterations, 20, true);
2
$init_vector = hash_pbkdf2('sha256', $init_vector , $salt, $iterations, 16, true);
?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.