it-swarm.com.de

Wie verschlüsselt/entschlüsselt man Daten in PHP?

Ich bin zurzeit Student und lerne PHP. Ich versuche, Daten in PHP einfach zu verschlüsseln/entschlüsseln. Ich habe online recherchiert und einige davon waren ziemlich verwirrend (zumindest für mich).

Folgendes versuche ich zu tun:

Ich habe eine Tabelle bestehend aus diesen Feldern (UserID, Fname, Lname, Email, Password)

Ich möchte, dass alle Felder verschlüsselt und dann entschlüsselt werden. (Kann ich sha256 für die Verschlüsselung/Entschlüsselung verwenden, wenn kein Verschlüsselungsalgorithmus vorhanden ist?)

Eine andere Sache, die ich lernen möchte, ist, wie man eine Einbahnstraße hash(sha256) zusammen mit einem guten "Salz" schafft. (Grundsätzlich möchte ich nur eine einfache Implementierung der Verschlüsselung/Entschlüsselung haben, hash(sha256)+salt) Sir/Ma'am, Ihre Antworten wären von großer Hilfe und werden sehr geschätzt. Vielen Dank ++

102
Randel Ramirez

Vorwort

Beginnen Sie mit Ihrer Tabellendefinition:

_- UserID
- Fname
- Lname
- Email
- Password
- IV
_

Hier sind die Änderungen:

  1. Die Felder Fname, Lname und Email werden mit einer symmetrischen Verschlüsselung verschlüsselt, die von OpenSSL bereitgestellt wird.
  2. Das IV-Feld speichert den Initialisierungsvektor , der für die Verschlüsselung verwendet wird. Die Speicheranforderungen hängen von der verwendeten Verschlüsselung und dem verwendeten Modus ab. dazu später mehr.
  3. Das Feld Password wird mit einem Einweg-Passwort-Hash gehasht.

Verschlüsselung

Chiffre und Modus

Die Auswahl der besten Verschlüsselungsart und des besten Verschlüsselungsmodus würde den Rahmen dieser Antwort sprengen. Die endgültige Auswahl wirkt sich jedoch auf die Größe des Verschlüsselungsschlüssels und des Initialisierungsvektors aus. Für diesen Beitrag verwenden wir AES-256-CBC mit einer festen Blockgröße von 16 Byte und einer Schlüsselgröße von 16, 24 oder 32 Byte.

Verschlüsselungsschlüssel

Ein guter Verschlüsselungsschlüssel ist ein binärer Blob, der von einem zuverlässigen Zufallszahlengenerator generiert wird. Das folgende Beispiel wird empfohlen (> = 5.3):

_$key_size = 32; // 256 bits
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);
// $strong will be true if the key is crypto safe
_

Dies kann ein- oder mehrmals erfolgen (wenn Sie eine Kette von Verschlüsselungsschlüsseln erstellen möchten). Halten Sie diese so privat wie möglich.

IV

Der Initialisierungsvektor fügt der Verschlüsselung Zufälligkeit hinzu und ist für den CBC-Modus erforderlich. Diese Werte sollten idealerweise nur einmal verwendet werden (technisch einmal pro Verschlüsselungsschlüssel), sodass sie bei einer Aktualisierung eines beliebigen Teils einer Zeile neu generiert werden sollten.

Es wird eine Funktion bereitgestellt, mit der Sie die IV erstellen können:

_$iv_size = 16; // 128 bits
$iv = openssl_random_pseudo_bytes($iv_size, $strong);
_

Beispiel

Lassen Sie uns das Namensfeld mit den früheren _$encryption_key_ und _$iv_ verschlüsseln. Dazu müssen wir unsere Daten auf die Blockgröße auffüllen:

_function pkcs7_pad($data, $size)
{
    $length = $size - strlen($data) % $size;
    return $data . str_repeat(chr($length), $length);
}

