Zweiwege-Verschlüsselung: Ich muss Kennwörter speichern, die abgerufen werden können


174

Ich erstelle eine Anwendung, in der Kennwörter gespeichert werden, die der Benutzer abrufen und anzeigen kann. Die Passwörter gelten für ein Hardwaregerät, sodass eine Überprüfung auf Hashes nicht in Frage kommt.

Was ich wissen muss ist:

  1. Wie verschlüssele und entschlüssele ich ein Passwort in PHP?

  2. Was ist der sicherste Algorithmus zum Verschlüsseln der Passwörter?

  3. Wo speichere ich den privaten Schlüssel?

  4. Ist es eine gute Idee, Benutzer zu verpflichten, den privaten Schlüssel jedes Mal einzugeben, wenn sie ein entschlüsseltes Kennwort benötigen, anstatt den privaten Schlüssel zu speichern? (Benutzern dieser Anwendung kann vertraut werden)

  5. Wie kann das Passwort gestohlen und entschlüsselt werden? Was muss ich beachten?


1
Hinweis: Libsodium wird jetzt für> = 7.2 in den PHP-Kern kompiliert. Dies wäre jetzt die "Gehe zu" -Lösung, da sie im Gegensatz zu mcrypt, das als veraltet gilt und entfernt wurde, voller moderner Methoden ist.
Exhibitionist

Antworten:


212

Persönlich würde ich mcryptgerne andere posten. Aber es gibt noch viel mehr zu beachten ...

  1. Wie verschlüssele und entschlüssele ich ein Passwort in PHP?

    Unten finden Sie eine starke Klasse, die sich um alles für Sie kümmert:

  2. Was ist der sicherste Algorithmus zum Verschlüsseln der Passwörter?

    am sichersten ? jeder von ihnen. Die sicherste Methode zum Verschlüsseln ist der Schutz vor Sicherheitslücken bei der Offenlegung von Informationen (XSS, Remote Inclusion usw.). Wenn es herauskommt, kann der Angreifer möglicherweise die Verschlüsselung knacken (keine Verschlüsselung ist ohne den Schlüssel zu 100% nicht umkehrbar - Wie @NullUserException hervorhebt, ist dies nicht ganz richtig. Es gibt einige Verschlüsselungsschemata, die nicht geknackt werden können, wie z. B. OneTimePad ). .

  3. Wo speichere ich den privaten Schlüssel?

    Was ich tun würde, ist 3 Schlüssel zu verwenden. Einer ist vom Benutzer bereitgestellt, einer ist anwendungsspezifisch und der andere ist benutzerspezifisch (wie ein Salz). Der anwendungsspezifische Schlüssel kann überall gespeichert werden (in einer Konfigurationsdatei außerhalb des Webstamms, in einer Umgebungsvariablen usw.). Das benutzerspezifische wird in einer Spalte in der Datenbank neben dem verschlüsselten Passwort gespeichert. Der vom Benutzer angegebene wird nicht gespeichert. Dann würden Sie so etwas tun:

    $key = $userKey . $serverKey . $userSuppliedKey;

    Der Vorteil dort ist, dass 2 beliebige Schlüssel kompromittiert werden können, ohne dass die Daten kompromittiert werden. Wenn es einen SQL Injection-Angriff gibt, können sie den $userKey, aber nicht den anderen 2 erhalten. Wenn es einen lokalen Server-Exploit gibt, können sie $userKeyund $serverKey, aber nicht den dritten $userSuppliedKey. Wenn sie den Benutzer mit einem Schraubenschlüssel schlagen, können sie die $userSuppliedKey, aber nicht die anderen 2 bekommen (aber wenn der Benutzer mit einem Schraubenschlüssel geschlagen wird, sind Sie sowieso zu spät).

  4. Ist es eine gute Idee, Benutzer zu verpflichten, den privaten Schlüssel jedes Mal einzugeben, wenn sie ein entschlüsseltes Kennwort benötigen, anstatt den privaten Schlüssel zu speichern? (Benutzern dieser Anwendung kann vertraut werden)

    Absolut. In der Tat ist das der einzige Weg, wie ich es tun würde. Andernfalls müssten Sie eine unverschlüsselte Version in einem dauerhaften Speicherformat (gemeinsam genutzter Speicher wie APC oder Memcached oder in einer Sitzungsdatei) speichern. Das setzt Sie zusätzlichen Kompromissen aus. Speichern Sie die unverschlüsselte Version des Passworts niemals in einer anderen als einer lokalen Variablen.

  5. Wie kann das Passwort gestohlen und entschlüsselt werden? Was muss ich beachten?

    Bei jeder Form von Kompromittierung Ihrer Systeme können sie verschlüsselte Daten anzeigen. Wenn sie Code einfügen oder in Ihr Dateisystem gelangen können, können sie entschlüsselte Daten anzeigen (da sie die Dateien bearbeiten können, die die Daten entschlüsseln). Jede Form von Replay oder MITM-Angriff ermöglicht ihnen auch den vollen Zugriff auf die beteiligten Schlüssel. Wenn Sie den rohen HTTP-Verkehr abhören, erhalten Sie auch die Schlüssel.

    Verwenden Sie SSL für den gesamten Datenverkehr. Stellen Sie außerdem sicher, dass auf dem Server keinerlei Sicherheitslücken bestehen (CSRF, XSS, SQL Injection, Eskalation von Berechtigungen, Remotecodeausführung usw.).

