Wie verschlüsseln / entschlüsseln Daten in PHP?

Ich bin zur Zeit Student und studiere PHP, ich versuche eine einfache Ver- und Entschlüsselung von Daten in PHP zu machen. Ich machte einige Online-Recherchen und einige von ihnen waren ziemlich verwirrend (zumindest für mich).

Hier ist, was ich versuche zu tun:

Ich habe eine Tabelle, bestehend aus diesen Feldern (UserID, Fname, Lname, E-Mail, Passwort)

Was ich haben möchte, ist die alle Felder verschlüsselt und dann entschlüsselt werden (Ist es möglich, sha256 für die Verschlüsselung / Entschlüsselung zu verwenden, wenn nicht irgendein Verschlüsselungsalgorithmus)

Eine andere Sache, die ich lernen möchte, ist, wie man einen Einweg- hash(sha256) kombiniert mit einem guten “Salz” erstellt. (Grundsätzlich möchte ich nur eine einfache Implementierung von Verschlüsselung / Entschlüsselung, hash(sha256)+salt) Sir / Ma’am, Ihre Antworten würden eine große Hilfe sein und sehr geschätzt werden. Danke ++

    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. Mehr dazu später.
    3. Das Password Feld wird mit einem Einweg- Passwort-Hash Hash

    Verschlüsselung

    Chiffre und Modus

    Die Wahl der besten Verschlüsselungscodierung und des Verschlüsselungsmodus geht über den Rahmen dieser Antwort hinaus, aber die endgültige Auswahl betrifft die Größe sowohl des Verschlüsselungsschlüssels als auch des Initialisierungsvektors; Für diesen Beitrag verwenden wir AES-256-CBC, das eine feste Blockgröße von 16 Byte und eine Schlüsselgröße von 16, 24 oder 32 Byte hat.

    Verschlüsselungsschlüssel

    Ein guter Verschlüsselungsschlüssel ist ein binärer Blob, der von einem zuverlässigen Zufallszahlengenerator erzeugt wird. Das folgende Beispiel würde 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 einmal oder mehrmals durchgeführt werden (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 eine 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), daher sollte ein Update für jeden Teil einer Zeile es neu generieren.

    Eine function wird bereitgestellt, um Ihnen beim Generieren der IV zu helfen:

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

    Beispiel

    Lassen Sie uns das Namensfeld mit dem früheren $encryption_key und $iv $encryption_key ; Um dies zu tun, 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 database kann mithilfe von angegebenen VARBINARY wie VARBINARY oder VARBINARY .

    Der Ausgabewert ist wie der IV binär; VARBINARY diese Werte in MySQL zu speichern, sollten Sie VARBINARY oder VARBINARY Spalten verwenden. Wenn dies keine Option ist, können Sie die binären Daten auch in eine textliche Darstellung base64_encode() indem Sie base64_encode() oder bin2hex() , was zwischen 33% und 100% mehr Speicherplatz erfordert.

    Entschlüsselung

    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 Chiffretextes weiter verbessern, indem Sie eine Signatur anfügen, die aus einem geheimen Schlüssel (anders als der Chiffrierschlüssel) und dem Chiffretext generiert wird. Bevor der Chiffretext entschlüsselt wird, wird die Signatur zunächst verifiziert (vorzugsweise mit einer Vergleichszeitmethode).

    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 reversiblen Passworts in Ihrer database muss so weit wie möglich vermieden werden. Sie möchten nur das Passwort überprüfen, anstatt dessen Inhalt zu kennen. Wenn ein Benutzer sein Passwort verliert, ist es besser, ihm das Zurücksetzen zu erlauben, anstatt ihm das Original zu schicken (stellen Sie sicher, dass das Zurücksetzen des Passworts nur für eine begrenzte Zeit möglich ist).

    Das Anwenden einer Hash-function ist eine einseitige Operation; danach kann es sicher zur Überprüfung verwendet werden, ohne die ursprünglichen Daten zu offenbaren; für Passwörter ist eine Brute-Force-Methode ein praktikabler Ansatz, um es aufgrund seiner relativ kurzen Länge und schlechten Passwort-Entscheidungen vieler Menschen aufzudecken.

    Hashing-Algorithmen wie MD5 oder SHA1 wurden gemacht, um Dateiinhalte gegen einen bekannten Hash-Wert zu verifizieren. Sie sind stark optimiert, um diese Verifizierung so schnell wie möglich zu machen und dennoch genau zu sein. Angesichts ihres relativ begrenzten Ausgangsraums war es einfach, eine database mit bekannten Passwörtern und ihren jeweiligen Hash-Ausgaben, den Rainbow-Tabellen, zu erstellen.

    Das Hinzufügen eines Salzes zum Passwort vor dem Hashing würde eine Rainbow-Tabelle nutzlos machen, aber jüngste Hardware-Verbesserungen machten Brute-Force-Lookups zu einem realisierbaren Ansatz. Deshalb benötigen Sie einen Hashalgorithmus, der bewusst langsam ist und einfach nicht optimiert werden kann. Es sollte auch in der Lage sein, die Last für schnellere Hardware zu erhöhen, ohne die Fähigkeit zu beeinträchtigen, vorhandene Passwort-Hashes zu verifizieren, um es zukunftssicher zu machen.

    Momentan gibt es zwei beliebte Möglichkeiten:

    1. PBKDF2 (Passwortbasierte Schlüsselableitungsfunktion v2)
    2. bcrypt (aka Blowfish)

    Diese Antwort verwendet ein Beispiel mit bcrypt.

    Generation

    Ein Passwort-Hash kann folgendermaßen erzeugt 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() , um einen zufälligen openssl_random_pseudo_bytes() zu bilden, der dann durch base64_encode() und strtr() , um dem erforderlichen Alphabet von [A-Za-z0-9/.] .

    Die function crypt() führt das Hashen basierend auf dem Algorithmus ( $2y$ für Blowfish), den Kostenfaktor (ein Faktor von 13 dauert ungefähr 0,40s auf einer 3GHz-Maschine) und das Salz von 22 Zeichen durch.

    validation

    Sobald Sie die Zeile mit den Benutzerinformationen abgerufen haben, validieren Sie das Passwort 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 crypt() erneut auf, aber Sie übergeben den zuvor berechneten Hash als Salt-Wert. Der Rückgabewert ergibt denselben Hash, wenn das angegebene Passwort mit dem Hash übereinstimmt. Um den Hash zu überprüfen, wird häufig empfohlen, eine Vergleichszeitfunktion zu verwenden, um Timing-Angriffe zu vermeiden.

    Passwort Hashing mit PHP 5.5

    PHP 5.5 führte die Hashing-functionen für das Passwort ein , mit denen Sie die obige 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()

    Ich denke, das wurde schon beantwortet … aber wenn Sie Daten verschlüsseln / entschlüsseln wollen, 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); 

    Antwort Hintergrund und Erklärung

    Um diese Frage zu verstehen, müssen Sie zuerst verstehen, was SHA256 ist. SHA256 ist eine kryptographische Hash-function . Eine kryptographische Hash-function ist eine Einwegfunktion, deren Ausgabe kryptographisch sicher ist. Dies bedeutet, dass es einfach ist, einen Hash zu berechnen (entspricht der Verschlüsselung von Daten), aber es ist schwierig, die ursprüngliche Eingabe mit dem Hash zu erhalten (entspricht der Entschlüsselung der Daten). Da die Verwendung einer kryptografischen Hash-function bedeutet, dass die Entschlüsselung nicht machbar ist, können Sie die Entschlüsselung mit SHA256 nicht durchführen.

    Was Sie verwenden möchten, ist eine Zwei-Wege-function, genauer gesagt, eine Block-Chiffre . Eine function, mit der Daten sowohl verschlüsselt als auch entschlüsselt werden können. Die functionen mcrypt_encrypt und mcrypt_decrypt standardmäßig den Blowfish-Algorithmus. PHP verwendet mcrypt in diesem Handbuch . Eine Liste von Chiffrierdefinitionen zur Auswahl der Chiffre, die mcrypt verwendet, existiert ebenfalls. Ein Wiki auf Blowfish kann bei Wikipedia gefunden werden . Eine Blockchiffre 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); 

    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; 

    Es hat eine Weile openssl_decrypt() , bis ich herausgefunden habe, wie man bei Verwendung von openssl_decrypt() kein false openssl_decrypt() erhält und die Arbeit verschlüsseln und entschlüsseln kann.

      // 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 vor sich geht, 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 zu sehen, können Sie verwenden: echo openssl_error_string();

    Ich hoffe, das hilft.

      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; }