$name = 'Jack';
$enc_name = openssl_encrypt(
    pkcs7_pad($name, 16), // padded data
    'AES-256-CBC',        // cipher and mode
    $encryption_key,      // secret key
    0,                    // options (not used)
    $iv                   // initialisation vector
);
_

Lagerungssansprüche

Die verschlüsselte Ausgabe ist wie die IV binär. Das Speichern dieser Werte in einer Datenbank kann mithilfe bestimmter Spaltentypen wie BINARY oder VARBINARY erfolgen.

Der Ausgabewert ist wie der IV binär; Verwenden Sie zum Speichern dieser Werte in MySQL die Spalten BINARY ODER VARBINARY . Wenn dies nicht möglich ist, können Sie die Binärdaten auch mit base64_encode() oder bin2hex() in eine Textdarstellung konvertieren. Dies erfordert zwischen 33% und 100% mehr Speicherplatz.

Entschlüsselung

Die Entschlüsselung der gespeicherten Werte ist ähnlich:

_function pkcs7_unpad($data)
{
    return substr($data, 0, -ord($data[strlen($data) - 1]));
}

$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result
// $enc_name = base64_decode($row['Name']);
// $enc_name = hex2bin($row['Name']);
$enc_name = $row['Name'];
// $iv = base64_decode($row['IV']);
// $iv = hex2bin($row['IV']);
$iv = $row['IV'];

$name = pkcs7_unpad(openssl_decrypt(
    $enc_name,
    'AES-256-CBC',
    $encryption_key,
    0,
    $iv
));
_

Authentifizierte Verschlüsselung

Sie können die Integrität des generierten Chiffretexts weiter verbessern, indem Sie eine Signatur anhängen, die aus einem geheimen Schlüssel (der sich vom Verschlüsselungsschlüssel unterscheidet) und dem Chiffretext generiert wurde. Bevor der Chiffretext entschlüsselt wird, wird zunächst die Signatur verifiziert (vorzugsweise mit einem zeitlich konstanten Vergleich).

Beispiel

_// generate once, keep safe
$auth_key = openssl_random_pseudo_bytes(32, $strong);

// authentication
$auth = hash_hmac('sha256', $enc_name, $auth_key, true);
$auth_enc_name = $auth . $enc_name;

// verification
$auth = substr($auth_enc_name, 0, 32);
$enc_name = substr($auth_enc_name, 32);
$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);

if (hash_equals($auth, $actual_auth)) {
    // perform decryption
}
_

Siehe auch: hash_equals()

Hashing

Das Speichern eines umkehrbaren Passworts in Ihrer Datenbank muss so weit wie möglich vermieden werden. Sie möchten nur das Kennwort überprüfen, anstatt dessen Inhalt zu kennen. Wenn ein Benutzer sein Kennwort verliert, ist es besser, das Zurücksetzen zuzulassen, als das ursprüngliche Kennwort zu senden (stellen Sie sicher, dass das Zurücksetzen des Kennworts nur für eine begrenzte Zeit möglich ist).

Das Anwenden einer Hash-Funktion ist eine Einwegoperation. Danach kann es sicher zur Überprüfung verwendet werden, ohne die ursprünglichen Daten preiszugeben. Bei Passwörtern ist eine Brute-Force-Methode ein praktikabler Ansatz, um sie aufzudecken, da sie relativ kurz ist und von vielen Menschen nur eine geringe Auswahl an Passwörtern getroffen wird.

Hashing-Algorithmen wie MD5 oder SHA1 wurden erstellt, um den Dateiinhalt anhand eines bekannten Hash-Werts zu überprüfen. Sie sind stark optimiert, um diese Überprüfung so schnell wie möglich und dennoch genau wie möglich durchzuführen. Angesichts ihres relativ begrenzten Ausgabebereichs war es einfach, eine Datenbank mit bekannten Kennwörtern und ihren jeweiligen Hash-Ausgaben, den Rainbow-Tabellen, zu erstellen.