Bearbeiten: Hier ist eine PHP-Klassenimplementierung einer starken Verschlüsselungsmethode:

/**
 * A class to handle secure encryption and decryption of arbitrary data
 *
 * Note that this is not just straight encryption.  It also has a few other
 *  features in it to make the encrypted data far more secure.  Note that any
 *  other implementations used to decrypt data will have to do the same exact
 *  operations.  
 *
 * Security Benefits:
 *
 * - Uses Key stretching
 * - Hides the Initialization Vector
 * - Does HMAC verification of source data
 *
 */
class Encryption {

    /**
     * @var string $cipher The mcrypt cipher to use for this instance
     */
    protected $cipher = '';

    /**
     * @var int $mode The mcrypt cipher mode to use
     */
    protected $mode = '';

    /**
     * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
     */
    protected $rounds = 100;

    /**
     * Constructor!
     *
     * @param string $cipher The MCRYPT_* cypher to use for this instance
     * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
     * @param int    $rounds The number of PBKDF2 rounds to do on the key
     */
    public function __construct($cipher, $mode, $rounds = 100) {
        $this->cipher = $cipher;
        $this->mode = $mode;
        $this->rounds = (int) $rounds;
    }

    /**
     * Decrypt the data with the provided key
     *
     * @param string $data The encrypted datat to decrypt
     * @param string $key  The key to use for decryption
     * 
     * @returns string|false The returned string if decryption is successful
     *                           false if it is not
     */
    public function decrypt($data, $key) {
        $salt = substr($data, 0, 128);
        $enc = substr($data, 128, -64);
        $mac = substr($data, -64);

        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        if (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             return false;
        }

        $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

        $data = $this->unpad($dec);

        return $data;
    }

    /**
     * Encrypt the supplied data using the supplied key
     * 
     * @param string $data The data to encrypt
     * @param string $key  The key to encrypt with
     *
     * @returns string The encrypted data
     */
    public function encrypt($data, $key) {
        $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        $data = $this->pad($data);

        $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

        $mac = hash_hmac('sha512', $enc, $macKey, true);
        return $salt . $enc . $mac;
    }

    /**
     * Generates a set of keys given a random salt and a master key
     *
     * @param string $salt A random string to change the keys each encryption
     * @param string $key  The supplied key to encrypt with
     *
     * @returns array An array of keys (a cipher key, a mac key, and a IV)
     */
    protected function getKeys($salt, $key) {
        $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
        $keySize = mcrypt_get_key_size($this->cipher, $this->mode);
        $length = 2 * $keySize + $ivSize;

        $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

        $cipherKey = substr($key, 0, $keySize);
        $macKey = substr($key, $keySize, $keySize);
        $iv = substr($key, 2 * $keySize);
        return array($cipherKey, $macKey, $iv);
    }

    /**
     * Stretch the key using the PBKDF2 algorithm
     *
     * @see http://en.wikipedia.org/wiki/PBKDF2
     *
     * @param string $algo   The algorithm to use
     * @param string $key    The key to stretch
     * @param string $salt   A random salt
     * @param int    $rounds The number of rounds to derive
     * @param int    $length The length of the output key
     *
     * @returns string The derived key.
     */
    protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
        $size   = strlen(hash($algo, '', true));
        $len    = ceil($length / $size);
        $result = '';
        for ($i = 1; $i <= $len; $i++) {
            $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
            $res = $tmp;
            for ($j = 1; $j < $rounds; $j++) {
                 $tmp  = hash_hmac($algo, $tmp, $key, true);
                 $res ^= $tmp;
            }
            $result .= $res;
        }
        return substr($result, 0, $length);
    }

    protected function pad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $padAmount = $length - strlen($data) % $length;
        if ($padAmount == 0) {
            $padAmount = $length;
        }
        return $data . str_repeat(chr($padAmount), $padAmount);
    }

    protected function unpad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $last = ord($data[strlen($data) - 1]);
        if ($last > $length) return false;
        if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
            return false;
        }
        return substr($data, 0, -1 * $last);
    }
}

Beachten Sie, dass ich eine in PHP 5.6 hinzugefügte Funktion verwende : hash_equals. Wenn Sie weniger als 5,6 verwenden, können Sie diese Ersatzfunktion verwenden, die eine zeitsichere Vergleichsfunktion mit doppelter HMAC-Überprüfung implementiert :

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

Verwendung:

$e = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, $key);

Dann, um zu entschlüsseln:

$e2 = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, $key);

Beachten Sie, dass ich $e2das zweite Mal verwendet habe, um Ihnen zu zeigen, dass verschiedene Instanzen die Daten immer noch ordnungsgemäß entschlüsseln.

Wie funktioniert es nun / warum wird es über einer anderen Lösung verwendet:

  1. Schlüssel

    • Die Schlüssel werden nicht direkt verwendet. Stattdessen wird der Schlüssel durch eine Standard-PBKDF2-Ableitung gestreckt.

    • Der für die Verschlüsselung verwendete Schlüssel ist für jeden verschlüsselten Textblock eindeutig. Der mitgelieferte Schlüssel wird somit zu einem "Hauptschlüssel". Diese Klasse bietet daher eine Schlüsselrotation für Verschlüsselungs- und Authentifizierungsschlüssel.

    • WICHTIGER HINWEIS : Der $roundsParameter ist für echte Zufallsschlüssel mit ausreichender Stärke konfiguriert (mindestens 128 Bit Cryptographically Secure Random). Wenn Sie ein Kennwort oder einen nicht zufälligen Schlüssel (oder weniger zufällig als 128 Bit CS-Zufall) verwenden möchten, müssen Sie diesen Parameter erhöhen. Ich würde ein Minimum von 10000 für Passwörter vorschlagen (je mehr Sie sich leisten können, desto besser, aber es erhöht die Laufzeit) ...

  2. Datenintegrität

    • Die aktualisierte Version verwendet ENCRYPT-THEN-MAC, eine weitaus bessere Methode, um die Authentizität der verschlüsselten Daten sicherzustellen.
  3. Verschlüsselung:

    • Es verwendet mcrypt, um die Verschlüsselung tatsächlich durchzuführen. Ich würde vorschlagen, entweder MCRYPT_BLOWFISHoder MCRYPT_RIJNDAEL_128Chiffren und MCRYPT_MODE_CBCfür den Modus zu verwenden. Es ist stark genug und immer noch ziemlich schnell (ein Verschlüsselungs- und Entschlüsselungszyklus dauert auf meinem Computer ungefähr eine halbe Sekunde).

Was nun Punkt 3 aus der ersten Liste betrifft, so würde Ihnen dies eine Funktion wie diese geben:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

Sie könnten es in der makeKey()Funktion dehnen , aber da es später gedehnt wird, ist es nicht wirklich sinnvoll, dies zu tun.