Das Hinzufügen eines Salt zum Kennwort vor dem Hashing würde eine Rainbow-Tabelle unbrauchbar machen, aber die jüngsten Hardware-Verbesserungen machten Brute-Force-Lookups zu einem praktikablen Ansatz. Aus diesem Grund benötigen Sie einen Hashing-Algorithmus, der absichtlich langsam und einfach nicht zu optimieren ist. Es sollte auch in der Lage sein, die Last für schnellere Hardware zu erhöhen, ohne die Möglichkeit zu beeinträchtigen, vorhandene Kennwort-Hashes zu überprüfen, um diese zukunftssicher zu machen.

Derzeit sind zwei beliebte Optionen verfügbar:

  1. PBKDF2 (Passwortbasierte Schlüsselableitungsfunktion v2)
  2. bcrypt (auch bekannt als Blowfish)

In dieser Antwort wird ein Beispiel mit bcrypt verwendet.

Generation

Ein Passwort-Hash kann folgendermaßen generiert werden:

_$password = 'my password';
$random = openssl_random_pseudo_bytes(18);
$salt = sprintf('$2y$%02d$%s',
    13, // 2^n cost factor
    substr(strtr(base64_encode($random), '+', '.'), 0, 22)
);

$hash = crypt($password, $salt);
_

Das Salz wird mit openssl_random_pseudo_bytes() erzeugt, um einen zufälligen Datenblock zu bilden, der dann durch base64_encode() und strtr() geleitet wird, um dem erforderlichen Alphabet von _[A-Za-z0-9/.]_ zu entsprechen.

Die Funktion crypt() führt das Hashing basierend auf dem Algorithmus (_$2y$_ für Blowfish), dem Kostenfaktor (ein Faktor von 13 benötigt ungefähr 0,40 Sekunden auf einer 3GHz-Maschine) und dem Salt von 22 Zeichen durch .

Validierung

Nachdem Sie die Zeile mit den Benutzerinformationen abgerufen haben, validieren Sie das Kennwort auf folgende Weise:

_$given_password = $_POST['password']; // the submitted password
$db_hash = $row['Password']; // field with the password hash

$given_hash = crypt($given_password, $db_hash);

if (isEqual($given_hash, $db_hash)) {
    // user password verified
}

// constant time string compare
function isEqual($str1, $str2)
{
    $n1 = strlen($str1);
    if (strlen($str2) != $n1) {
        return false;
    }
    for ($i = 0, $diff = 0; $i != $n1; ++$i) {
        $diff |= ord($str1[$i]) ^ ord($str2[$i]);
    }
    return !$diff;
}
_

Um ein Passwort zu verifizieren, rufen Sie erneut crypt() auf, übergeben aber den zuvor berechneten Hash als Salt-Wert. Der Rückgabewert liefert den gleichen Hash, wenn das angegebene Passwort mit dem Hash übereinstimmt. Um den Hash zu verifizieren, wird häufig empfohlen, eine zeitlich konstante Vergleichsfunktion zu verwenden, um Timing-Angriffe zu vermeiden.

Passwort-Hashing mit PHP 5.5

In PHP 5.5 wurden die Passwort-Hashing-Funktionen eingeführt, mit denen Sie die oben beschriebene Hashing-Methode vereinfachen können:

_$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);
_

Und überprüfen:

_if (password_verify($given_password, $db_hash)) {
    // password valid
}
_

Siehe auch: password_hash() , password_verify()

283
Ja͢ck

Ich denke, das wurde schon mal beantwortet ... aber wenn Sie Daten verschlüsseln/entschlüsseln möchten, können Sie SHA256 nicht verwenden

//Key
$key = 'SuperSecretKey';

//To Encrypt:
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, 'I want to encrypt this', MCRYPT_MODE_ECB);

//To Decrypt:
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_ECB);
21
romo

Hintergrund und Erklärung beantworten