Die Speichergröße hängt vom Klartext ab. Blowfish verwendet eine Blockgröße von 8 Byte, sodass Sie Folgendes haben:

  • 16 Bytes für das Salz
  • 64 Bytes für den hmac
  • Datenlänge
  • Auffüllen, damit die Datenlänge% 8 == 0 ist

Für eine 16-stellige Datenquelle müssen also 16 Zeichen Daten verschlüsselt werden. Das bedeutet, dass die tatsächliche Größe der verschlüsselten Daten aufgrund des Auffüllens 16 Byte beträgt. Fügen Sie dann die 16 Bytes für das Salt und 64 Bytes für den hmac hinzu, und die insgesamt gespeicherte Größe beträgt 96 Bytes. Es gibt also bestenfalls einen Overhead von 80 Zeichen und im schlimmsten Fall einen Overhead von 87 Zeichen ...

Ich hoffe das hilft...

Hinweis: 11.12.12: Ich habe diese Klasse gerade mit einer VIEL besseren Verschlüsselungsmethode aktualisiert, indem ich besser abgeleitete Schlüssel verwendet und die MAC-Generierung korrigiert habe ...


3
Jemand versteht nicht, was es "Pause" bedeutet. @IRC gute Arbeit in der Klasse, das ist verdammt guter Code.
Jcolebrand

1
Das Folgende gibt false zurück. Irgendeine Idee warum? $ x = neue Verschlüsselung (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ test = $ x-> encrypt ("test", "a"); echo var_dump ($ x-> entschlüsseln ($ test, "a"));
Die Wellenlänge

2
Oh und wieder in der Entschlüsselungsfunktion ändern die beiden -64s zu -128helfen (so bekommen Sie $enc = substr($data, 128, -128)und$mac = substr($data, -128);
Cosmorogers

4
@ircmaxell Es ist schon eine Weile her, seit der Code das letzte Mal überarbeitet wurde, also frage ich mich, ob er aktuell ist. Ich muss etwas Ähnliches für eine Finanzanwendung verwenden und es wäre schön, wenn Sie mit dieser Klasse ein Okay geben würden :-)
nt.bas

2
Warnung! Die mcrypt-Erweiterung ist seit fast einem Jahrzehnt eine Abbruchware und auch recht komplex in der Verwendung. Es wurde daher zugunsten von OpenSSL abgelehnt, wo es in PHP 7.2 aus dem Kern in PECL entfernt wird. th1.php.net/manual/en/migration71.deprecated.php
vee

15

Wie verschlüssele und entschlüssele ich ein Passwort in PHP? Durch die Implementierung eines von vielen Verschlüsselungsalgorithmen. (oder mit einer von vielen Bibliotheken)

Was ist der sicherste Algorithmus zum Verschlüsseln der Passwörter? Es gibt unzählige verschiedene Algorithmen, von denen keiner 100% sicher ist. Aber viele von ihnen sind sicher genug für den Handel und sogar für militärische Zwecke

Wo speichere ich den privaten Schlüssel? Wenn Sie sich für die Implementierung eines Kryptografiealgorithmus mit öffentlichem Schlüssel (z. B. RSA) entschieden haben, speichern Sie keinen privaten Schlüssel. Benutzer haben privaten Schlüssel. Ihr System verfügt über einen öffentlichen Schlüssel, der an einem beliebigen Ort gespeichert werden kann.

Ist es eine gute Idee, Benutzer zu verpflichten, den privaten Schlüssel jedes Mal einzugeben, wenn sie ein entschlüsseltes Kennwort benötigen, anstatt den privaten Schlüssel zu speichern? (Benutzern dieser Anwendung kann vertraut werden.) Wenn sich Ihr Benutzer an lächerlich lange Primzahlen erinnern kann, dann - ja, warum nicht. Im Allgemeinen müssten Sie jedoch ein System entwickeln, mit dem der Benutzer seinen Schlüssel irgendwo speichern kann.

Wie kann das Passwort gestohlen und entschlüsselt werden? Was muss ich beachten? Dies hängt vom verwendeten Algorithmus ab. Stellen Sie jedoch immer sicher, dass Sie das Passwort nicht unverschlüsselt an oder vom Benutzer senden. Entweder auf der Clientseite verschlüsseln / entschlüsseln oder https verwenden (oder andere kryptografische Mittel verwenden, um die Verbindung zwischen Server und Client zu sichern).

Wenn Sie jedoch nur Kennwörter verschlüsselt speichern müssen, empfehlen wir Ihnen, eine einfache XOR-Verschlüsselung zu verwenden. Das Hauptproblem bei diesem Algorithmus besteht darin, dass er durch Frequenzanalyse leicht beschädigt werden kann. Da Passwörter im Allgemeinen nicht aus langen Absätzen des englischen Textes bestehen, sollten Sie sich darüber keine Sorgen machen. Das zweite Problem mit XOR Cipher besteht darin, dass Sie bei einer verschlüsselten und entschlüsselten Nachricht leicht herausfinden können, mit welchem ​​Kennwort sie verschlüsselt wurde. Auch dies ist in Ihrem Fall kein großes Problem, da es nur den Benutzer betrifft, der bereits auf andere Weise kompromittiert wurde.


Wenn Sie in Antwort 3 sagen, dass Benutzer einen privaten Schlüssel haben, verstehe ich nicht, was das bedeutet. Sie empfehlen nicht, private Schlüssel manuell vom Benutzer an die Anwendung zu übergeben. Wie werden private Schlüssel sonst an die Anwendung übergeben?
HyderA

Nun, das ist ein kleines Problem. Der private Schlüssel kann in der Textdatei gespeichert und dann in die App eingefügt werden. Der Schlüssel kann auch auf dem Server gespeichert werden. In diesem Fall sollte er jedoch weiterhin mit einem anderen Verschlüsselungsalgorithmus wie XOR verschlüsselt werden. Die Verwendung von XOR hier ist in diesem Fall sicher genug, da es nur ein Passwort-Nachrichten-Paar gibt und die Nachricht ziemlich zufällig ist, sodass die Frequenzanalyse nicht kalt verwendet werden kann.
Ivan

4
Ich würde sicherlich nicht empfehlen, einen Verschlüsselungsalgorithmus selbst zu implementieren, da es zu viele potenzielle Fallstricke gibt und die vorhandenen Bibliotheken von vielen Menschen getestet und analysiert wurden.
Lange Ohren

Das Hauptproblem bei XOR besteht darin, dass jemand, der Ihre Anwendungsdaten stiehlt und nur eines der Kennwörter eines Benutzers kennt, alle anderen Kennwörter für diesen Benutzer entschlüsseln kann.
Lange Ohren

1
@Ivan: Ja, aber dies ist einer der Fälle, in denen ich denke, dass DIY wirklich sehr, sehr schlecht ist, es sei denn, Sie verstehen die Kryptographie WIRKLICH. Es gibt starke Chiffren, warum nicht?
Ircmaxell

13
  1. Die PHP-Funktion, nach der Sie suchen, ist Mcrypt ( http://www.php.net/manual/en/intro.mcrypt.php ).

Das Beispiel aus dem Handbuch wurde für dieses Beispiel leicht bearbeitet.

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$pass = "PasswordHere";
echo strlen($pass) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
?>

Sie würden mcrypt_decrypt verwenden , um Ihr Passwort zu entschlüsseln.

  1. Der beste Algorithmus ist eher subjektiv - fragen Sie 5 Personen, erhalten Sie 5 Antworten. Persönlich, wenn die Standardeinstellung (Blowfish) nicht gut genug für Sie ist, haben Sie wahrscheinlich größere Probleme!

  2. Angesichts der Tatsache, dass PHP es zum Verschlüsseln benötigt - nicht sicher, ob Sie es irgendwo verstecken können -, begrüßen Sie Kommentare dazu. Es gelten natürlich die üblichen Best-Coding-Praktiken für PHP!

  3. Da sich der Verschlüsselungsschlüssel ohnehin in Ihrem Code befindet, sind Sie sich nicht sicher, was Sie gewinnen werden, vorausgesetzt, der Rest Ihrer Anwendung ist sicher.

  4. Wenn das verschlüsselte Passwort und der Verschlüsselungsschlüssel gestohlen werden, ist das Spiel natürlich vorbei.

Ich würde meiner Antwort einen Fahrer hinzufügen - ich bin kein PHP-Krypto-Experte, aber ich denke, was ich beantwortet habe, ist Standardpraxis - ich begrüße Kommentare, die andere möglicherweise haben.


$pass = $text. Ich glaube, er hat das geändert, um der Frage gerecht zu werden, und das zweite Vorkommen nicht bemerkt.
HyderA

3
Zwei Dinge zu beachten. Erstens MCRYPT_MODE_ECBverwendet keine IV. Zweitens müssten Sie in diesem
Fall

"Der beste Algorithmus ist eher subjektiv - fragen Sie 5 Personen, erhalten Sie 5 Antworten. Wenn die Standardeinstellung (Blowfish) für Sie nicht gut genug ist, haben Sie wahrscheinlich größere Probleme!" Das ist völlig falsch. Jeder Krypto-Experte wird mehr oder weniger mit gist.github.com/tqbf/be58d2d39690c3b366ad einverstanden sein, das Blowfish ausdrücklich ausschließt
Scott Arciszewski

6

Viele Benutzer haben vorgeschlagen, mcrypt zu verwenden ... was richtig ist, aber ich gehe gerne noch einen Schritt weiter, um es einfach zu speichern und zu übertragen (da verschlüsselte Werte es manchmal schwierig machen, sie mit anderen Technologien wie curl oder json zu senden). .

Nachdem Sie erfolgreich mit mcrypt verschlüsselt haben, führen Sie es durch base64_encode aus und konvertieren Sie es dann in Hex-Code. Einmal im Hex-Code, ist es einfach, auf verschiedene Arten zu übertragen.

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $unencrypted);
$encrypted = $ua."||||".$iv;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encrypted = base64_encode($encrypted);
$encrypted = array_shift(unpack('H*', $encrypted));

Und auf der anderen Seite:

$encrypted = pack('H*', $encrypted);
$encrypted = base64_decode($encrypted);
list($encrypted,$iv) = explode("||||",$encrypted,2);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$unencrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);