Um diese Frage zu verstehen, müssen Sie zuerst verstehen, was SHA256 ist. SHA256 ist eine Cryptographic Hash-Funktion. Eine kryptografische Hash-Funktion ist eine Einwegfunktion, deren Ausgabe kryptographisch sicher ist. Dies bedeutet, dass es leicht ist, einen Hash zu berechnen (entspricht dem Verschlüsseln von Daten), aber die ursprüngliche Eingabe mit dem Hash (entspricht dem Entschlüsseln der Daten). Da die Verwendung einer kryptographischen Hash-Funktion bedeutet, dass das Entschlüsseln rechnerisch nicht durchführbar ist, können Sie mit SHA256 keine Entschlüsselung durchführen. 

Was Sie verwenden möchten, ist eine bidirektionale Funktion, insbesondere eine Block-Chiffre. Eine Funktion, die sowohl die Verschlüsselung als auch die Entschlüsselung von Daten ermöglicht. Die Funktionen mcrypt_encrypt und mcrypt_decrypt verwenden standardmäßig den Blowfish-Algorithmus. PHP verwendet mcrypt in diesem manual . Es gibt auch eine Liste von Verschlüsselungsdefinitionen zur Auswahl der von mcrypt verwendeten Verschlüsselung. Ein Wiki zu Blowfish kann unter Wikipedia gefunden werden. Eine Blockverschlüsselung verschlüsselt die Eingabe in Blöcken bekannter Größe und Position mit einem bekannten Schlüssel, so dass die Daten später mit dem Schlüssel entschlüsselt werden können. Dies kann SHA256 Ihnen nicht bieten.

Code

$key = 'ThisIsTheCipherKey';

$ciphertext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, 'This is plaintext.', MCRYPT_MODE_CFB);

$plaintext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB);
14
cytinus

Hier ist ein Beispiel mit openssl_encrypt 

//Encryption:
$textToEncrypt = "My Text to Encrypt";
$encryptionMethod = "AES-256-CBC";
$secretHash = "encryptionhash";
$iv = mcrypt_create_iv(16, MCRYPT_Rand);
$encryptedText = openssl_encrypt($textToEncrypt,$encryptionMethod,$secretHash, 0, $iv);

//Decryption:
$decryptedText = openssl_decrypt($encryptedText, $encryptionMethod, $secretHash, 0, $iv);
print "My Decrypted Text: ". $decryptedText;
8
Vivek
     function my_simple_crypt( $string, $action = 'e' ) {
        // you may change these values to your own
        $secret_key = 'my_simple_secret_key';
        $secret_iv = 'my_simple_secret_iv';

        $output = false;
        $encrypt_method = "AES-256-CBC";
        $key = hash( 'sha256', $secret_key );
        $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );

        if( $action == 'e' ) {
            $output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
        }
        else if( $action == 'd' ){
            $output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
        }

        return $output;
    }
1

Ich habe eine Weile gebraucht, um herauszufinden, wie man mit openssl_decrypt() keine false bekommt und verschlüsselt und entschlüsselt. 

    // cryptographic key of a binary string 16 bytes long (because AES-128 has a key size of 16 bytes)
    $encryption_key = '58adf8c78efef9570c447295008e2e6e'; // example
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, $iv);
    $encrypted = $encrypted . ':' . base64_encode($iv);

    // decrypt to get again $plaintext
    $parts = explode(':', $encrypted);
    $decrypted = openssl_decrypt($parts[0], 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, base64_decode($parts[1])); 

Wenn Sie die verschlüsselte Zeichenfolge über eine URL übergeben möchten, müssen Sie die Zeichenfolge urlencodieren: 

    $encrypted = urlencode($encrypted);

Um besser zu verstehen, was los ist, lesen Sie: 

Um 16 Byte lange Schlüssel zu generieren, können Sie Folgendes verwenden: 

    $bytes = openssl_random_pseudo_bytes(16);
    $hex = bin2hex($bytes);

Um Fehlermeldungen von openssl anzuzeigen, können Sie Folgendes verwenden: echo openssl_error_string();

Hoffentlich hilft das.

0
Kai Noack