2
Nun - es war im Jahr 2011: P
Bradley

5

Ich würde die Verschlüsselung mit öffentlichen Schlüsseln nur empfehlen, wenn Sie das Kennwort eines Benutzers ohne dessen Interaktion festlegen möchten (dies kann für Zurücksetzungen und freigegebene Kennwörter nützlich sein).

Öffentlicher Schlüssel

  1. Die OpenSSL- Erweiterung, speziell openssl_public_encryptundopenssl_private_decrypt
  2. Dies wäre eine reine RSA, vorausgesetzt, Ihre Passwörter passen in die Schlüsselgröße - Auffüllen, andernfalls benötigen Sie eine symmetrische Ebene
  3. Speichern Sie beide Schlüssel für jeden Benutzer. Die Passphrase des privaten Schlüssels ist das Anwendungskennwort

Symmetrisch

  1. Die Mcrypt- Erweiterung
  2. AES-256 ist wahrscheinlich eine sichere Wette, aber dies könnte eine SO-Frage an sich sein
  3. Sie nicht - dies wäre ihr Anwendungskennwort

Beide

4. Ja - Benutzer müssten jedes Mal ihr Anwendungskennwort eingeben, aber das Speichern in der Sitzung würde andere Probleme aufwerfen

5.

  • Wenn jemand die Anwendungsdaten stiehlt, sind diese genauso sicher wie die symmetrische Verschlüsselung (für das Schema des öffentlichen Schlüssels wird es verwendet, um den privaten Schlüssel mit der Passphrase zu schützen.)
  • Auf Ihre Anwendung sollte auf jeden Fall nur über SSL zugegriffen werden können, vorzugsweise mit Client-Zertifikaten.
  • Erwägen Sie, einen zweiten Faktor für die Authentifizierung hinzuzufügen, der nur einmal pro Sitzung verwendet wird, z. B. ein per SMS gesendetes Token.

Vermeiden Sie mcrypt, seien Sie vorsichtig mit openssl_private_decrypt().
Scott Arciszewski

2

Ich habe so etwas versucht, aber bitte beachten Sie, dass ich weder Kryptograf bin noch über fundierte Kenntnisse phpoder Programmiersprachen verfüge. Es ist nur eine Idee. Meine Idee ist es, keyin einer Datei zu speichern oder database(oder manuell einzugeben), welche (Speicherort) nicht leicht vorherzusagen ist (und natürlich wird eines Tages alles entschlüsselt, das Konzept besteht darin, die Entschlüsselungszeit zu verlängern) und vertrauliche Informationen zu verschlüsseln.

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "myemail@domain.com";
echo "Key : ".$key."<br/>";
echo "Text : ".$text . "<br/>";
echo "Md5 : ".md5($text). "<br/>";
echo "Sha1 : ".sha1($text). "<br/>";



$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH , $key, $text, MCRYPT_MODE_ECB, $iv);
echo "Crypted Data : ".$crypttext."<br>";

$base64 = base64_encode($crypttext);
echo "Encoded Data : ".$base64."<br/>";
$decode =  base64_decode($base64);


$decryptdata = mcrypt_decrypt(MCRYPT_BLOWFISH , $key, $crypttext, MCRYPT_MODE_ECB, $iv);

echo "Decoded Data : ".ereg_replace("?", null ,  $decryptdata); 
//event if i add '?' to the sting to the text it works, I don't know why.

Bitte beachten Sie, dass es sich nur um ein Konzept handelt. Jede Verbesserung dieses Codes wäre sehr bemerkenswert.


2

Die Passwörter gelten für ein Hardwaregerät, sodass eine Überprüfung auf Hashes nicht in Frage kommt

Eh? Ich verstehe nicht. Meinen Sie nur, dass das Passwort wiederherstellbar sein muss?

Wie andere bereits gesagt haben, bietet die mcrypt-Erweiterung Zugriff auf viele kryptografische Funktionen. Sie laden Ihre Benutzer jedoch ein, alle Eier in einen Korb zu legen - einen, der möglicherweise ein Ziel für Angreifer ist - und wenn Sie es nicht einmal wissen Wenn Sie anfangen, das Problem zu lösen, tun Sie Ihren Benutzern einen schlechten Dienst. Sie sind nicht in der Lage zu verstehen, wie die Daten geschützt werden.

Die meisten Sicherheitslücken entstehen nicht, weil der zugrunde liegende Algorithmus fehlerhaft oder unsicher ist, sondern aufgrund von Problemen bei der Verwendung des Algorithmus im Anwendungscode.

Trotzdem ist es möglich , ein einigermaßen sicheres System aufzubauen.

Sie sollten eine asymmetrische Verschlüsselung nur in Betracht ziehen, wenn ein Benutzer eine sichere Nachricht erstellen muss, die von einem anderen (bestimmten) Benutzer gelesen werden kann. Der Grund dafür ist, dass es rechenintensiv ist. Wenn Sie nur ein Repository bereitstellen möchten, in das Benutzer ihre eigenen Daten eingeben und abrufen können, ist eine symmetrische Verschlüsselung ausreichend.

Wenn Sie jedoch den Schlüssel zum Entschlüsseln der Nachricht an derselben Stelle wie die verschlüsselte Nachricht speichern (oder wo die verschlüsselte Nachricht gespeichert ist), ist das System nicht sicher. Verwenden Sie zur Authentifizierung des Benutzers dasselbe Token wie für den Entschlüsselungsschlüssel (oder verwenden Sie bei assymetrischer Verschlüsselung das Token als Passphrase für den privaten Schlüssel). Da Sie das Token auf dem Server speichern müssen, auf dem die Entschlüsselung zumindest vorübergehend erfolgt, sollten Sie ein nicht durchsuchbares Sitzungsspeichersubstrat verwenden oder das Token direkt an einen Daemon übergeben, der der Sitzung zugeordnet ist, in der das Token gespeichert wird Token im Speicher und führen Sie die Entschlüsselung von Nachrichten bei Bedarf durch.


1

Verwenden Sie password_hash und password_verify

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

Und um zu entschlüsseln:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.